Si defino un método de clase con un argumento de palabra clave así:
class foo(object):
def foodo(thing=None, thong='not underwear'):
print thing if thing else "nothing"
print 'a thong is',thong
llamar al método genera un TypeError
:
myfoo = foo()
myfoo.foodo(thing="something")
...
TypeError: foodo() got multiple values for keyword argument 'thing'
¿Que esta pasando?
python
class
python-2.7
methods
drevicko
fuente
fuente
self
es mejor que implícitothis
.Respuestas:
El problema es que el primer argumento pasado a los métodos de clase en python es siempre una copia de la instancia de clase en la que se llama al método, normalmente etiquetado
self
. Si la clase se declara así:Se comporta como se esperaba.
Explicación:
Sin
self
como primer parámetro, cuandomyfoo.foodo(thing="something")
se ejecuta, elfoodo
método se llama con argumentos(myfoo, thing="something")
. El ejemplomyfoo
se asigna athing
(ya quething
es el parámetro de primera declarado), pero Python también intentos de asignar"something"
athing
, por lo tanto, la excepción.Para demostrarlo, intente ejecutar esto con el código original:
Saldrás como:
Puede ver que a 'cosa' se le ha asignado una referencia a la instancia 'myfoo' de la clase 'foo'. Esta sección de los documentos explica cómo los argumentos de función funcionan un poco más.
fuente
Gracias por los mensajes instructivos. Solo me gustaría tener en cuenta que si obtiene "TypeError: foodo () tiene múltiples valores para el argumento de palabra clave 'cosa'", también puede ser que esté pasando erróneamente el 'yo' como parámetro cuando llamar a la función (probablemente porque copió la línea de la declaración de clase, es un error común cuando uno tiene prisa).
fuente
@classmethod
, la solución es usar ensuper().function(...)
lugar de<parentclass>.function(cls, ...)
.Esto puede ser obvio, pero podría ayudar a alguien que nunca lo haya visto antes. Esto también sucede para las funciones regulares si asigna erróneamente un parámetro por posición y explícitamente por nombre.
fuente
simplemente agregue el decorador 'staticmethod' a la función y el problema está solucionado
fuente
myfoo.foodo(thing="something")
, se asignará thing = "something" al primer argumento, en lugar del argumento propio implícito.self
Quiero agregar una respuesta más:
there is difference between parameter and argument
puedes leer en detalle aquí Argumentos y parámetros en pythonya que tenemos tres parámetros:
a es parámetro posicional
b = 1 es palabra clave y parámetro predeterminado
* args es un parámetro de longitud variable
así que primero asignamos un parámetro posicional, significa que tenemos que proporcionar valor al argumento posicional en su orden de posición, aquí el orden importa. pero estamos pasando el argumento 1 en el lugar de a en la función de llamada y luego también estamos proporcionando valor a a, tratándolo como argumento de palabra clave. ahora a tiene dos valores:
uno es el valor posicional: a = 1
segundo es el valor de palabras clave que es a = 12
Solución
Tenemos que cambiar
hello(1, 2, 3, 4,a=12)
a,hello(1, 2, 3, 4,12)
por lo que ahora a obtendrá un solo valor posicional que es 1 yb obtendrá el valor 2 y el resto de valores obtendrá * args (parámetro de longitud variable)Información Adicional
si queremos que * args debería obtener 2,3,4 y a debería obtener 1 yb debería obtener 12
entonces podemos hacer así
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)
Algo más :
salida:
fuente
Este error también puede ocurrir si pasa un argumento de palabra clave para el cual una de las claves es similar (tiene el mismo nombre de cadena) a un argumento posicional.
"fuego" ha sido aceptado en el argumento 'bar'. Y sin embargo, hay otro argumento 'bar' presente en kwargs.
Tendría que eliminar el argumento de la palabra clave de los kwargs antes de pasarlo al método.
fuente
También esto puede suceder en Django si está utilizando jquery ajax para url que revierte a una función que no contiene el parámetro 'request'
fuente