什么是元类

  • 在python中可以看到很多的对象都是type类型,那么什么是type类型呢?即元类。元类就是创建所有类的一个模板,是创建python所有类的类,里面封装了一些方法。

使用type创建类

  • type的第一个用法就是查看对象所属类
  • 可以使用type创建类,type需要传入三个参数:name、bases、dict。需要注意传入时不用写形参。
    • name 类名
    • bases 继承的基类,元组形式传入
    • dict 类封装的方法,以字典传入
  • 如下所示: ```python

    使用type创建类

def init(self): print(“我要初始化!”)

def func(self): print(“我是普通方法!”)

@classmethod def class_func(cls): print(“我是类方法!”)

@staticmethod def static_func(): print(“我是静态方法!”)

MyClassType = type( “MyClassType”,
(object, ), {“init“: init, “func”: func, “class_func”: class_func, “static_func”:static_func} )

c = MyClassType() c.static_func() MyClassType.class_func()

  1. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1325594/1594455596422-597076e6-d4ea-44e3-a7ea-bafe7a544ac5.png#align=left&display=inline&height=79&margin=%5Bobject%20Object%5D&name=image.png&originHeight=87&originWidth=1218&size=35101&status=done&style=none&width=1100)
  2. <a name="UMm49"></a>
  3. ### 为什么使用元类?
  4. - 可以通过元类控制子类实现一些功能。
  5. - 可以通过abc模块里的ABCMeta类来实现
  6. <a name="NidMa"></a>
  7. #### 抽象基类
  8. - 在基类中实现一些方法,但是什么都不用做,但是强迫子类重写这些方法,不然不能实例化子类,从而达到了子类继承时符合要求。
  9. ```python
  10. from abc import ABCMeta,abstractmethod
  11. class MyAbstract(object, metaclass=ABCMeta):
  12. # 定义抽象方法
  13. @abstractmethod
  14. def say_something(self):
  15. pass
  16. class MyClass(MyAbstract):
  17. # 重写抽象方法
  18. def say_something(self):
  19. print("nihao !")
  20. my_class = MyClass()
  21. my_class.say_something()
  22. print("my_class", type(my_class))
  23. print("MyClass", type(MyClass))
  24. print("MyAbstract", type(MyAbstract))

image.png

  • 如果不重写say_something这个方法,就会报错,如下: ```python from abc import ABCMeta,abstractmethod

class MyAbstract(object, metaclass=ABCMeta): @abstractmethod def say_something(self): pass

class MyClass(MyAbstract):

  1. # def say_something(self):
  2. # print("nihao !")
  3. pass

my_class = MyClass()

  1. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/1325594/1594457185450-5eb582d0-b8d3-4487-8f40-126a10b03d46.png#align=left&display=inline&height=90&margin=%5Bobject%20Object%5D&name=image.png&originHeight=125&originWidth=1525&size=73415&status=done&style=none&width=1100)
  2. <a name="Zozlq"></a>
  3. #### 其他用法
  4. - 强迫写说明文档
  5. ```python
  6. from abc import ABCMeta,abstractmethod
  7. class MyAbstract(object, metaclass=ABCMeta):
  8. @abstractmethod
  9. def say_something(self):
  10. pass
  11. def __new__(cls):
  12. if cls.__dict__["__doc__"] is not None:
  13. return super().__new__(cls)
  14. else:
  15. raise TypeError("没有说明文档,亲!")
  16. class MyClass(MyAbstract):
  17. """doc"""
  18. def say_something(self):
  19. print("nihao !")
  20. my_class = MyClass()
  21. print(my_class.__doc__)

结果如下:
image.png
如果没有子类没有写说明文档运行如下:
image.png

继承顺序

  • python 3之后的类继承顺序使用的c3算法,可以使用mro方法查看继承顺序
    • 由下至上继承
    • 从左至右继承 ```python from abc import ABCMeta

class A(object): pass

class B: pass

class C(A, B): pass

print(C.mro) ``` image.png