__new__ 和 __init__ 顺序之间的差异 Python2/3

Difference between __new__ and __init__ order in Python2/3

在 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 中,由于缺少 __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"
"""

在Python2中,我什至把元类弄得乱七八糟。

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 的方式来做到这一点。

在Python2中,您需要使用新式classes才能使classes正常工作。这意味着您需要将 class 定义为 class Foo(object)。那么你的第一个例子将适用于 Python 2 和 Python 3.