使用多个__init__参数对Python元组进行子类化

时间:2022-09-05 00:30:14

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 
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 
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?

为什么?

2 个解决方案

#1


58  

Because tuples are immutable, you have to override __new__ instead:

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

python docs

python docs

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

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).

被调用以创建类cls的新实例。 __new __()是一个静态方法(特殊的,因此您不需要声明它),它将请求实例的类作为其第一个参数。其余参数是传递给对象构造函数表达式的参数(对类的调用)。 __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 __()方法创建类的新实例,然后在返回之前根据需要修改新创建的实例它。

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是新实例,其余参数与传递给的相同。 __新__()。

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. It is also commonly overridden in custom metaclasses in order to customize class creation.

__new __()主要用于允许不可变类型的子类(如int,str或tuple)自定义实例创建。它也通常在自定义元类中重写,以自定义类创建。

#2


41  

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

#1


58  

Because tuples are immutable, you have to override __new__ instead:

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

python docs

python docs

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

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).

被调用以创建类cls的新实例。 __new __()是一个静态方法(特殊的,因此您不需要声明它),它将请求实例的类作为其第一个参数。其余参数是传递给对象构造函数表达式的参数(对类的调用)。 __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 __()方法创建类的新实例,然后在返回之前根据需要修改新创建的实例它。

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是新实例,其余参数与传递给的相同。 __新__()。

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. It is also commonly overridden in custom metaclasses in order to customize class creation.

__new __()主要用于允许不可变类型的子类(如int,str或tuple)自定义实例创建。它也通常在自定义元类中重写,以自定义类创建。

#2


41  

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