【一】什么是元类
元类是所有类的基类,包括object
class Solution:...
print(type(Solution))   # <class 'type'>
print(type(dict))       # <class 'type'>
print(type(object))     # <class 'type'>
data = {'username':'dream'}
print(type(data))       # <class 'dict'> 
【二】直接使用type生成
【1】直接用关键字创建
正常创建类的方式 class 类名():类体代码
【2】直接使用 type 生成
类名 = type('类名',(父类1,父类2),名称空间字典)
class Student(object):...
print(Student)          # # <class '__main__.Student'>
Student = type('Student',(object,),{'name':'knight'})
print(Student)          # <class '__main__.Student'>
print(type(Student))    # <class 'type'>
# 如果是类的名称空间字典,一定会看到出来自己定义的属性以外的很多属性,这是自带的属性
# 如果是对象的名称空间字典,一定会只有__init__初始化后的属性
print(Student.__dict__)     # {'name': 'knight', 
【三】元类的使用
元类可以在创建类的过程中进行修改和增加
# 控制当前类名必须首字母大写!首字母不大写就报错!
# 【1】创建元类
class MyType(type):def __init__(cls,class_name,class_bases,class_name_space):# cls 是当前类的本身print(f'cls:{cls}')     # cls:<class '__main__.MyClass'># class_name 是当前类的类名# 首字母必须大写其他必须小写,否则报错print(f'class_name:{class_name}')   # class_name:MyClassif not class_name.istitle():raise TypeError(f"首字母必须大写")# class_bases 当前类的父类print(f'class_bases:{class_bases}')     # class_bases:()# class_name_space 当前类的名称空间print(f'class_name_space:{class_name_space}')      # class_name_space:{'__module__': '__main__', '__qualname__': 'MyClass'}super().__init__(class_name,class_bases,class_bases)
# 【2】创建一个继承元类的类
# metaclass 指定元类
class MyClass(metaclass=MyType):...
class student(metaclass=MyType):... 
【四】元类的进阶使用
class MyType(type):def __init__(cls, class_name, class_bases, class_name_space):super().__init__(class_name, class_bases, class_name_space)
# 3.触发元类中的__call__def __call__(self, *args, **kwargs):# 4.打印三个参数# 当前类本身print(f"{self}")  # <class '__main__.MyClass'># 类实例化的时候传进来的位置参数print(f"{args}")  # ('knight',)# 类实例化的时候传进来的关键字参数print(f"{kwargs}")  # {'age': 22}print(f"类名()触发MyType中的__call__")  # 类名()触发MyType中的__call__# 加了这个判断,下面就必须使用关键字传参if args:raise TypeError(f"必须通过关键字传参数")# 5.如果不返回值就默认输入none# 一定要返回一个对象 ,直接把type拿过来用# 所以用super().__call__()# super() 其实就是typeobj = super().__call__(*args, **kwargs)print(f"obj:{obj}")  # obj:<__main__.MyClass object at 0x00000140C105FD90># 6.返回当前对象return obj
# 1.触发MyType的__init__方法
class MyClass(metaclass=MyType):def __init__(self, name, age):self.name = nameself.age = age
def __call__(self, *args, **kwargs):print(f"myclass的对象()触发了__call__")
# 2.对象(参数)调用,一定会触发MyType的__call__方法
# 7. me 接收的就是MyType的 __call__ 方法返回的obj对象
me = MyClass(name='knight', age=22)     # 因为上面加了判断,这里就不能只写'knight',要改为name='knight',否则报错
print(me())  # myclass的对象()触发了__call__
print(me.name)  # knight 
总结
如果你想高度定制类的生产过程,那么编写元类里面的__init__方法
如果你想高度定制对象的生产过程,那么编写元类里面的__call__方法