以下代码有效:
class Foo(tuple):
def __init__(self, b):
super(Foo, self).__init__(tuple(b))
if __name__ == '__main__':
print Foo([3, 4])
$ python play.py
结果:
play.py:4: DeprecationWarning: object.__init__() takes no parameters
super(Foo, self).__init__(tuple(b))
(3, 4)
但不是以下内容:
class Foo(tuple):
def __init__(self, a, b):
super(Foo, self).__init__(tuple(b))
if __name__ == '__main__':
print Foo(None, [3, 4])
$ python play.py
结果:
Traceback (most recent call last):
File "play.py", line 7, in <module>
print Foo(None, [3, 4])
TypeError: tuple() takes at most 1 argument (2 given)
为什么?
答案 0 :(得分:64)
因为元组是不可变的,所以你必须改为覆盖__new__
:
object.__new__(cls[, ...])
被调用以创建新的实例 班
cls
。__new__()
是静态的 方法(特殊装,所以你不需要 宣称它是这样的 实例所在的类 要求作为其第一个论点。该 剩下的论点是那些传递的 到对象构造函数表达式 (对班级的呼唤)。回报__new__()
的值应该是新的 对象实例(通常是一个实例cls
)。典型的实现创建一个新的 通过调用类的实例 超类的
__new__()
方法使用super(currentclass, cls).__new__(cls[, ...])
有适当的论据和 然后修改新创建的 返回之前必要的实例 它如果
__new__()
返回的实例cls
,然后是新实例__init__()
方法将像__init__(self[, ...])
一样被调用,其中self是新实例,其余是 参数与传递的相同 到__new__()
。如果
__new__()
没有返回cls
的实例,然后是新的 实例的__init__()
方法不会 被调用。
__new__()
主要用于允许不可变类型的子类(如int
,str
或tuple
)进行自定义 实例创建。它也是常见的 在自定义元类中重写 为了自定义类创建。
答案 1 :(得分:48)
要分配您需要覆盖__new__
方法所需的元组值:
class Foo(tuple):
def __new__ (cls, a, b):
return super(Foo, cls).__new__(cls, tuple(b))
这些参数似乎被元组类的__init__
实现忽略了,但是如果你需要做一些初始化的东西,你可以按如下方式进行:
class Foo(tuple):
def __new__ (cls, a, b):
return super(Foo, cls).__new__(cls, tuple(b))
def __init__(self, a, b):
self.a=a
self.b=b
if __name__ == '__main__':
foo = Foo(None, [3, 4])
print foo
print foo.a
print foo.b