python黑魔法metaclass
python黑魔法metaclass
在看Flask源码的时候遇到了metaclass,记录下metaclass简单使用。
利用metaclass创建类示例01:
"""
class Foo(object):
pass
以上代码解释器将其解释为
Foo = type('Foo', (object,), {})
type()的三个参数:'Foo':类名; (object, ): 类的继承关系,用元组表示; {}: 类的字段,方法。
"""
class MyType(type):
def __new__(cls, *args, **kwargs):
print('MyType __new__')
return super(MyType, cls).__new__(cls, *args, **kwargs)
def __init__(cls, *args, **kwargs):
print('MyType __init__')
super().__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
print('MyType __call__')
# return None
return super().__call__(*args, **kwargs)
class Foo(metaclass=MyType):
pass
obj = Foo()
print(obj)
"""
MyType __new__
MyType __init__
MyType __call__
<__main__.Foo object at 0x0000020A6CDBAB00>
"""
当执行到class Foo(metaclass=MyType)语句时,会看是否指定元类,如果没指定元类则默认使用type创建类,否则按照指定元类创建类。这里回去执行MyType的__new__方法和__init__方法生成类。当执行obj = Foo()实例化类的时候会调用MyType的__call__方法。这里如果我在MyType里return None那么obj就会是None而不是类实例
给创建的类添加__call__方法,当执行对象obj()调用时执行。
class MyType(type):
def __new__(cls, *args, **kwargs):
print('MyType __new__')
return super(MyType, cls).__new__(cls, *args, **kwargs)
def __init__(cls, *args, **kwargs):
print('MyType __init__')
super().__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
print('MyType __call__')
return super().__call__(*args, **kwargs)
class Foo(metaclass=MyType):
def __call__(self, *args, **kwargs):
print(11111)
obj = Foo()
print(obj)
print(obj())
"""
MyType __new__
MyType __init__
MyType __call__
<__main__.Foo object at 0x00000159DC30ABA8>
11111
None
"""
利用metaclass创建类示例02:
class MyType(type):
def __new__(cls, *args, **kwargs):
print('MyType __new__')
return super(MyType, cls).__new__(cls, *args, **kwargs)
def __init__(cls, *args, **kwargs):
print('MyType __init__')
super().__init__(*args, **kwargs)
def __call__(cls, *args, **kwargs):
print('MyType __call__')
return super().__call__(*args, **kwargs)
def with_meta(meta, Base):
return meta('Foo', (Base, ), {})
Foo = with_meta(MyType, object)
print(Foo())
"""
MyType __new__
MyType __init__
MyType __call__
<__main__.Foo object at 0x000001D13919AC18>
"""
利用metaclass构造单例
class Sington(type):
_instaces = dict()
def __call__(cls, *args, **kwargs):
if cls not in cls._instaces:
cls._instaces[cls] = super().__call__(*args, **kwargs)
return cls._instaces[cls]
class MyClass(metaclass=Sington):
pass
one = MyClass()
two = MyClass()
print(id(one))
print(id(two))

浙公网安备 33010602011771号