使用多个 __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__() 主要用于允许不可变类型的子类(如 intstrtuple) 自定义 实例创建。这也很常见 在自定义元类中被覆盖 为了自定义类创建。

【讨论】:

有人能告诉我如何引用整个块,这样双下划线就不是粗体了吗? 选择整个粘贴的文本并点击引号图标(文本框顶部的黑色图标)。 我把它们都换成了 _【参考方案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__ 参数子类化元组的主要内容,如果未能解决你的问题,请参考以下文章

使用具有tensorflow对象的元组创建类对象

随机矩阵:int()参数必须是字符串或数字,而不是'元组'

面向对象三大特性之继承

面向对象三大特性之继承

Python 避免字典和元组的多重嵌套

python_高级