python基础-元类执行流程

第一步

继承默认元类type

class Mymeta(type):  # 继承默认元类的一堆属性
    def __init__(self, class_name, class_bases, class_dic):
        print("Mymeta__init__")

        super(Mymeta, self).__init__(class_name, class_bases, class_dic)


class People(object, metaclass=Mymeta):
    country = 'China'

    def __init__(self, name, age):
        print("people__init__")
        self.name = name
        self.age = age

    def talk(self):
        print('%s is talking' % self.name)

p1= People("a",1)
print("--------")
p2 = People("b",2)

输出如下:

Mymeta__init__
people__init__
--------
people__init__

第二步

__call__方法的使用,对象调用时候,会调用该方法

class People(object,metaclass=type):
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def __call__(self, *args, **kwargs):
        print(self,args,kwargs)



p1= People("a",1)
p1(1,2)
print("--------")
p2 = People("b",2)
p2(2,3)

输出如下:

E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
<__main__.People object at 0x04B713B0> (1, 2) {}
--------
<__main__.People object at 0x04B714F0> (2, 3) {}

如果说类People是元类type的实例,那么在元类type内肯定也有一个call,会在调用People(‘egon’,18)时触发执行,然后返回一个初始化好了的对象obj

第三步

class Mymeta(type): #继承默认元类的一堆属性
    def __init__(self,class_name,class_bases,class_dic):
        print("Mymeta__init__")
        print(self,class_name,class_bases,class_dic)
        super(Mymeta,self).__init__(class_name,class_bases,class_dic)

    def __call__(self, *args, **kwargs):
        print("Mymeta__call__",self)
        #self=People
        print(self,args,kwargs) #<class '__main__.People'> ('orz', 18) {}

        #1、实例化People,产生空对象obj
        obj=object.__new__(self)


        #2、调用People下的函数__init__,初始化obj
        self.__init__(obj,*args,**kwargs)


        #3、返回初始化好了的obj
        return obj

class People(object,metaclass=Mymeta):
    country='China'

    def __init__(self,name,age):
        print("People__init__",self)
        self.name=name
        self.age=age

    def talk(self):
        print('%s is talking' %self.name)



obj1=People('orz',18)
print(obj1.__dict__) #{'name': 'orz', 'age': 18}

print("------------------")
obj2=People('safly',10)
print(obj2.__dict__) #{'name': 'safly', 'age': 10}

输出如下:

E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
Mymeta__init__
<class '__main__.People'> People (<class 'object'>,) {'__module__': '__main__', '__qualname__': 'People', 'country': 'China', '__init__': <function People.__init__ at 0x036D28E8>, 'talk': <function People.talk at 0x036D27C8>}
Mymeta__call__ <class '__main__.People'>
<class '__main__.People'> ('orz', 18) {}
People__init__ <__main__.People object at 0x036D1E30>
{'name': 'orz', 'age': 18}
------------------
Mymeta__call__ <class '__main__.People'>
<class '__main__.People'> ('safly', 10) {}
People__init__ <__main__.People object at 0x036D1DF0>
{'name': 'safly', 'age': 10}

Process finished with exit code 0

第四步

class Mymeta(type): #继承默认元类的一堆属性
    def __init__(self,class_name,class_bases,class_dic):
        print("Mymeta__init__")
        super(Mymeta,self).__init__(class_name,class_bases,class_dic)

    def __call__(self, *args, **kwargs):
        print("Mymeta__call__")

        #1、调用self,即People下的函数__new__,在该函数内完成:1、产生空对象obj 2、初始化 3、返回obj
        obj=self.__new__(self,*args,**kwargs)

        #2、一定记得返回obj,因为实例化People(...)取得就是__call__的返回值
        return obj

class People(object,metaclass=Mymeta):
    country='China'

    def __init__(self,name,age):
        print("People__init__")
        self.name=name
        self.age=age

    def talk(self):
        print('%s is talking' %self.name)


    def __new__(cls, *args, **kwargs):
        print("People__new__")
        obj=object.__new__(cls)
        cls.__init__(obj,*args,**kwargs)
        return obj


obj=People('safly',18)
print(obj.__dict__) #{'name': 'egon', 'age': 18}
print("-------------")
obj1 = People("orz",18)
print(obj1.__dict__)

输出如下:

E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
Mymeta__init__
Mymeta__call__
People__new__
People__init__
{'name': 'safly', 'age': 18}
-------------
Mymeta__call__
People__new__
People__init__
{'name': 'orz', 'age': 18}

Process finished with exit code 0

第五步

定制元类实现单例模式

class Mymeta(type):
    def __init__(self,name,bases,dic): #定义类Mysql时就触发
        print("Mymeta __init__")
        self.__instance=None
        super().__init__(name,bases,dic)

    def __call__(self, *args, **kwargs): #Mysql(...)时触发
        print("Mymeta __call__")
        if not self.__instance:
            self.__instance=object.__new__(self) #产生对象
            self.__init__(self.__instance,*args,**kwargs) #初始化对象
            #上述两步可以合成下面一步
            # self.__instance=super().__call__(*args,**kwargs)

        return self.__instance
class Obj(metaclass=Mymeta):
    def __init__(self,host='127.0.0.1',port='3306'):
        print("Obj __init__")
        self.host=host
        self.port=port

    def __new__(cls, *args, **kwargs):
        print("Obj new")



obj1=Obj()
print("-----------")
obj2=Obj()

print(obj1 is obj2)

输出如下:

E:\python\python_sdk\python.exe E:/oldboy/视频/python基础/day91/s8day88/demo.py
Mymeta __init__
Mymeta __call__
Obj __init__
-----------
Mymeta __call__
True

如果替换为注释的代码self.__instance=super().__call__(*args,**kwargs)输出如下:

Mymeta __init__
Mymeta __call__
Obj new
-----------
Mymeta __call__
Obj new
True

Mymeta中的__call__直接调用Obj中的__new__方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值