我只是想简化我的一个类,并引入了一些与flyweight设计模式相同的功能.
但是,我有点困惑,为什么__init__总是被称为__new__.我没想到这个.任何人都可以告诉我为什么会这样,以及我如何能够实现这个功能呢?(除了将实施放入__new__感觉相当hacky之外.)
这是一个例子:
class A(object):
_dict = dict()
def __new__(cls):
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return super(A, cls).__new__(cls)
def __init__(self):
print "INIT"
A._dict['key'] = self
print ""
a1 = A()
a2 = A()
a3 = A()
Run Code Online (Sandbox Code Playgroud)
输出:
NEW
INIT
EXISTS
INIT
EXISTS
INIT
Run Code Online (Sandbox Code Playgroud)
为什么?
根据我的理解,__call__类内部的方法实现了函数调用运算符,例如:
class Foo:
def __init__(self):
print("I'm inside the __init__ method")
def __call__(self):
print("I'm inside the __call__ method")
x = Foo() #outputs "I'm inside the __init__ method"
x() #outputs "I'm inside the __call__ method"
Run Code Online (Sandbox Code Playgroud)
但是,我正在阅读Python Cookbook,作者定义了一个元类来控制实例创建,因此您无法直接实例化对象。他是这样做的:
class NoInstance(type):
def __call__(self, *args, **kwargs):
raise TypeError("Can't instantaite class directly")
class Spam(metaclass=NoInstance):
@staticmethod
def grok(x):
print("Spam.grok")
Spam.grok(42) #outputs "Spam.grok"
s = Spam() #outputs TypeError: Can't instantaite class directly
Run Code Online (Sandbox Code Playgroud)
但是,我不明白的是如何s()不被调用,但它的__call__方法被调用了。这是如何运作的?