参考文档
creating-a-singleton-in-python和what-is-a-metaclass-in-python
问题描述
下面这两段代码的执行结果反映了一个问题:很明显元类的存在会影响__call__和__new__的优先级,请问大神能否分析一下两者执行结果不同的原因?
实例代码
1.不含元类的单例模式
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
print('__new__')
return cls._instance
def __call__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
print('__call__')
return cls._instance
class Foo(Singleton):
pass
print('1')
foo1 = Foo()
print('2')
foo2 = Foo()
print(foo1 is foo2) # True
上面这段代码的执行结果
$ python non_metaclass.py
1
__new__
2
__new__
True
2.含有元类的单例模式
class Singleton(type):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
print('__new__')
return cls._instance
def __call__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
print('__call__')
return cls._instance
class Foo(metaclass=Singleton):
# 不兼容Python2
pass
print('1')
foo1 = Foo()
print('2')
foo2 = Foo()
print (foo1 is foo2) # True
上面这段代码的执行结果
$ python metaclass.py
__new__
1
__call__
2
__call__
True
如果描述不够详细,请在评论区留一下言,我再改进。
我在这里再修改仔细说明下吧
元类是定义类结构属性的, 而类里的 "__new__", "__init__" 方法, 是处理类实例用的
我们所定义的每一个类, 都可以理解为是 type 的一个实例
好, 说回到 "__new__" 和 "__call__"
元类中, "__new__" 会在你定义类的时候执行, 只执行一次, 如果有两个类使用了这个元类, OK, 会执行两次
而__call__会在你每次实例化的时候调用, 其实和Foo.__new__是一样的, 意思是, 如果你的Foo定义了__new__, 元类中的__call__便不会执行
元类的 "__new__" 可以变更你所定义的类型, 我在这里定义Foo成了一个list
写这么多很辛苦的, 能正解理解metaclass的人非常的少, 不知题主要怎么感谢我