- 继承-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__)"""ca(<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 = 0def __init__(self, name):self.name = nameTest.num_of_instance += 1class 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 = nameself.column_type = column_typedef __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] = vfor 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] = valueclass 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
