【发布时间】:2014-10-30 12:47:17
【问题描述】:
我正在将一些代码从 Python 2 迁移到 Python 3,我得到了不同的行为。查看“发生了什么变化”的列表并没有指出任何相关的差异,但大概我错过了一个大差异。
我已经尽可能简化了我的代码以获得这个“最小的错误程序”:
def decorator(Type):
""" This is a class decorator. It replaces a class with a subclass which
*should be* equivalent.
The result works on Python 2.7 but not on Python 3.4. """
class FactorySubclass(Type):
""" This subclasses from the provided type, and overrides the __new__
and __init__ methods, but replaces them with exact equivalents,
so I can't see how this has any effect. """
def __new__(cls, *args, **kwargs):
# Simplified this code to do basically nothing.
# If this line is removed, it works on both versions.
return Type.__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
# Simplified this code to do basically nothing.
Type.__init__(self, *args, **kwargs)
return FactorySubclass
@decorator
class ExampleClass(object):
def __init__(self, param=3):
print("Constructed example instance")
ec = ExampleClass(param=5)
此代码在 Python 2.7 中运行并打印 Constructed example instance。
此代码失败,并在 Python 3.4 中转储堆栈跟踪。
Traceback (most recent call last):
File "mfp.py", line 31, in <module>
ec = ExampleClass(param=5)
File "mfp.py", line 16, in __new__
return Type.__new__(cls, *args, **kwargs)
TypeError: object() takes no parameters
通常,此错误意味着有人拼错了__init__(因此构造函数参数绕过相关类并被提供给object 的无参数构造函数,但这里似乎并非如此。
哦,事后我确认了,是的,param 的值在 Python 2.7 中是 5。
2to3 为它提供了一份健康证明。
请给我一个指向 Python 3 中的更改的指针,该更改将使此代码无效,以便我可以阅读更多相关信息。
【问题讨论】:
-
这看起来像是 Why does object.__new__ work differently in these three cases 的骗子,我会调查的。
-
是的,这是因为
ExampleClass没有自己的__new__方法。 -
@Martijn:鉴于周围的行为已经改变,它似乎很可能是相关的。但是,您的回答指出“如果
__new__和__init__都没有被覆盖,Python 只会抱怨__init__不支持参数”。在这种情况下,两者都已被覆盖。 -
向
Example添加一个__new__方法,错误就消失了。
标签: python python-3.x python-3.4