Mixins机制
class Vehicle: # 交通工具 pass class FlyMinix(): def fly(self): ''' 飞行功能相应的代码 ''' print("I am flying") ''' 1. 主类:就是大部分都是主要的功能 2. 辅类:就是一些辅助的功能 3. 辅类的类名也有讲究:一般以mixin、able、ible等结尾 4. 继承的位置也有讲究:一般辅类在左边,主类在右边 ''' class CivilAircraft(FlyMinix, Vehicle): # 民航飞机 pass class Helicopter(FlyMinix, Vehicle): # 直升飞机 pass
元类简介
# 什么是元类? # 即产生类的类 '''type其实查看的就是对象是由哪个类产生的''' class MyClass(object): pass obj = MyClass() # <class '__main__.MyClass'> print(type(obj)) # 可以查看出obj对象是有哪个类产生的 '''打印type(MyClass)结果会是什么呢?''' class type(object): print(type(MyClass)) # <class 'type'> 我就可以认为MyClass类就是有type类产生的 class Student(): pass # print(type(Student)) # <class 'type'> class C1(): pass print(type(C1)) # <class 'type'> ''' 得出结论:我们之前使用class造出来的类都是由type类造出来的 所以说默认情况下,所有的类的元类都是type '''
产生类的两种方式
1. class 类名():
pass
2. 由于所有的类都是由type类造出来的,所以我们也可以使用type类造出来一个新类
type(object_or_name, bases, dict) # 这三个条件就是造出来类的三个要素. # type("类名", "父类", "类的名称空间")
3. 为什么要学习元类?
元类是造出类的类,所以我们可以对类进行高度的定制化
eg:
限定写出的类名必须是首字母大写的
思考:定制化代码在哪里写?
类是如何产生的?类是由元类产生的type类,如果想改类的行为,应该在元类里的__init__方法中改。
对象是如何产生的?是执行了产生这个对象的类内部的__init__方法
推导:已知推出来的未知
想改父类的__init__方法,但是又不能修改源代码,所以我们可以写出来一个子类来继承父类type,在子类里面写代码,然后重新执行一些父类的__init__方法。
ps:元类不能直接继承
class MyTypeClass(type): def __init__(self, cls_name, cls_bases=None, cls_dict=None): print(cls_name, cls_bases, cls_dict) # C1 () {'__module__': '__main__', '__qualname__': 'C1'} # cls_name:它就是类名 # 限制类名必须是首字母大写 if not cls_name.istitle(): raise Exception("类名必须是首字母大写") super().__init__(cls_name, cls_bases=None, cls_dict=None) class C1(metaclass=MyTypeClass): school = 'Sh' class a(metaclass=MyTypeClass): pass
元类的进阶操作
__call__ # 对象加括号会自动调用类的__call__方法,并且__call__方法里面返回神恶魔,那么对象加括号的位置就是什么 # 推导:类名()会怎么样? '''类名(),应该会执行产生类的类中的__call__方法,而这个类恰好是元类type''' class MyClass(type): def __call__(self, *args, **kwargs): print("__call__ 执行了") print(args, kwargs) """限制传参的方式必须是关键字传参,只需要args是空就行""" if args: raise Exception("传参必须是关键字传参") super(MyClass, self).__call__(*args, **kwargs) class C1(metaclass=MyClass): def __init__(self, name): print("__init__ 执行了") # self.name = name '''看C1类里面的__init__方法和元类里面的__call__方法的执行顺序 得出结论:其实在执行类的__init__之前,先执行了__call__方法 obj = C1(name='kevin') # 都是位置传参,强制要求必须是关键字传参
标签:__,python,day35,Mixins,元类,init,type,class,cls From: https://www.cnblogs.com/zfq132/p/17514538.html