4
在Python 3中,如果返回的值不是cls
的實例,則不會調用__init__
方法。這樣我就可以,例如,做到這一點:Python2/3中的__new__和__init__命令之間的區別
class Foo:
@staticmethod
def bar(n):
return n * 5
def __new__(cls, n):
return Foo.bar(n)
print(Foo(3)) # => 15
我的印象是,順序爲__call__
下(如果它是一個實例) - >__new__
- >__init__
。
但是,在Python 2中,由於缺少__init__
,似乎會增加TypeError: this constructor takes no arguments
。我可以通過繼承object
來解決這個問題。所以,運行這個:
class Foo:
def __new__(cls, *args, **kwargs):
print("new called")
def __init__(self, *args, **kwargs):
print("init called")
Foo()
"""
Python2: "init called"
Python3: "new called"
"""
在Python 2中,我甚至搞砸了metaclasses。
Meta = type("Meta", (type,), dict(__call__=lambda self, x: x * 5))
class Foo(object):
__metaclass__ = Meta
print(Foo(4)) # => 20
但是這在Python3中不起作用,因爲init/new方法似乎被顛倒過來。
是否有任何Python2/3兼容的方式來做到這一點?
解決方案:
這是我做到的。我不喜歡它,但它的工作原理:
class Foo(object):
@staticmethod
def __call__(i):
return i * 5
def __new__(cls, i):
return Foo.__call__(i)
當然,這樣做有更多的pythonic方法。
該死的打敗了我,但驗證這是爲什麼。 –
太容易了。謝謝! – Goodies
你介意解釋我看到的行爲嗎? – Goodies