通过元类控制类的调用过程

通过元类来控制类的调用过程

__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)
posted @ 2023-10-30 11:22  hanyingshuo  阅读(18)  评论(0)    收藏  举报