一、什么是元类
在 Python 中,一切皆为对象,即类也是一个对象。type 是内置的元类。我们用 class 关键字定义的所有的类以及内置的类都是由元类 type(内置的元类) 实例化产生的。
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def show_info(self):
print(f"name: {self.name}, age: {self.age}")
print(type(Person))
print(type(int))
二、class机制分析
# 1、类名
class_name = "Person"
# 2、类的基类
class_base = (object,)
# 3、执行类体代码拿到类的名称空间
class_dict = {}
class_body = """
def __init__(self,name,age):
self.name = name
self.age = age
def show_info(self):
print(f"name: {self.name}, age: {self.age}")
"""
exec(class_body,{},class_dict)
print(class_dict)
# 4、调用元类
Person = type(class_name,class_base,class_dict)
print(Person)
三、自定义元类
# 只有继承了type类的类才是元类
class MyMeta(type):
# cls当前所在的类,*args、**kwargs调用类时所传入的参数
def __new__(cls,*args,**kwargs):
print("__new__()方法运行了")
print(cls)
print(args)
print(kwargs)
return type.__new__(cls,*args,**kwargs)
# __init__()接收的参数是__new__()方法返回的
def __init__(self,class_name,class_bases,class_dict):
print("__init__()方法运行了")
print(self)
print(class_name)
print(class_bases)
print(class_dict)
"""
调用MyMeta发生的三件事:
1、先造一个空对象,调用类内的__new__()方法,就是调用type.__call__()方法
2、调用MyMeta这个类内的__init__()方法,完成初始化对象的操作
3、返回初始化好的对象
Person = MyMeta(class_name,class_bases,class_dict)
"""
class Person(metaclass=MyMeta):
def __init__(self,name,age):
self.name = name
self.age = age
def show_info(self):
print(f"name: {self.name}, age: {self.age}")
# 只有继承了type类的类才是元类
class MyMeta(type):
def __call__(self,*args,**kwargs):
print(self)
print(args)
print(kwargs)
# MyMeta.__call__()方法会先调用Person类内的__new__()方法
obj = self.__new__(self)
# MyMeta.__call__()方法内会调用Person类内的__init__()方法
self.__init__(obj,*args,**kwargs)
# MyMeta.__call__()方法会返回一个初始化好的对象
return obj
"""
类的产生:Person = MyMeta() --> type.__call__()干的三件事:
1、type.__call__()方法内会先调用MyMeta类内的__new__()方法
2、type.__call__()方法内会调用MyMeta类内的__init__()方法
3、type.__call__()方法会返回一个初始化好的对象
"""
class Person(metaclass=MyMeta):
def __new__(cls,*args,**kwargs):
# 产生真正的对象
return object.__new__(cls)
def __init__(self,name,age):
self.name = name
self.age = age
def show_info(self):
print(f"name: {self.name}, age: {self.age}")
"""
类的调用:p = Person("Sakura",10) --> MyMeta.__call__()干的三件是
1、MyMeta.__call__()方法内会先调用Person类内的__new__()方法
2、MyMeta.__call__()方法内会调用Person类内的__init__()方法
3、MyMeta.__call__()方法会返回一个初始化好的对象
"""
p = Person("Sakura",10)
print(p)
print(p.__dict__)
只要掉类,那么会依次调用类内的
__new__()方法,在调用__init__()方法;如果想要一个对象可以加括号调用,需要在该对象的类中添加一个
__call__()方法;