python 具有多个 __init__ 参数的子类化元组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1565374/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 22:35:36  来源:igfitidea点击:

Subclassing tuple with multiple __init__ arguments

pythoninheritancesubclasstuples

提问by Sridhar Ratnakumar

The following code works:

以下代码有效:

class Foo(tuple):

    def __init__(self, b):
        super(Foo, self).__init__(tuple(b))

if __name__ == '__main__':
    print Foo([3, 4])

$ python play.py 

Result:

结果:

play.py:4: DeprecationWarning: object.__init__() takes no parameters
  super(Foo, self).__init__(tuple(b))
(3, 4)

But not the following:

但不是以下:

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 

Result:

结果:

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)

Why?

为什么?

回答by John La Rooy

Because tuples are immutable, you have to override __new__instead:

因为元组是不可变的,所以你必须重写__new__

python docs

蟒蛇文档

object.__new__(cls[, ...])

Called to create a new instance of class cls. __new__()is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class). The return value of __new__()should be the new object instance (usually an instance of cls).

Typical implementations create a new instance of the class by invoking the superclass's __new__()method using super(currentclass, cls).__new__(cls[, ...])with appropriate arguments and then modifying the newly-created instance as necessary before returning it.

If __new__()returns an instance of cls, then the new instance's __init__()method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().

If __new__()does not return an instance of cls, then the new instance's __init__()method will not be invoked.

__new__()is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

object.__new__(cls[, ...])

调用以创建 class 的新实例cls__new__()是一个静态方法(特殊情况,因此您无需如此声明),它将请求实例的类作为其第一个参数。其余参数是传递给对象构造函数表达式(对类的调用)的参数。的返回值__new__()应该是新的对象实例(通常是 的实例cls)。

典型的实现通过__new__()使用super(currentclass, cls).__new__(cls[, ...])适当的参数调用超类的方法来 创建类的新实例,然后在返回之前根据需要修改新创建的实例。

如果__new__()返回 的实例 cls,则新实例的 __init__()方法将像 一样被调用__init__(self[, ...]),其中 self 是新实例,其余参数与传递给 的参数相同__new__()

如果__new__()不返回 的实例cls,则__init__()不会调用新实例的方法。

__new__()主要是用来允许不可改变的类型的子类(例如 intstrtuple)来定制实例创建。它也通常在自定义元类中被覆盖以自定义类创建。

回答by Jonatan Anauati

To assign the tuple value you need to override the __new__method:

要分配元组值,您需要覆盖该__new__方法:

class Foo(tuple):

    def __new__ (cls, a, b):
        return super(Foo, cls).__new__(cls, tuple(b))

The arguments seem to be ignored by the __init__implementation of the tuple class, but if you need to do some init stuff you can do it as follows:

__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