简体   繁体   English

使用多个__init__参数将元组子类化

[英]Subclassing tuple with multiple __init__ arguments

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? 为什么?

Because tuples are immutable, you have to override __new__ instead: 因为元组是不可变的,所以您必须改写__new__

python docs python文档

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

Called to create a new instance of class cls . 调用以创建类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. __new__()是一个静态方法(特殊情况,因此您不必这样声明),它将实例被请求的类作为其第一个参数。 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 ). __new__()的返回值应该是新的对象实例(通常是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. 典型的实现通过使用具有适当参数的super(currentclass, cls).__new__(cls[, ...])调用超类的__new__()方法,然后在返回之前根据需要修改新创建的实例,来创建super(currentclass, cls).__new__(cls[, ...])的新实例。它。

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__() . 如果__new__()返回cls的实例,则将调用新实例的__init__()方法,就像__init__(self[, ...]) ,其中self是新实例,其余参数与传递给__new__()

If __new__() does not return an instance of cls , then the new instance's __init__() method will not be invoked. 如果__new__()没有返回cls的实例,则将不会调用新实例的__init__()方法。

__new__() is intended mainly to allow subclasses of immutable types (like int , str , or tuple ) to customize instance creation. __new__()主要用于允许不可变类型的子类(例如intstrtuple )自定义实例创建。 It is also commonly overridden in custom metaclasses in order to customize class creation. 为了自定义类的创建,它通常也被自定义元类覆盖。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM