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>

浙公网安备 33010602011771号