【问题标题】:Subclassing tuple with multiple __init__ arguments使用多个 __init__ 参数子类化元组
【发布时间】: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)

为什么?

【问题讨论】:

    标签: python inheritance subclass tuples


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-24
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      • 2022-10-13
      • 2012-04-25
      • 2012-03-22
      相关资源
      最近更新 更多