55 votes

Sous-classement de tuple Python avec plusieurs arguments __init__

Le code suivant fonctionne:

 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)
 

Mais pas les suivants:

 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)
 

Pourquoi?

71voto

gnibbler Points 103484

Parce que les tuples sont immuables, vous devez remplacer __new__ à la place:

python docs

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

Appelé à créer une nouvelle instance de classe cls.__new__() est statique méthode (spécial tubés si vous n'avez pas besoin le déclarer comme tel) qui prend l' la classe d'une instance qui a été demandé en tant que premier argument. L' arguments restants sont ceux qui sont passés le constructeur de l'objet de l'expression (l'appel à la classe). Le retour la valeur de __new__() devrait être le nouveau l'instance d'un objet (généralement une instance d' cls).

Typique des implémentations de créer un nouveau instance de la classe en invoquant la superclasse, __new__() méthode à l'aide de super(currentclass, cls).__new__(cls[, ...]) avec les arguments appropriés et puis de modifier le nouvellement créé exemple que nécessaire avant de retourner c'.

Si __new__() retourne une instance de cls, alors que la nouvelle instance de l' __init__() méthode sera invoquée comme __init__(self[, ...]), où l'auto est la nouvelle instance et le reste les arguments sont les mêmes que pour passé d' __new__().

Si __new__() ne renvoie pas une exemple d' cls, alors que les nouveaux l'instance de l' __init__() méthode ne sera pas être invoquée.

__new__() est destiné principalement à permettre aux sous-classes de immuable types (comme int, strou tuple) à personnaliser création de l'instance. Il est aussi couramment substituée dans des metaclasses dans afin de personnaliser la création de classes.

54voto

Jonatan Anauati Points 169

Pour affecter la valeur du tuple, vous devez remplacer la méthode __new__ :

 class Foo(tuple):

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

Les arguments semblent être ignorés par l'implémentation __init__ de la classe tuple, mais si vous avez besoin de faire quelques trucs init, vous pouvez le faire comme suit:

 class Foo(tuple):

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

    def __init__(self, a, b):
        super(Foo, self).__init__(a,b)
        self.a=a
        self.b=b

if __name__ == '__main__':
    foo = Foo(None, [3, 4])
    print foo
    print foo.a
    print foo.b
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X