__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.
在 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.