在Python 3中,如果返回任何不是cls
实例的值,则永远不会调用__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中,由于缺少TypeError: this constructor takes no arguments
,这似乎会引发__init__
。我可以通过继承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中,我甚至搞乱了元类。
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方法可以做到这一点。
答案 0 :(得分:6)
在Python 2中,您需要使用新式类来使类正常工作。这意味着您需要将类定义为class Foo(object)
。然后你的第一个例子将在Python 2和Python 3中都有效。