Python 类中的MetaClass

MetaClass

如果对python中类的创建顺序不明确。可以先浏览此链接(再接着阅读以下内容):
Python中创建类的执行顺序

类型中的:

  • __new__ :创建类实例化对象(空对象)
  • __init__ :初始化类实例化对象(空对象赋值)
  • __call__ :类实例化对象加括号 (对象调用)

基于类创建对象(类实例化对象)

class Test:

    # 2.赋值类实例化对象,将空对象赋值数据 (初始化对象)
    def __init__(self, name):
        print('初始化类实例对象前拓展空间')
        self.name = name
        print('初始化类实例对象后拓展空间')

    # 1.开辟空间,创建类的实例化空对象+自定义拓展 (创建对象)
    def __new__(cls, *args, **kwargs):
        print('创建类实例对象前拓展空间')
        empty_object = object.__new__(cls)
        print('创建类实例对象后拓展空间')
        return empty_object

    # 3. 执行类实例化对象实例 (执行对象)
    def __call__(self, *args, **kwargs):
        print('类实例对象添加括号执行类实例化对象实例')


obj = Test('reds')
obj()

# ===============《终端》==================
创建类实例对象前拓展空间
创建类实例对象后拓展空间
初始化类实例对象前拓展空间	
初始化类实例对象后拓展空间
类实例对象添加括号执行类实例化对象实例
- 根据类创建对象
	1.执行类的new方法,创建对象(空对象)。【构造方法】 {}
	2. 执行类的init方法,初始化对象。  【初始化方法】 {name: "redskaber"}

对象是基于类创建出来的。

  • 类是由谁创建出来的?
类是由type创建出来的。
# 1.传统创建类的方式(直观)
class Foo(object):
    
    static = 'foo'
    
    def func(self):
        return 666

    
# 2.非传统创建类方式(一行)
type('Foo',(object,),{'static':'foo','func':lambda self:666})

  • python实现创建类
# 1.传统创建类方式
class Foo(object):
    static = 'foo'

    def func(self):
        return 666


# 2.非传统创建类方式
#   - 类名
#   - 继承类
#   - 成员
def do():
    pass


fa = type('Foo', (object,), {"static": 'foo', 'func': lambda self: 666, 'do': do})
print(Foo(), fa())		# <__main__.Foo object at 0x00000223C3291FD0> <__main__.Foo object at 0x00000223C3291FA0>
print(Foo().static, fa().static)	# foo foo
print(Foo().func(), fa().func())	# 666 666
  • 类默认由type创建,怎么让一个类的创建改成其他的东西呢? 元类。
元类,指定类是由谁来创建。
# 默认由type创建Foo类型
class Foo(object):
    pass

# 由 `xxoo` 创建Foo类型
class Foo(object, metaclass=xxoo):
    pass

假设,Foo类型是MyType元类创建出来的对象,则创建Foo类型时,是执行MyType元类中的: __new____init____call__方法。

元类中的:

  • __new__(创建空类型)
  • __init__(赋值空类型)
  • __call__(类型实例化)
# mcs <=> make_class
# cls <=> class

# Foo 类型本质上是由MyType元类创建的一个对象
# Foo()  ->  MyType对象() -> 执行MyType.__call__方法


class MyType(type):

    def __init__(cls, *args, **kwargs):
        super(MyType, cls).__init__(*args, **kwargs)
        
    def __new__(mcs, *args, **kwargs):
        make_class = super(MyType, mcs).__new__(mcs, *args, **kwargs)
        return make_class
	
    def __call__(cls, *args, **kwargs):
        empty_object = cls.__new__(cls)
        cls.__init__(empty_object, *args, **kwargs)
        return empty_object

    

class Foo(metaclass=MyType):

    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        new_obj = super(Foo, cls).__new__(cls)
        return new_obj

    def __call__(self, *args, **kwargs):
        return '__call__'

        
obj = Foo('reds')  		# <class '__main__.Foo'> 当前类型是由 metaclass(元类)创建。
obj()


# ########################################》当实例化类对象时《#########################################
'''
	(类)
    - 1.创建类型		
        - 1.1 类型元类:__new__      --> 开辟空间,创建类型空对象 
        - 1.2 类型元类: __init__     --> 初始化类型对象(赋值)
        - 1.3 类型元类: __call__     --> 实例化类型对象(执行) Foo()
    (对象)
    - 2.创建类实例化对象	
        - 2.1 类型对象: __new__     --> 开辟空间,创建类实例化空对象
        - 2.2 类型对象: __init__    --> 初始化类实例化对象(赋值)
        - 2.3 类型对象: __call__    --> 实例化类实例化对象(执行) obj()
    
'''

实战案例

wtforms源码

from wtforms.fields import simple


class FormMeta(type):
    def __init__(cls, name, bases, attrs):
        type.__init__(cls, name, bases, attrs)
        cls._unbound_fields = None
        cls._wtforms_meta = None

    def __call__(cls, *args, **kwargs):
        if cls._unbound_fields is None:
            fields = []
            for name in dir(cls):
                if not name.startswith("_"):
                    unbound_field = getattr(cls, name)
                    if hasattr(unbound_field, "_formfield"):
                        fields.append((name, unbound_field))
            fields.sort(key=lambda x: (x[1].creation_counter, x[0]))
            cls._unbound_fields = fields

        if cls._wtforms_meta is None:
            bases = []
            for mro_class in cls.__mro__:  # [<class '__main__.Form'>, <class '__main__.BaseForm'>, <class 'object'>]
                if "Meta" in mro_class.__dict__:  # class Meta:
                    bases.append(mro_class.Meta)
            cls._wtforms_meta = type("Meta", tuple(bases), {})
        return type.__call__(cls, *args, **kwargs)

"""
cls._wtforms_meta = type("Meta", tuple(bases), {})

class Meta(bases):
    pass
    
"""

class BaseForm:
    pass

class Form(BaseForm, metaclass=FormMeta):
    pass

class LoginForm(Form):
    name = simple.StringField(label='用户名', render_kw={'class': 'form-control'})
    pwd = simple.PasswordField(label='密码', render_kw={'class': 'form-control'})

    class Meta:
        pass


# 1.创建LoginForm 类型时,先执行 metaclass=FormMeta 中的 __new__ && __init__ 方法
# 2.创建LoginForm类实例化对象时,调用metaclass=FormMeta 中的 __call__方法 --> 拓展 + type.__call__ -->调用 LoginForm 中的 __new__ && __init__

print(LoginForm.mro())  # [<class '__main__.Form'>, <class '__main__.BaseForm'>, <class 'object'>]
bases = []
for mro_class in LoginForm.__mro__:
    if "Meta" in mro_class.__dict__:
        bases.append(mro_class.Meta)
        print(bases)

单例模式

实现方式:

  • 模块导入
  • 并发编程
  • 元类单例
# 通过metaclass 控制单例

class MyType(type):

    def __init__(cls, *args, **kwargs):
        super().__init__(*args, **kwargs)
        cls._instance = None

    def __call__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = cls.__new__(cls, *args, **kwargs)
        return cls._instance

class Singleton(metaclass=MyType):
    pass

class Foo(Singleton):
    pass

print(Foo()) # <__main__.Foo object at 0x000001A30C0EE4F0>
print(Foo()) # <__main__.Foo object at 0x000001A30C0EE4F0>






# 创建类实例对象时,控制单例
class MyType(type):
    pass

class Singleton(metaclass=MyType):

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance


class Foo(Singleton):
    pass


obj1 = Foo()  # <__main__.Foo object at 0x000001CA04701C10>
obj2 = Foo()  # <__main__.Foo object at 0x000001CA04701C10>


posted @ 2022-11-05 17:59  Redskaber  阅读(157)  评论(0)    收藏  举报