什么是元类

元类是类的类,是类的模板,用来控制如何创建类的,正如类是创建对象的模板一样,typepython的一个内建元类,用来直接控制生成类,python中任何class 定义的类其实是type 类实例化的对象

面向对象之元类 - 图1

  1. class MyClass(object):
  2. pass
  3. '''type就是所有类默认的元类'''
  4. obj = MyClass()
  5. print(type(obj))
  6. # <class '__main__.MyClass'>
  7. print(type(MyClass))
  8. # <class 'type'>

如何产生类

  1. 利用class 关键字
  1. # class 类名
  2. class MyClass(object):
  3. pass
  4. print(MyClass)
  5. # <class '__main__.MyClass'>
  1. type元类
  1. # type(类名, 父类, 类的名称空间)
  2. res = type('MyClass', (), {})
  3. print(res)
  4. # <class '__main__.MyClass'>

面向对象之元类 - 图2

基本使用

  1. class MyTypeClass(type):
  2. def __init__(cls, cls_name, cls_bases, cls_dict): # cls用来接收类
  3. if not cls_name.istitle():
  4. raise Exception("类名的首字母必须大写")
  5. super.__init__(cls_name, cls_bases, cls_dict)
  6. # print(cls, cls_name, cls_bases, cls_dict)
  7. # <class '__main__.MyClass'> MyClass () {'__module__': '__main__', '__qualname__': 'MyClass', 'student': 'kevin'}
  8. # 元类是不能通过继承的方式直接指定的,需要关键字metaclass
  9. class MyClass(metaclass=MyTypeClass):
  10. student = 'kevin'
  11. print(type(MyClass))
  12. # <class '__main__.MyTypeClass'>
  13. class a(metaclass=MyTypeClass):
  14. pass
  15. # Exception: 类名的首字母必须大写

元类是不能通过继承的方式直接指定的,需要关键字metaclass

进阶操作

对象加括号会自动执行产生该对象的类里面的__call__。类加括号会执行元类的里面的__call__

  1. class MyTypeClass(type):
  2. def __call__(self, *args, **kwargs):
  3. print('执行__call__')
  4. super().__call__(*args, **kwargs)
  5. class MyClass(metaclass=MyTypeClass):
  6. def __init__(self, name):
  7. print('执行__init__')
  8. self.name = name
  9. obj = MyClass('kevin')
  10. # 执行__call__
  11. # 执行__init__
  1. # 定制对象的产生过程
  2. class MyTypeClass(typ):
  3. def __call__(self, *args, **kwargs):
  4. # print('__call__ run')
  5. # print(args,kwargs)
  6. if args:
  7. raise Exception('必须全部采用关键字参数')
  8. super().__call__(*args, **kwargs)
  9. class MyClass(metaclass=MyTypeClass):
  10. def __init__(self, name):
  11. # print('__init__ run')
  12. self.name = name
  13. """强制规定:类在实例化产生对象的时候 对象的独有数据必须采用关键字参数"""
  14. obj = MyClass(name='kevin')