Python2/3中的__new__和__init__命令之间的区别
问题描述:
在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方法。
答
在Python 2中,您需要使用新式类来使类正常工作。这意味着您需要将您的课程定义为class Foo(object)
。然后你的第一个例子将在Python 2和Python 3中工作。
该死的打败了我,但验证这是为什么。 –
太容易了。谢谢! – Goodies
你介意解释我看到的行为吗? – Goodies