通过元类控制类的调用过程
通过元类来控制类的调用过程
在__init__之前还有__call__方法, 首先Person加括号会调__call__产生了一个空的对象(裸体的人),再把它丢进__init__方法中穿上了衣服,完成了实例化
__call__
控制类的调用过程, 实际上在控制:对象的产生
class My_class(type):
def __call__(self, *args, **kwargs):
print('yyywww')
return 1
class Person():
school = 'FYZX'
def __init__(self, name):
self.name = name
def score(self):
print("分数为100")
def __call__(self, *args, **kwargs):
print('xxdd')
# Person类加括号会调用这个类中的__call__也就是元类的__call__
p = Person('nick') # 自动触发init的执行
#先出发元类的__call__
# 出现错误因为Person调用的call方法没有返回值,
p() # 只有当对象加括号才会调用到类的__call__中
练习:把对象当中的所有属性都设置为私有的
分析
class My_class(type):
def __call__(self, *args, **kwargs):
# self 此时self是Person这个类
# print(args)
# print(kwargs)
# return self(args) # 这里不行, 会递归
# self.__new__(ocj, o) # 这里对象来调再把类传进去,容易晕
# 实例化产生一个Person类的对象,再借助于__new__来产生, 把类传进去才能产生对象
# 生产一个空对象
# obj 是Person类的对象,只不过是空的
# 这里的super指的是对象,而不是类
# obj = super().__new__(self)
# obj = object.__new__(self) # 可以用object,因为它是所有类的父类
obj = self.__new__(self)
print(obj)
# 调用__init__方法完成初始化
# 这是类来调用__init__方法,就是个普通函数,有几个参数就要传几个参数
# self.__init__(obj, *args, **kwargs)
# 对象来调__init__方法, 对象的绑定方法, 会把自身传过来
obj.__init__(*args, **kwargs)
print(obj)
return obj
class Person(object, metaclass=My_class):
school = 'FYZX'
def __init__(self, name):
self.name = name
def score(self):
print("分数为100")
def __call__(self, *args, **kwargs):
print('xxdd')
p = Person('nick')
# 这里基于元类调用__init__方法完成初始化放值
print(p.name)
实际:就三行
class My_class(type):
def __call__(self, *args, **kwargs):
# 1.调用new方法产生空对象obj; 产生一个裸体
obj = self.__new__(self)
# 2.调init方法初始化obj; 穿上衣服
obj.__init__(*args, **kwargs)
# 修改前
print(obj.__dict__)
# 修改后
obj.__dict__ = {'_%s__%s' % (self.__name__, k): v for k, v in obj.__dict__.items()}
print(obj.__dict__)
# 再return返回初始化好的obj
return obj
class Person(object, metaclass=My_class):
school = 'FYZX'
def __init__(self, name):
self.name = name
def score(self):
print("分数为100")
def __call__(self, *args, **kwargs):
print('xxdd')
p = Person('nick')
# 这里已经取不到了,name已经变为私有的了
print(p.name)

浙公网安备 33010602011771号