对象名称空间
obj.name 会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类…最后都找不到就抛出异常
对象的组合用法
class Weapon:
def prick(self, obj): # 这是该装备的主动技能,扎死对方
obj.life_value -= 500 # 假设攻击力是500
class Person: # 定义一个人类
role = 'person' # 人的角色属性都是人
def __init__(self, name):
self.name = name # 每一个角色都有自己的昵称;
self.weapon = Weapon() # 给角色绑定一个武器;
面向对象三大特征
继承
class Animal:
def __init__(self, name, kind):
self.name = name
self.kind = kind
def eat(self, food):
print(f'{self.name} is eating {food}')
class Cat(Animal):
def __init__(self, name, kind, eye_color):
super().__init__(name,kind) # 第二种方法,使用super().__init__()方法,相当于执行了父类的init方法
# super(Cat,self).__init__(name,kind)
self.eye_color = eye_color # 派生属性
当类是经典类时,多继承情况下, 会按照深度优先的方式查找
当类是新式类时,多继承情况下, 会按照广度优先方式查找
MRO 是通过 c3线下算法实现的。
多态
封装
私有变量双下滑线和单下划线
单下划线:继承子类也可以访问
双下划线:会自动变更变量和方法名 class A: key=’a’ => A._Akey
实例attribute增加除访问与修改之外的其他处理逻辑,比如类型检查或合法性验证
# 不建议使用property,使得代码变得臃肿,执行变慢
class Person:
def __init__(self, first_name):
self.first_name = first_name
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, value):
self._first_name = value
# 增加额外的操作,验证输入值类型,不让删除
class Person:
def __init__(self, first_name):
self._first_name = first_name
# Getter function
@property
def first_name(self):
return self._first_name
# Setter function
@first_name.setter
def first_name(self, value):
if not isinstance(value, str):
raise TypeError('Expected a string')
self._first_name = value
# Deleter function (optional)
@first_name.deleter
def first_name(self):
raise AttributeError("Can't delete attribute")
在子类中调用父类的某个已经被覆盖的方法 super。
- 子类调用父类已覆盖的方法
- 函数的一个常见用法是在 init() 方法中确保父类被正确的初始化了
MRO算法:
- 子类会先于父类被检查
- 多个父类会根据它们在列表中的顺序被检查
- 如果对下一个类存在两个合法的选择,选择第一个父类