面向对象object-oriented
"""
面向对象思考流程:
现实世界 软件世界
客观事物 app(滴滴打车)
汽车 --抽象化--> 类 --具体化--> 对象
品牌 奔驰
车牌 007
颜色 白色
...
"""
class 类名:
"""
文档说明
"""
def __init__(self,参数):
self.实例变量 = 参数
方法(函数)成员
说明: 类名所有单词首字母大写。init 也叫构造函数,创建对象时被调用,也可以省略。
self变量绑定的是被创建的对象,名称可以随意,但不会改,行业默认。
变量 = 类名(参数) #即创建对象(自动调用__init__)
变量存储的是实例化后的对象地址,类名后面的参数按照构造函数的形参传递
举例
alt+enter 弹出创建参数,自动补充def后面的参数
class Wife:
# 数据
def __init__(self, name, age=18, face_score=60):
self.name = name
self.age = age # (输入完,alt+enter 弹出创建参数age,自动补充def后面的参数)
self.face_score =face_score
# ....
# 行为-方法函数
def work(self):
print(self.name + "working")
# 实例化
# 创建对象(自动调用__init__)
shuang_er = Wife("双儿", 23, 93)
# 读取对象数据
print(shuang_er.name) #输出 双儿
# 调用对象方法
shuang_er.work() # 输出 双儿working
#创建新的对象
jian_ning = Wife("建宁")
# 修改对象数据
print(jian_ning.face_score) #60
jian_ning.face_score = 95
print(jian_ning.face_score) #90
"""
练习:创建手机类,实例化两个对象并调用其函数,
数据:品牌、价格、颜色
行为:通话
"""
# 类明:所有单词首字母大写,不用下划线分割
class MobilePhone:
def __init__(self, brand, price=0, color=""):
self.brand = brand
self.price = price
self.color = color # alt + 回车
def call(self):
print(self.brand, "在通话")
huawei = MobilePhone("华为", 8000, "白色")
iphone = MobilePhone("苹果", color = "黑色")
print(huawei.price) #8000
huawei.call() #华为 在通话
iphone.call() #华为 在通话
"""
实例成员
实例变量:表达不同个体的不同数据
语法:对象.变量名
实例方法:操作实例变量
语法:
def 方法名(self,参数):
方法体
对象.方法名(数据)
"""
class Wife:
def __init__(self, name=""):
# 创建实例变量
self.name = name
# 实例方法
def work(self):
print(self.name + "在工作")
#创建
shuang_er = Wife("双儿")
# 修改实例变量
shuang_er.name = "双双"
# 读取实例变量
print(shuang_er.name)
# __dict__ 存储所有实例变量
print(shuang_er.__dict__) # {'name': '双双'}
# 通过对象访问实例方法
shuang_er.work() # work(shuang_er)
# 不建议在类外创建实例变量
class Wife:
pass
shuang_er = Wife()
# 创建实例变量
shuang_er.name = "双双"
# 读取实例变量
print(shuang_er.name)
# __dict__ 存储所有实例变量
print(shuang_er.__dict__) # {'name': '双双'}
# 不建议在__init__外创建实例变量
class Wife:
def set_name(self, name):
# 创建实例变量
self.name = name
shuang_er = Wife()
shuang_er.set_name("双双")
print(shuang_er.name)
print(shuang_er.__dict__)
练习
"""
创建狗类
数据:
品种、昵称、身长、体重
行为:
吃(体重增长1)
实例化两个对象并调用其函数
"""
class Dog:
def __init__(self, species="", pet_name="", height=0.0, weight=0):
self.species = species
self.pet_name = pet_name
self.height = height
self.weight = weight
self.eat()
def eat(self):
self.weight += 1
print("吃饭饭~") #不创建对象是不会打印,创建时会打印一次,
mi_xiu = Dog("拉布拉多", "米咻", 0.6, 60) #打印出 吃饭饭~
print(mi_xiu.weight) # 61
mi_xiu.eat() # eat(mi_xiu) #使用时打印 吃饭饭~
print(mi_xiu.weight) #61
练习
class Wife:
def __init__(self, name, age=20):
self.name = name
self.age = age
# 练习1:
person01 = Wife("双儿", 23) #创建了内存地址
person02 = person01 #给person02赋值了内存地址
person01.name = "双双"
print(person02.name) # 打印出双双
# 练习2:
def func01(p1, p2):
p1.name = "双双"
p2 = Wife("宁宁", 26)
person01 = Wife("双儿", 23)
person02 = Wife("建宁", 25)
func01(person01, person02) #p1产生修改 p2在栈帧内指向新地址("宁宁", 26),栈帧执行完销毁
print(person01.name) # 双双
print(person02.name) # 建宁
# 练习3:
person01 = Wife("双儿", 23)
list_wifes = [
person01,
Wife("建宁", 25),
Wife("阿珂", 22),
]
def func01(p1):
p1[0].name = "双双"
p1[1] = Wife("宁宁", 25)
p1[2] = "珂珂"
func01(list_wifes)
print(list_wifes[0].name) #双双
print(list_wifes[1].name) #宁宁
print(list_wifes[2]) #珂珂,整个p1[2]被修改成珂珂(就没.mame可调用打印了)
"""
定义函数,在老婆列表中查找,姓名是阿珂的老婆.
定义函数,在老婆列表中查找,年龄大于25岁的所有老婆.
定义函数,在老婆列表中查找,查找颜值小于95的所有老婆姓名.
定义函数,累加所有老婆的年龄
定义函数,在老婆列表中查找,年龄最大的老婆
定义函数,根据颜值对老婆列表生序排列
"""
# -------------类----------------
class Wife:
def __init__(self, name, age=20, face_score=60):
self.name = name
self.age = age
self.face_score = face_score
# -------------全局变量----------------
list_wifes = [
Wife("双儿", 23, 93),
Wife("建宁", 26, 91),
Wife("阿珂", 22, 100),
Wife("苏荃", 32, 92),
]
# -------------函数----------------
# 定义函数,在老婆列表中查找,姓名是阿珂的老婆.
def find_single_wife_by_name():
for item in list_wifes:
if item.name == "阿珂":
return item
# 定义函数,在老婆列表中查找,年龄大于25岁的所有老婆.
def find_all_wife_by_age():
list_result = []
for item in list_wifes:
if item.age > 25:
list_result.append(item)
return list_result
# 定义函数,在老婆列表中查找,查找颜值小于95的所有老婆姓名.
def find_all_name_by_face_score():
list_result = []
for item in list_wifes:
if item.face_score < 95:
list_result.append(item.name)
return list_result
# 定义函数,累加所有老婆的年龄
def sum_age():
result = 0
for item in list_wifes:
result += item.age
return result
# 定义函数,在老婆列表中查找,年龄最大的老婆
def get_max_by_age():
max_value = list_wifes[0]
for i in range(1, len(list_wifes)):
if max_value.age < list_wifes[i].age:
max_value = list_wifes[i]
return max_value
# 定义函数,根据颜值对老婆列表生序排列
def order_by_face_score():
for r in range(len(list_wifes) - 1):
for c in range(r + 1, len(list_wifes)):
if list_wifes[r].face_score > list_wifes[c].face_score:
list_wifes[r], list_wifes[c] = list_wifes[c], list_wifes[r]
# -------------调用----------------
a_ke = find_single_wife_by_name()
# 建议通过__dict__查看自定义对象的数据
print(a_ke) #<__main__.Wife object at 0x000001B5355B4EE0>,这个是内存地址。__dict__完成实例对象变量调用
print(a_ke.__dict__) #{'name': '阿珂', 'age': 22, 'face_score': 100}
list_result = find_all_wife_by_age()
# 建议通过断点查看自定义对象的列表
print(list_result) #[<__main__.Wife object at 0x000001D891474F70>, <__main__.Wife object at 0x000001D891474E20>]
# for item in list_result:
# print(item.__dict__) #{'name': '建宁', 'age': 26, 'face_score': 91}
#{'name': '苏荃', 'age': 32, 'face_score': 92}
list_names = find_all_name_by_face_score()
print(list_names) #['双儿', '建宁', '苏荃']
total_age = sum_age()
print(total_age) #103
value = get_max_by_age()
print(value.__dict__) #{'name': '苏荃', 'age': 32, 'face_score': 92}
order_by_face_score()
print(list_wifes) #[<__main__.Wife object at 0x000001BF22D24F70>, <__main__.Wife object at 0x000001BF22D24E20>, <__main__.Wife object at 0x000001BF22D24FD0>, <__main__.Wife object at 0x000001BF22D24EE0>]
面向过程->面向对象
"""
面向过程->面向对象 抽象化过程
list_commodity_infos = [
{"cid": 1001, "name": "屠龙刀", "price": 10000},
{"cid": 1002, "name": "倚天剑", "price": 10000},
{"cid": 1003, "name": "金箍棒", "price": 52100},
{"cid": 1004, "name": "口罩", "price": 20},
{"cid": 1005, "name": "酒精", "price": 30},
]
"""
class Commodity:
def __init__(self, cid=0, name="", price=0):
self.cid = cid
self.name = name
self.price = price
list_commodity_infos = [
Commodity(1001, "屠龙刀", 10000),
Commodity(1002, "倚天剑", 10000),
Commodity(1003, "金箍棒", 52100),
Commodity(1004, "口罩", 20),
Commodity(1005, "酒精", 30),
]
def print_single_commodity(commodity):
print(f"编号:{commodity.cid},商品名称:{commodity.name},商品单价:{commodity.price}")
print_single_commodity(list_commodity_infos[0]) #编号:1001,商品名称:屠龙刀,商品单价:10000
print_single_commodity(list_commodity_infos[1]) #编号:1002,商品名称:倚天剑,商品单价:10000
将面向过程代码改为面向对象代码
"""
#商品列表
list_commodity_infos = [
{"cid": 1001, "name": "屠龙刀", "price": 10000},
{"cid": 1002, "name": "倚天剑", "price": 10000},
{"cid": 1003, "name": "金箍棒", "price": 52100},
{"cid": 1004, "name": "口罩", "price": 20},
{"cid": 1005, "name": "酒精", "price": 30},
]
# 订单列表
list_orders = [
{"cid": 1001, "count": 1},
{"cid": 1002, "count": 3},
{"cid": 1005, "count": 2},
]
def print_single_commodity(commodity):
print(f"编号:{commodity['cid']},商品名称:{commodity['name']},商品单价:{commodity['price']}")
# 1. 定义函数,打印所有商品信息,格式:商品编号xx,商品名称xx,商品单价xx.
def print_commodity_infos():
for commodity in list_commodity_infos:
print_single_commodity(commodity)
# 2. 定义函数,打印商品单价小于2万的商品信息
def print_price_in_2w():
for commodity in list_commodity_infos:
if commodity["price"] < 20000:
print_single_commodity(commodity)
# 3. 定义函数,打印所有订单中的商品信息,
def print_order_infos():
for order in list_orders:
for commodity in list_commodity_infos:
if order["cid"] == commodity["cid"]:
print(f"商品名称{commodity['name']},商品单价:{commodity['price']},数量{order['count']}.")
break # 跳出内层循环
# 4. 查找最贵的商品(使用自定义算法,不使用内置函数)
def commodity_max_by_price():
max_value = list_commodity_infos[0]
for i in range(1, len(list_commodity_infos)):
if max_value["price"] < list_commodity_infos[i]["price"]:
max_value = list_commodity_infos[i]
return max_value
# 5. 根据单价对商品列表降序排列
def descending_order_by_price():
for r in range(len(list_commodity_infos) - 1):
for c in range(r + 1, len(list_commodity_infos)):
if list_commodity_infos[r]["price"] < list_commodity_infos[c]["price"]:
list_commodity_infos[r], list_commodity_infos[c] = list_commodity_infos[c], list_commodity_infos[r]
"""
class Commodity:
def __init__(self, cid, name, price):
self.cid = cid
self.name = name
self.price = price
class Order:
def __init__(self, cid, count):
self.cid = cid
self.count = count
list_commodity_infos = [
Commodity(1001, "屠龙刀", 10000),
Commodity(1002, "倚天剑", 10000),
Commodity(1003, "金箍棒", 52100),
Commodity(1004, "口罩", 20),
Commodity(1005, "酒精", 30),
]
list_orders = [
Order(1001, 1),
Order(1002, 3),
Order(1005, 2),
]
def print_single_commodity(commodity):
print(f"编号:{commodity.cid},商品名称:{commodity.name},商品单价:{commodity.price}")
# 1. 定义函数,打印所有商品信息,格式:商品编号xx,商品名称xx,商品单价xx.
def print_commodity_infos():
for commodity in list_commodity_infos:
print_single_commodity(commodity)
def print_price_in_2w():
for commodity in list_commodity_infos:
if commodity.price < 20000:
print_single_commodity(commodity)
# 3. 定义函数,打印所有订单中的商品信息,
def print_order_infos():
for order in list_orders:
for commodity in list_commodity_infos:
if order.cid == commodity.cid:
print(f"商品名称{commodity.name},商品单价:{commodity.price},数量{order.count}.")
break
# 4. 查找最贵的商品(使用自定义算法,不使用内置函数)
def commodity_max_by_price():
max_value = list_commodity_infos[0]
for i in range(1, len(list_commodity_infos)):
if max_value.price < list_commodity_infos[i].price:
max_value = list_commodity_infos[i]
return max_value
# 5. 根据单价对商品列表降序排列
def descending_order_by_price():
for r in range(len(list_commodity_infos) - 1):
for c in range(r + 1, len(list_commodity_infos)):
if list_commodity_infos[r].price < list_commodity_infos[c].price:
list_commodity_infos[r], list_commodity_infos[c] = list_commodity_infos[c], list_commodity_infos[r]
# -------------调用----------------
print_commodity_infos()
print_price_in_2w()
print_order_infos()
cmd = commodity_max_by_price()
print(cmd.__dict__)
descending_order_by_price()
print(list_commodity_infos)
"""
跨类调用
为什么创建类?
因为类需要包装多个数据,承担相应行为.
如何跨类调用?
直接创建对象,构造函数中创建对象,参数传递对象
"""
# 需求:请使用面向对象思想,描述下列情景.
# -- 老张开车去东北,抽象成Person人物去哪,Car方式
class Person:
def __init__(self, name=""):
self.name = name
def go_to(self, position):
print("去" + position)
class Car:
def run(self):
print("汽车在行驶")
# 语义:老张每次去东北,都开一辆新车(每次都会创建车).
class Person:
def __init__(self, name=""):
self.name = name
def go_to(self, position):
print("去" + position)
car = Car() #直接调用下面的Car类,创建对象
car.run()
class Car:
def run(self):
print("汽车在行驶")
zl = Person("老张")
zl.go_to("东北") #去东北\n汽车在行驶
# 语义:老张去东北,开自己的车(随老张的构建产生)
class Person:
def __init__(self, name=""):
self.name = name
self.car = Car() #随老张的构建产生,不会在每次go_to的时候创建新的
def go_to(self, position):
print("去" + position)
self.car.run()
class Car:
def run(self):
print("汽车在行驶")
zl = Person("老张")
zl.go_to("东北")
# 语义: 老张通过交通工具(传参vehicle)去东北
class Person:
def __init__(self, name=""):
self.name = name
def go_to(self, position, vehicle):
print("去" + position)
vehicle.run()
class Car:
def run(self):
print("汽车在行驶")
# 在使用时创建,传递参数
zl = Person("老张")
car = Car() #创建car对象
zl.go_to("东北", car) #传递参数进去
"""
练习1:以面向对象思想,描述下列情景.
小明请保洁打扫卫生
"""
# 语义:小明每次通知新保洁员打扫卫生
"""
class Client:
def __init__(self, name=""):
self.name = name
def notify(self):
print("发出通知")
cleaner = Cleaner()
cleaner.cleaning()
class Cleaner:
def cleaning(self):
print("打扫卫生")
xm = Client("小明")
xm.notify()
"""
# 语义:小明每次通知自己的保洁员打扫卫生
"""
class Client:
def __init__(self, name=""):
self.name = name
self.cleaner = Cleaner()
def notify(self):
print("发出通知")
self.cleaner.cleaning()
class Cleaner:
def cleaning(self):
print("打扫卫生")
xm = Client("小明")
xm.notify()
"""
# 语义:小明每次通知自己的保洁员打扫卫生
class Client:
def __init__(self, name=""):
self.name = name
def notify(self, server):
print("发出通知")
server.cleaning()
class Cleaner:
def cleaning(self):
print("打扫卫生")
xm = Client("小明")
cleaner = Cleaner()
xm.notify(cleaner)
练习
"""
1. 定义函数,打印所有员工信息,格式:xx的员工编号是xx,部门编号是xx,月薪xx元.
2. 定义函数,打印所有月薪大于2w的员工信息,格式:xx的员工编号是xx,部门编号是xx,月薪xx元.
3. 定义函数,打印所有员工的部门信息,格式:xx的部门是xx,月薪xx元.
4. 定义函数,查找薪资最少的员工
5. 定义函数,根据薪资对员工列表升序排列
*6.定义函数,计算所有员工总薪资
*7.定义函数,获取所有员工姓名
结果:["师父","孙悟空","猪八戒","沙僧","小白龙"]
# 员工列表
list_employees = [
{"eid": 1001, "did": 9002, "name": "师父", "money": 60000},
{"eid": 1002, "did": 9001, "name": "孙悟空", "money": 50000},
{"eid": 1003, "did": 9002, "name": "猪八戒", "money": 20000},
{"eid": 1004, "did": 9001, "name": "沙僧", "money": 30000},
{"eid": 1005, "did": 9001, "name": "小白龙", "money": 15000},
]
# 部门列表
list_departments = [
{"did": 9001, "title": "教学部"},
{"did": 9002, "title": "销售部"},
]
"""
# -------------类--------------
class Employee:
def __init__(self, eid, did, name, money):
self.eid = eid
self.did = did
self.name = name
self.money = money
class Department:
def __init__(self, did, title):
self.did = did
self.title = title
# -------------全局变量--------------
# 员工列表
list_employees = [
Employee(1001, 9002, "师父", 60000),
Employee(1002, 9001, "孙悟空", 50000),
Employee(1003, 9002, "猪八戒", 20000),
Employee(1004, 9001, "沙僧", 30000),
Employee(1005, 9001, "小白龙", 15000),
]
# 部门列表
list_departments = [
Department(9001, "教学部"),
Department(9002, "销售部")
]
# -------------函数--------------
# 1. 定义函数,打印所有员工信息,格式:xx的员工编号是xx,部门编号是xx,月薪xx元.
def print_employee_info(emp):
print(f"{emp.name}的员工编号是{emp.eid},部门编号是{emp.did},月薪{emp.money}元.")
def print_employee_infos():
for emp in list_employees:
print_employee_info(emp)
# 2. 定义函数,打印所有月薪大于2w的员工信息,格式:xx的员工编号是xx,部门编号是xx,月薪xx元.
def print_employees_gt_2w():
for emp in list_employees:
if emp.money > 20000:
print_employee_info(emp)
# 3. 定义函数,打印所有员工的部门信息,格式:xx的部门是xx,月薪xx元.
def print_employees_for_department():
# 取员工
for emp in list_employees:
# 找部门
for dep in list_departments:
if emp.did == dep.did:
print(f"{emp.name}的部门是{dep.title},月薪{emp.money}元.")
break
# 4. 查找薪资最少的员工
def employee_min_by_money():
min_value = list_employees[0]
for i in range(1, len(list_employees)):
if min_value.money > list_employees[i].money:
min_value = list_employees[i]
return min_value
# 5. 根据薪资对员工列表降序排列
def ascending_employee_by_money():
for r in range(len(list_employees) - 1):
for c in range(r + 1, len(list_employees)):
if list_employees[r].money < list_employees[c].money:
list_employees[r], list_employees[c] = list_employees[c], list_employees[r]
# 6.定义函数, 计算所有员工总薪资
def calculate_total_money():
total_money = 0
for item in list_employees:
total_money += item.money
return total_money
# 7.定义函数,获取所有员工姓名
def get_all_name():
list_name = []
for item in list_employees:
list_name.append(item.name)
return list_name
# -------------入口--------------
result01 = get_all_name()
# 返回的是Python自带类型,可以直接打印
print(result01) #['师父', '孙悟空', '猪八戒', '沙僧', '小白龙']
result02 = calculate_total_money()
print(result02) #175000
ascending_employee_by_money()
print(list_employees) #返回地址
result04 = employee_min_by_money()
# 返回的是自定义类型,打印 __dict__
print(result04.__dict__) #{'eid': 1005, 'did': 9001, 'name': '小白龙', 'money': 15000}
# 内部直接显示结果,无需接收返回值
print_employees_for_department() #师父的部门是销售部,月薪60000元.孙悟空的...
复习-跨类调用
1. 为什么创建类?
有多个数据需要包装
有行为需要承担
2. 为什么创建多个类?
根据变化点,分担多个职责.
3. 划分职责的原则:
行为不同用类区分,数据不同用对象区分
老张类 开车类
驾驶方法 行驶方法
张无忌对象 赵敏对象
教
4. 语法
--1. 直接创建对象
class A:
def func01():
b = B()
b.func02()
class B:
def func02():
pass
--2. 在构造函数中创建对象
class A:
def __init__():
self.b = B()
def func01():
self.b.func02()
class B:
def func02():
pass
--3. 通过参数传递对象
class A:
def func01(c):
c.func02()
class B:
def func02():
pass
a = A()
a.func01( B() )
"""
练习2:以面向对象思想,描述下列情景.
玩家攻击敌人,敌人受伤(头顶爆字).
"""
class Player:
def attack(self,target):
print("发起攻击")
target.damage() # 跨类调用
class Enemy:
def damage(self):
print("头顶爆字")
p = Player()
e = Enemy()
p.attack(e) #发起攻击\n头顶爆字
"""
练习4:以面向对象思想,描述下列情景.
张无忌教赵敏九阳神功
赵敏教张无忌玉女心经
张无忌工作挣了5000元
赵敏工作挣了10000元
思想:张无忌与赵敏行为相同
"""
class Person:
def __init__(self, name=""):
self.name = name
def teach(self, other, skill):
print(self.name, "教", other.name, skill)
def work(self, money):
print(self.name, "工作挣了", money)
# 对象区分数据不同
zwj = Person("张无忌")
zm = Person("赵敏")
zwj.teach(zm, "九阳神功") #张无忌 教 赵敏 九阳神功
zm.teach(zwj, "玉女心经") #赵敏 教 张无忌 玉女心经
zwj.work(5000) #张无忌 工作挣了 5000
zm.work(10000) #赵敏 工作挣了 10000
Player调Enemy
"""
在玩家攻击敌人时,传递数据
以面向对象思想,描述下列情景.
玩家(攻击力)攻击敌人(血量),
敌人受伤(减血,头顶爆字,还有可能死亡).
"""
"""
class Player:
def attack(self,target): # 2
print("发起攻击")
target.damage()
class Enemy:
def damage(self): # 3 # ?
print("头顶爆字")
p = Player()
e = Enemy()
# 由使用决定Player调用Enemy
p.attack(e)# 1
"""
"""
class Player:
def __init__(self, atk=0):
self.atk = atk
def attack(self, target):
print("发起攻击")
target.damage(self) # 将玩家传入到敌人类中
class Enemy:
def __init__(self, hp=0):
self.hp = hp
def damage(self, other):
self.hp -= other.atk #调用玩家atk使用
print("头顶爆字")
if self.hp <= 0:
self.death()
def death(self):
print("掉金币")
p = Player(50)
e = Enemy(100)
p.attack(e)
p.attack(e)
"""
class Player:
def __init__(self, atk=0):
self.atk = atk
def attack(self, target):
print("发起攻击")
target.damage(self.atk) # 将玩家的攻击力传入到敌人类中
class Enemy:
def __init__(self, hp=0):
self.hp = hp
def damage(self, value):
self.hp -= value #直接使用atk
print("头顶爆字")
if self.hp <= 0:
self.death() #同一个类里调用self.
def death(self):
print("掉金币")
p = Player(50)
e = Enemy(100)
p.attack(e)
p.attack(e)
发起攻击
头顶爆字
发起攻击
头顶爆字
掉金币
"""
以面向对象思想,描述下列情景.
练习:
玩家(攻击力)攻击敌人(血量),
敌人受伤(减血,头顶爆字,还有可能死亡[掉金币]).
敌人(攻击力)攻击玩家(血量),
玩家受伤(减血,碎屏,还有可能死亡[游戏结束]).
"""
class Player:
def __init__(self, hp=0, atk=0):
self.atk = atk
self.hp = hp
def attack(self, target):
print("发起攻击")
target.damage(self.atk)
def damage(self, value):
print("碎屏")
self.hp -= value
if self.hp <= 0:
self.death()
def death(self):
print("游戏结束")
class Enemy:
def __init__(self, hp=0, atk=0):
self.hp = hp
self.atk = atk
def damage(self, value):
self.hp -= value
print("头顶爆字")
if self.hp <= 0:
self.death()
def death(self):
print("掉金币")
def attack(self, target):
print("发起攻击")
target.damage(self.atk)
p = Player(500, 50)
e = Enemy(100, 20)
# 玩家打一次敌人
p.attack(e)
# 敌人打一次玩家
e.attack(p)
print("玩家血量:", p.hp)
print("敌人血量:", e.hp)
发起攻击
头顶爆字
发起攻击
碎屏
玩家血量: 480
敌人血量: 50
MVC模型(model view controller),数据模型类、界面视图类、逻辑控制类。
分配职责:
界面视图类:负责处理界面逻辑,比如显示菜单,获取输入,显示结果等。
逻辑控制类:负责存储学生信息,处理业务逻辑。比如添加、删除等
数据模型类:定义需要处理的数据类型。比如学生信息。
行业默认格式
class xxxView:
def ...:
class xxxController:
def ...:
class xxxModel:
def ...:
# 入口
view = StudentView()
view.main()
class内的设计步骤
第一步:定义功能函数若干,同时进行
第二步:创建调用连接
第三步:数据传递调用
学生信息管理系统MVC
class StudentModel:
class StudentView:
"""
学生视图:输入/输出学生信息
"""
class StudentController:
"""
学生控制器:处理核心功能,存储...
"""
# 入口
view = StudentView()
view.main()
alt + 回车: 代码生成快捷键。先写出调用函数代码,再将光标停留在函数上alt + 回车快捷键生成定义函数代码
class StudentModel:
def __init__(self, name="", age=0, score=0.0, sid=0):
self.name = name
self.age = age
self.score = score
# 由系统决定的全球唯一标识符(不是用户输入的)
self.sid = sid
class StudentView:
"""
学生视图:输入/输出学生信息
"""
def __init__(self):
self.controller = StudentController() #第二步:创建调用连接
def display_menu(self):
print("按1键录入学生信息")
print("按2键显示学生信息")
print("按3键删除学生信息")
print("按4键修改学生信息")
print("按5键根据成绩显示学生信息")
def select_menu(self):
item = input("请输入选项:")
if item == "1":
self.input_student()
elif item == "2":
# 先写出调用函数代码,再选中函数alt + 回车快捷键生成定义函数代码
self.display_students()
elif item == "3":
self.delete_student()
elif item == "4":
self.set_student()
elif item == "5":
self.order_by_score()
def input_student(self):#第一步:定义功能函数若干
stu = StudentModel()
stu.name = input("请输入学生姓名:")
stu.age = int(input("请输入学生年龄:"))
stu.score = int(input("请输入学生成绩:"))
self.controller.add_student(stu) #第三步:数据传递调用,然后去StudentController()执行add_student()
def main(self): #让入口一直使用
while True:
self.display_menu()
self.select_menu()
def display_students(self):
for item in self.controller.list_student:
print(f"{item.name}的编号是{item.sid},年龄是{item.age},成绩是{item.score}")
def delete_student(self):
sid = int(input("请输入需要删除的学生编号:"))
if self.controller.remove_student(sid):
print("删除成功")
else:
print("删除失败")
def set_student(self):
stu = StudentModel()
stu.sid = input("请输入学生编号:")
stu.name = input("请输入学生姓名:")
stu.age = int(input("请输入学生年龄:"))
stu.score = int(input("请输入学生成绩:"))
if self.controller.update_student(stu):
print("修改成功")
else:
print("修改失败")
def order_by_score(self):
self.controller.ascending_order()
self.display_students()
class StudentController:
"""
学生控制器:处理核心功能,存储...
"""
def __init__(self):
self.start_id = 100
self.list_student = []
def add_student(self, new_stu):
# 设置学生编号(自增长)
self.start_id += 1
new_stu.sid = self.start_id
# 追加到列表中
self.list_student.append(new_stu)
def remove_student(self, sid):
"""
在列表中删除学生信息
:param sid: 学生编号
:return: 是否成功
"""
for i in range(len(self.list_student)):
if self.list_student[i].sid == sid:
del self.list_student[i]
return True # 删除成功
return False # 删除失败
def update_student(self, stu):
"""
:param stu:
:return:
"""
for i in range(len(self.list_student)):
if self.list_student[i].sid == stu.sid:
# self.list_student[i].name = stu.name
# self.list_student[i].age = stu.age
# self.list_student[i].score = stu.score
self.list_student[i].__dict__ = stu.__dict__
return True
return False
def ascending_order(self):
for r in range(len(self.list_student) - 1):
for c in range(r + 1, len(self.list_student)):
if self.list_student[r].score > self.list_student[c].score:
self.list_student[r], self.list_student[c] = self.list_student[c], self.list_student[r]
# 入口
view = StudentView()
view.main()
练习
练习:商品信息管理系统
商品名称
商品单价
商品编号
(1)输入商品信息
V:显示菜单,选择菜单,获取信息
C:添加信息
M:商品模型
(2)添加商品信息
C:在add_commodity方法中设置cid
追加到列表中
(3)显示商品信息
V:选择菜单,打印商品列表
(4)删除商品信息
V:选择菜单,获取编号/显示成功或失败
C:移除信息
(5)修改商品信息
V:选择菜单,获取信息/显示成功或失败
C:修改信息
(6)根据单价升序排列
V:选择菜单,调用C的排序算法,显示商品
C:排序算法
"""
商品信息管理系统
"""
#按需求依次写,这里是完整的代码
class CommodityModel:
"""
商品模型:包装具体商品信息
"""
def __init__(self, name="", price=0, cid=0):
self.name = name
self.price = price
self.cid = cid
class CommodityView:
"""
商品视图:处理商品界面逻辑,例如:输入输出商品信息
"""
def __init__(self):
self.controller = CommodityController()
def display_menu(self):
print("按1键录入商品信息")
print("按2键显示商品信息")
print("按3键删除商品信息")
print("按4键修改商品信息")
print("按5键根据单价对商品信息排序")
def select_menu(self):
item = input("请输入选项:")
if item == "1":
self.input_commodity()
elif item == "2":
self.display_commoditys()
elif item == "3":
self.delete_commodity()
elif item == "4":
self.set_commodity()
def input_commodity(self):
cmd = CommodityModel()
cmd.name = input("请输入商品名称:")
cmd.price = int(input("请输入商品单价:"))
self.controller.add_commodity(cmd)
def main(self):
while True:
self.display_menu()
self.select_menu()
def display_commoditys(self):
for item in self.controller.list_commodity:
print("%s的编号是%s,单价是%s" % (item.name, item.cid, item.price))
def delete_commodity(self):
cid = int(input("请输入需要删除的编号:"))
if self.controller.remove_commodity(cid):
print("删除成功")
else:
print("删除失败")
def set_commodity(self):
cmd = CommodityModel()
cmd.cid = int(input("请输入商品编号:"))
cmd.name = input("请输入商品名称:")
cmd.price = int(input("请输入商品单价:"))
if self.controller.update_commodity(cmd):
print("修改成功")
else:
print("修改失败")
class CommodityController:
"""
商品控制器:处理商品业务逻辑,例如:存储信息
"""
def __init__(self):
self.start_id = 100
self.list_commodity = []
def add_commodity(self, new_cmd):
new_cmd.cid = self.start_id
self.start_id += 1
self.list_commodity.append(new_cmd)
def remove_commodity(self, cid):
"""
:param cid:
:return:
"""
for i in range(len(self.list_commodity)):
if self.list_commodity[i].cid == cid:
del self.list_commodity[i]
return True
return False
def update_commodity(self, cmd):
""""""
for i in range(len(self.list_commodity)):
if self.list_commodity[i].cid == cmd.cid:
self.list_commodity[i].__dict__ = cmd.__dict__
return True
return False
view = CommodityView()
view.main()
(1) 定义:在类中,方法外。
class 类名:
变量名 = 数据
(2) 调用:
类名.变量名 # 不建议通过对象访问类变量
(3) 特点:
随类的加载而加载,存在优先于对象,只有一份,被所有对象共享。
(4) 作用:描述所有对象的共有数据。
(1) 定义:
@classmethod
def 方法名称(cls,参数):
方法体
(2) 调用: 类名.方法名(参数) # 不建议通过对象访问类方法
"""
小结 - Python语言变量
"""
# 全局变量:整个文件可见
data01 = 1
def func01():
# 局部变量:一个函数内部可见
data02 = 2
class MyClass:
# 类变量:通过类访问
data04 = 4
def __init__(self):
# 实例变量:通过对象访问
self.data03 = 3
# 局部变量:一个函数内部可见
data05 = 5
class MyClass:
data01 = 1 # 类变量,随类的加载而加载
def __init__(self):
self.data02 = 2 # 实例变量,使用时存放到栈帧中
MyClass.data01 += 1
self.data02 += 1
m01 = MyClass()# data02:2->3 data01:1-2
m02 = MyClass()# data02:2->3 data01:2-3
print(m02.data02) # 3
print(MyClass.data01) # 3
至少有一个形参,第一个形参用于绑定类,一般命名为'cls'
使用@classmethod修饰的目的是调用类方法时可以隐式传递类。
类方法中不能访问实例成员,实例方法中可以访问类成员。
class ICBC:
"""
工商银行
"""
# 类变量:表达不同个体相同数据 [总行(大家的)]
total_money = 1000000
# 实例方法
"""
def print_total_money(cls):
print("总行的钱:", ICBC.total_money)
"""
def __init__(self, name="", money=0):
# 实例变量:表达不同个体不同数据 [支行(自己的)]
self.name = name
self.money = money
# 支行创建时,总行的钱减少
ICBC.total_money -= self.money
# 类方法
@classmethod
def print_total_money(cls):
# 建议:在类方法中通过cls操作类变量
print("总行的钱:", cls.total_money) #不用ICBC.调用,更简短
"""
#实例方法
def print_total_money2():
print("总行的钱:", ICBC.total_money) #实例方法使用的是ICBC
"""
tian_tian = ICBC("天坛支行", 100000)
# print("总行的钱:", ICBC.total_money)
ICBC.print_total_money()
xi_dan = ICBC("西单支行", 200000)
# print("总行的钱:", ICBC.total_money)
ICBC.print_total_money()# print_total_money(ICBC)
创建对象计数器,统计构造函数执行的次数
#创建对象计数器,统计构造函数执行的次数,
class Wife:
count = 0
@classmethod
def print_count(cls):
print(f"总共娶了{cls.count}个老婆")
def __init__(self, name):
self.name = name
Wife.count += 1
w01 = Wife("双儿")
w02 = Wife("阿珂")
w03 = Wife("苏荃")
w04 = Wife("丽丽")
w05 = Wife("芳芳")
Wife.print_count() # 总共娶了5个老婆
#看不懂可以先了解,上下对比classmethod
class StudentController:
"""
学生控制器:处理核心功能,存储...
"""
def __init__(self):
self.start_id = 100
self.list_student = []
def add_student(self, new_stu):
# 设置学生编号(自增长)
self.start_id += 1 #classmethod
new_stu.sid = self.start_id
# 追加到列表中
self.list_student.append(new_stu)
######### 上下对比classmethod #####################
class StudentController:
__start_id = 100 # 大家的:系统不同界面使用的学生编号是一份(连续增加)
@classmethod
def __set_student_id(cls, stu):
cls.__start_id += 1
stu.sid = cls.__start_id #StudentController替换成cls使用
def __init__(self):
self.__list_student = [] # 自己的:系统不同界面使用自己数据(可以显示不同数据)
@property # 只读属性:View类只能读取,不能修改
def list_student(self):
return self.__list_student
def add_student(self, new_stu):
# 设置学生编号
StudentController.__set_student_id(new_stu)
# 追加到列表中
self.__list_student.append(new_stu)
"""
信息管理系统
"""
class EmployeeModel:
def __init__(self, eid=0, did=0, name="", money=0):
self.eid = eid
self.did = did
self.name = name
self.money = money
def __str__(self):
return str(self.__dict__)
def __gt__(self, other):
return self.money > other.money
def __eq__(self, other):
return self.eid == other.eid
class EmployeeController:
"""
员工信息控制器:业务逻辑,核心功能
"""
__start_id = 1001 # 类变量:无论多少对象,只有一份
@classmethod
def __set_employee_id(cls, emp):
emp.eid = cls.__start_id
cls.__start_id += 1
def __init__(self):
self.__all_employee = [] # 实例变量:每个对象都有一份
@property
def all_employee(self):
return self.__all_employee
def add_employee(self, emp):
"""
添加商品信息
:param employee:需要添加的商品信息
"""
EmployeeController.__set_employee_id(emp)
self.__all_employee.append(emp)
def remove_employee(self, eid):
"""
根据商品编号删除商品信息
:param cid:商品编号
:return:是否删除成功
"""
emp = EmployeeModel(eid=eid)
if emp in self.all_employee:
self.all_employee.remove(emp)
return True
return False
def update_employee(self, emp):
for item in self.__all_employee:
if item.eid == emp.eid:
item.__dict__ = emp.__dict__
return True
return False
def ascending_order(self):
self.all_employee.sort()
class EmployeeView:
"""
员工信息视图:界面逻辑,输入输出
"""
def __init__(self):
self.__controller = EmployeeController()
def main(self):
while True:
self.__display_menu()
self.__select_menu()
def __display_menu(self):
print("1 添加员工")
print("2 显示员工")
print("3 删除员工")
print("4 修改员工")
print("5 根据薪资排序")
def __select_menu(self):
item = input("请输入您的选项:")
if item == "1":
self.__input_employee()
elif item == "2":
self.__display_employees()
elif item == "3":
self.__delete_employee()
elif item == "4":
self.__modify_employee()
elif item == "5":
self.__order_by_score()
def __order_by_score(self):
self.__controller.ascending_order()
self.__display_employees()
def __input_employee(self):
employee = EmployeeModel()
employee.name = input("请输入员工名称:")
employee.did = int(input("请输入部门编号:"))
employee.money = int(input("请输入员工工资:"))
self.__controller.add_employee(employee)
def __display_employees(self):
for item in self.__controller.all_employee:
print(item)
def __delete_employee(self):
cid = int(input("请输入员工编号:"))
if self.__controller.remove_employee(cid):
print("删除成功")
else:
print("删除失败")
def __modify_employee(self):
employee = EmployeeModel()
employee.eid = int(input("请输入员工编号:"))
employee.name = input("请输入员工名称:")
employee.did = int(input("请输入部门编号:"))
employee.money = int(input("请输入员工工资:"))
if self.__controller.update_employee(employee):
print("修改成功")
else:
print("修改失败")
view = EmployeeView()
view.main()
"""
2. 以面向对象思想,描述下列情景:
情景:手雷爆炸,可能伤害敌人(头顶爆字)或者玩家(碎屏)。
变化:还可能伤害房子、树、鸭子....
要求:增加新事物,不影响手雷.
画出架构设计图
"""
# --------------架构师--------------------
class Grenade:
def explode(self, target):
print("爆炸")
# 先确定用法
# 判断传入的对象是一种攻击目标
if isinstance(target,AttackTarget):
# 编码时,调用是父类
# 运行时,执行是子类
target.damage()
class AttackTarget:
def damage(self):
pass
# --------------程序员--------------------
class Player(AttackTarget):
# 后实现功能
def damage(self):
print("碎屏")
class Enemy(AttackTarget):
def damage(self):
print("头顶爆字")
# --------------入口--------------------
grenade = Grenade()
p = Player()
grenade.explode(p) #爆炸\n碎屏
grenade.explode(Enemy()) #爆炸\n头顶爆字
grenade.explode("大爷") #爆炸
面向对象三大特征:
封装:根据需求划分为多个类 [分]
例如:创建Person/Car/Airplane类
继承:将多个变化的类型抽象为一个概念 [隔]
例如:创建父类Vehicle
将多个变化类型的行为统一
例如:统一Car/Airplane类型的transport方法
隔离客户端代码,与多个变化类型
例如:隔离Person与Car/Airplane
多态:对于父类同一行为,在不同的子类中有不同的实现
例如:对于Vehicle的transport方法,在Car/Airplane类中有不同实现
多个变化类型通过重写实现具体功能 [做]
例如:Car/Airplane重写transport方法的内容
"""
需求:一家公司有如下几种岗位:
程序员:底薪 + 项目分红
测试员:底薪 + Bug数*5
创建员工管理器,实现下列要求:
(1)存储多个员工
(2)打印所有员工姓名
(3)计算所有员薪资
练习1:写出下列代码的面向对象三大特征思想
封装: 创建EmployeeController/Programmer/Tester
继承: 创建父类Employee
统一Programmer/Tester类型的calculate_salary方法
隔离EmployeeController与Programmer/Tester
多态:对于Employee的calculate_salary方法,在Programmer/Tester类中有不同实现
Programmer/Tester重写calculate_salary方法的内容
"""
class EmployeeController:
"""
员工管理器
"""
def __init__(self):
self.__list_employee = []
@property
def list_employee(self):
return self.__list_employee
def add_employee(self, emp):
if isinstance(emp, Employee): #判断是否继承父类,不是不添加。下面的add大爷操作不会被执行
self.__list_employee.append(emp)
def get_total_salary(self):
total_salary = 0
for item in self.__list_employee:
# 体会多态:编码时调用父
# 运行时执行子
total_salary += item.calculate_salary()
return total_salary
class Employee:
def __init__(self, name="", base_salary=0):
self.name = name
self.base_salary = base_salary
def calculate_salary(self):
pass
class Programmer(Employee):
def __init__(self, name, base_salary, bonus):
super().__init__(name, base_salary)
self.bonus = bonus
def calculate_salary(self):
# 底薪 + 项目分红
salary = self.base_salary + self.bonus
return salary
class Tester(Employee):
def __init__(self, name, base_salary, bug_count):
super().__init__(name, base_salary)
self.bug_count = bug_count
def calculate_salary(self):
# 底薪 + Bug数*5
salary = self.base_salary + self.bug_count * 5
return salary
controller = EmployeeController()
controller.add_employee(Programmer("张三", 10000, 1000000))
controller.add_employee(Tester("李四", 8000, 300))
controller.add_employee("大爷")
print(controller.get_total_salary())
for item in controller.list_employee:
print(item.name)
"""
创建图形管理器
-- 记录多种图形(圆形、矩形....)
-- 提供计算总面积的方法.
"""
class GraphicsController:
def __init__(self):
self.__list_graphics = []
@property
def list_graphics(self):
return self.__list_graphics
def add_graphics(self, graph):
# if isinstance(graph,Graphics):
self.__list_graphics.append(graph)
def get_total_area(self):
total_area = 0
for item in self.__list_graphics:
# 调用父,执行子(添加的子类对象)
total_area += item.calculate_area()
return total_area
class Graphics:
def __init__(self, name=""):
self.name = name
def calculate_area(self):
pass
class Rectangle(Graphics):
def __init__(self, name, l, w):
super().__init__(name)
self.l = l
self.w = w
def calculate_area(self):
return self.l * self.w
class Circle(Graphics):
def __init__(self, name, r):
super().__init__(name)
self.r = r
def calculate_area(self):
area = 3.14 * self.r ** 2
return area
controller = GraphicsController()
controller.add_graphics(Rectangle("大矩形", 7, 8))
controller.add_graphics(Circle("圈圈", 5))
for item in controller.list_graphics:
print(item.name)
print(controller.get_total_area())
多继承: 隔离多个维度上的变化,正常情况下从左到右继承,python中使用.mro()查看实际继承顺序
"""
同名方法在多继承中调用顺序
"""
class A:
def func01(self):
print("A-func01")
class B(A):
def func01(self):
print("B-func01")
super().func01()
class C(A):
def func01(self):
print("C-func01")
super().func01()
class D(B, C):
def func01(self):
print("D-func01")
super().func01()
# 通过类名调用指定类型中的函数
C.func01(self)
d = D()
d.func01() # D B C
# 类型记录了函数调用顺序
print(D.mro())
"""
小结-面向对象
一. 语法
class 类名:
类变量 = 数据
@classmethod
def 类方法(cls):
通过 cls.类变量 操作类变量
def __init__(self,参数):
self.实例变量 = 参数
def 实例方法(self):
通过 self.实例变量 操作数据
对象 = 类名(数据)
对象.实例变量
对象.实例方法()
类名.类变量
类名.类方法()
二. 设计思想
封装:根据需求划分为多个类
继承:统一多个变化类型,隔离客户端代码与多个变化类型
多态:多个变化类型通过重写实现具体功能
目标:满足开闭原则
允许增加新功能,但是不修改客户端代码
"""
in self.__list_graphics:
# 调用父,执行子(添加的子类对象)
total_area += item.calculate_area()
return total_area
class Graphics:
def init(self, name=“”):
self.name = name
def calculate_area(self):
pass
class Rectangle(Graphics):
def init(self, name, l, w):
super().init(name)
self.l = l
self.w = w
def calculate_area(self):
return self.l * self.w
class Circle(Graphics):
def __init__(self, name, r):
super().__init__(name)
self.r = r
def calculate_area(self):
area = 3.14 * self.r ** 2
return area
controller = GraphicsController()
controller.add_graphics(Rectangle(“大矩形”, 7, 8))
controller.add_graphics(Circle(“圈圈”, 5))
for item in controller.list_graphics:
print(item.name)
print(controller.get_total_area())
多继承: 隔离多个维度上的变化,正常情况下从左到右继承,python中使用.mro()查看实际继承顺序
```python
"""
同名方法在多继承中调用顺序
"""
class A:
def func01(self):
print("A-func01")
class B(A):
def func01(self):
print("B-func01")
super().func01()
class C(A):
def func01(self):
print("C-func01")
super().func01()
class D(B, C):
def func01(self):
print("D-func01")
super().func01()
# 通过类名调用指定类型中的函数
C.func01(self)
d = D()
d.func01() # D B C
# 类型记录了函数调用顺序
print(D.mro())
"""
小结-面向对象
一. 语法
class 类名:
类变量 = 数据
@classmethod
def 类方法(cls):
通过 cls.类变量 操作类变量
def __init__(self,参数):
self.实例变量 = 参数
def 实例方法(self):
通过 self.实例变量 操作数据
对象 = 类名(数据)
对象.实例变量
对象.实例方法()
类名.类变量
类名.类方法()
二. 设计思想
封装:根据需求划分为多个类
继承:统一多个变化类型,隔离客户端代码与多个变化类型
多态:多个变化类型通过重写实现具体功能
目标:满足开闭原则
允许增加新功能,但是不修改客户端代码
"""