- 继承-MRO
- 类的方法
- 元类
继承-MRO
在Python 中 类的继承有单继承 和 多继承
class A():
def a(self):
print("a")
class B():
def b(self):
print("b")
class C(A):
# class C(B,A):
def c(self):
print("c")
# 使用A的方法啊
super().a()
if __name__ == '__main__':
c = C()
c.c()
c.a()
print(C.__mro__)
"""
c
a
(<class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
# (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
# 可以看出 当C 继承A的 时候 也继承了A中的a方法
# mro链 看出 C-A-Object
"""
继承查找的顺序:
- 总的来说一个类的MRO列表就是合并所有父类的MRO列表
- 子类永远在父类前面
- 如果有多个父类,会根据他们在列表中的顺序被检查
- 如果遇到多继承则按代码中继承列表顺序从左到右写
- 根据侯入度为0 来判断,每一层必须选择完才可以进入下一个
类的方法
- 类方法
- 是类对象的方法,在定义时需要在上方使用@classmethod进行装饰,形参是cls,表示类对象,
类对象和实力对象都是可以调用
- 类实例方法
- 是实例化对象的方法 只有实例对象才可以调用 形参是self 指对象对象本身
- 静态方法
- 是一个任意函数,在其上方使用@staticmethod 进行装饰。可以用对象直接调用
- 类变量
- 类变量是可以在所有实例之间共享的值,也就是说他们不是单独分配给某一个实例的
class Test:
num_of_instance = 0
def __init__(self, name):
self.name = name
Test.num_of_instance += 1
class Person:
name = "aaa"
if __name__ == '__main__':
print(Test.num_of_instance)
t1 = Test("cc")
print(Test.num_of_instance)
t2 = Test("zz")
print(Test.num_of_instance)
print(t1.name, t1.num_of_instance)
print(t2.name, t2.num_of_instance)
p1 = Person()
p2 = Person()
p1.name = 'bb'
print(p1.name)
print(p2.name)
print(Person.name)
这里p1.name="bbb"是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,
p1.name一开始是指向的类变量name="aaa",但是在实例的作用域里把类变量的引用改变了,
就变成了一个实例变量,self.name不再引用Person的类变量name了.
元类
元类 在python中基本上我们使用到到频率非常小。也就是在orm的时候我们会用到,但是orm已经替我们做好了。元类就是创建类的东西 事实上type也是元类
https://segmentfault.com/a/1190000007255412
metaclass 实现orm的原理
class Field(object):
def __init__(self, name, column_type):
self.name = name
self.column_type = column_type
def __str__(self):
return '<%s:%s>' % (self.__class__.__name__, self.name)
class StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, 'varchar(100)')
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, 'bigint')
class ModelMteaclass(type):
def __new__(cls, name, bases, attrs):
if name == "Model":
return type.__new__(cls, name, bases, attrs)
print("Fount model:%s" % name)
mappings = dict()
for k, v in attrs.items():
if isinstance(v, Field):
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v
for k in mappings.keys():
attrs.pop(k)
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
return type.__new__(cls, name, bases, attrs)
class Model(dict, metaclass=ModelMteaclass):
def __init__(self, **kw):
super(Model, self).__init__(**kw)
def __getattr__(self, key):
print(key)
try:
return self[key]
except KeyError:
raise AttributeError(r"'Model' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
class Customer(Model):
# 定义类的属性到列的映射:
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password')
if __name__ == '__main__':
u = Customer(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
print(u.name)
python 中新类 旧类的区别
#新式类
class C(object):
pass
#经典类
class B:
pass
- class 执行结果和type不一致
- 继承搜索的顺序
- 新: 先水平搜索,然后再向上移动。
- 旧:先深入继承树左侧,再返回,开始找右侧
- slots: 可以把实例属性的种类锁定到 slots 规定的范围之中。
- getattribute