2009-10-14 17 views
43

El siguiente código funciona:tupla subclases Python con múltiples argumentos __init__

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) 

Pero no lo siguiente:

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) 

¿Por qué?

Respuesta

55

Debido tuplas son inmutables, tiene que anular __new__ lugar:

python docs

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

llama para crear una nueva instancia de la clase cls. __new__() es un método estático (con carcasa especial, por lo que no necesita declararlo como tal) que toma la clase de la cual una instancia fue solicitada como su primer argumento. Los argumentos restantes son los que pasaron a la expresión del constructor de objetos (la llamada a la clase). El valor de retorno de __new__() debe ser la nueva instancia de objeto (normalmente una instancia de cls).

implementaciones típicas crean un nuevo instancia de la clase invocando __new__() método las de superclase usando super(currentclass, cls).__new__(cls[, ...]) con argumentos apropiados y luego modificando el recién creado ejemplo como sea necesario antes de volver ella.

Si __new__() devuelve una instancia de cls, entonces __init__() el método de la nueva instancia se invocará como __init__(self[, ...]), donde uno mismo es la nueva instancia y las argumentos restantes son los mismos que se pasó a __new__().

Si __new__() no devuelve una instancia de cls, a continuación, el nuevo método de ejemplo __init__() no ser invocada.

__new__() está destinado principalmente para permitir subclases de tipos inmutables (como int, str, o tuple) para personalizar creación de la instancia. También es comúnmente anulado en metaclases personalizadas en para personalizar la creación de clase.

+0

¿alguien me puede decir cómo se cita todo el bloque para que los doble guts no signifiquen negrita? –

+0

Seleccione todo el texto pegado y haga clic en el icono de cita (icono negro en la parte superior del cuadro de texto). –

+0

No funcionó, pero lo sangra un poco –

39

Para asignar el valor tupla que necesita para anular el __new__ método:

class Foo(tuple): 

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

Los argumentos parecen ser ignorados por el __init__ implementación de la clase tupla, pero si usted tiene que hacer algunas cosas init puede hacerlo de la siguiente manera:

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