una propias procedimientos por pasar parametro opcionales lista funciones explicacion como argumentos argumento python

propias - pasar una lista como parametro en python



forma correcta de usar super(paso de argumento) (3)

Así que estaba siguiendo el mal considerado de Python , y fui a probar sus ejemplos.

Sin embargo, en el ejemplo 1-3 , que se supone que muestra la forma correcta de llamar a super cuando se manejan métodos __init__ que esperan diferentes argumentos, el funcionamiento no funciona.

Esto es lo que obtengo:

~ $ python example1-3.py MRO: [''E'', ''C'', ''A'', ''D'', ''B'', ''object''] E arg= 10 C arg= 10 A D arg= 10 B Traceback (most recent call last): File "Download/example1-3.py", line 27, in <module> E(arg=10) File "Download/example1-3.py", line 24, in __init__ super(E, self).__init__(arg, *args, **kwargs) File "Download/example1-3.py", line 14, in __init__ super(C, self).__init__(arg, *args, **kwargs) File "Download/example1-3.py", line 4, in __init__ super(A, self).__init__(*args, **kwargs) File "Download/example1-3.py", line 19, in __init__ super(D, self).__init__(arg, *args, **kwargs) File "Download/example1-3.py", line 9, in __init__ super(B, self).__init__(*args, **kwargs) TypeError: object.__init__() takes no parameters

Parece que el object sí viola una de las mejores prácticas mencionadas en el documento, que es que los métodos que usan super deben aceptar *args y **kwargs .

Ahora, obviamente, el Sr. Knight esperaba que sus ejemplos funcionaran, ¿es esto algo que cambió en las versiones recientes de Python? Revisé 2.6 y 2.7, y falla en ambos.

Entonces, ¿cuál es la forma correcta de lidiar con este problema?


A veces, dos clases pueden tener algunos nombres de parámetros en común. En ese caso, no puede sacar los pares clave-valor de **kwargs o eliminarlos de *args . En cambio, puede definir una clase Base que, a diferencia del object , absorba / ignore los argumentos:

class Base(object): def __init__(self, *args, **kwargs): pass class A(Base): def __init__(self, *args, **kwargs): print "A" super(A, self).__init__(*args, **kwargs) class B(Base): def __init__(self, *args, **kwargs): print "B" super(B, self).__init__(*args, **kwargs) class C(A): def __init__(self, arg, *args, **kwargs): print "C","arg=",arg super(C, self).__init__(arg, *args, **kwargs) class D(B): def __init__(self, arg, *args, **kwargs): print "D", "arg=",arg super(D, self).__init__(arg, *args, **kwargs) class E(C,D): def __init__(self, arg, *args, **kwargs): print "E", "arg=",arg super(E, self).__init__(arg, *args, **kwargs) print "MRO:", [x.__name__ for x in E.__mro__] E(10)

rendimientos

MRO: [''E'', ''C'', ''A'', ''D'', ''B'', ''Base'', ''object''] E arg= 10 C arg= 10 A D arg= 10 B

Tenga en cuenta que para que esto funcione, Base debe ser la penúltima clase en el MRO.


Como se explica en super () de Python, se considera super , una forma es que la clase coma los argumentos que requiere y pase el resto. Por lo tanto, cuando la cadena de llamadas alcanza el object , se han consumido todos los argumentos, y se object.__init__ sin argumentos (como se espera). Entonces su código debería verse así:

class A(object): def __init__(self, *args, **kwargs): print "A" super(A, self).__init__(*args, **kwargs) class B(object): def __init__(self, *args, **kwargs): print "B" super(B, self).__init__(*args, **kwargs) class C(A): def __init__(self, arg, *args, **kwargs): print "C","arg=",arg super(C, self).__init__(*args, **kwargs) class D(B): def __init__(self, arg, *args, **kwargs): print "D", "arg=",arg super(D, self).__init__(*args, **kwargs) class E(C,D): def __init__(self, arg, *args, **kwargs): print "E", "arg=",arg super(E, self).__init__(*args, **kwargs) print "MRO:", [x.__name__ for x in E.__mro__] E(10, 20, 30)


Si vas a tener mucha herencia (este es el caso aquí) te sugiero que pases todos los parámetros usando **kwargs , y luego los **kwargs justo después de usarlos (a menos que los necesites en las clases altas).

class First(object): def __init__(self, *args, **kwargs): self.first_arg = kwargs.pop(''first_arg'') super(First, self).__init__(*args, **kwargs) class Second(First): def __init__(self, *args, **kwargs): self.second_arg = kwargs.pop(''second_arg'') super(Second, self).__init__(*args, **kwargs) class Third(Second): def __init__(self, *args, **kwargs): self.third_arg = kwargs.pop(''third_arg'') super(Third, self).__init__(*args, **kwargs)

Esta es la forma más simple de resolver ese tipo de problemas.

third = Third(first_arg=1, second_arg=2, third_arg=3)