使用多个 __init__ 参数子类化元组
Posted
技术标签:
【中文标题】使用多个 __init__ 参数子类化元组【英文标题】:Subclassing tuple with multiple __init__ arguments 【发布时间】:2010-12-06 15:03:35 【问题描述】:以下代码有效:
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)
为什么?
【问题讨论】:
【参考方案1】:因为元组是不可变的,所以您必须改写 __new__
:
python docs
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
) 自定义 实例创建。这也很常见 在自定义元类中被覆盖 为了自定义类创建。
【讨论】:
有人能告诉我如何引用整个块,这样双下划线就不是粗体了吗? 选择整个粘贴的文本并点击引号图标(文本框顶部的黑色图标)。 我把它们都换成了 _【参考方案2】:要分配元组值,您需要覆盖__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
【讨论】:
以上是关于使用多个 __init__ 参数子类化元组的主要内容,如果未能解决你的问题,请参考以下文章