Se eu definir um método de classe com um argumento de palavra-chave assim:
class foo(object):
def foodo(thing=None, thong='not underwear'):
print thing if thing else "nothing"
print 'a thong is',thong
chamar o método gera um TypeError
:
myfoo = foo()
myfoo.foodo(thing="something")
...
TypeError: foodo() got multiple values for keyword argument 'thing'
O que está acontecendo?
python
class
python-2.7
methods
drevicko
fonte
fonte
self
é melhor do que implícitothis
.Respostas:
O problema é que o primeiro argumento passado aos métodos de classe em python é sempre uma cópia da instância de classe na qual o método é chamado, normalmente rotulado
self
. Se a classe for declarada assim:comporta-se como esperado.
Explicação:
Sem
self
como o primeiro parâmetro, quandomyfoo.foodo(thing="something")
é executado, ofoodo
método é chamado com argumentos(myfoo, thing="something")
. A instânciamyfoo
é então atribuída athing
(já quething
é o primeiro parâmetro declarado), mas o python também tenta atribuir"something"
athing
, daí a Exception.Para demonstrar, tente executar isso com o código original:
Você produzirá como:
Você pode ver que 'coisa' recebeu uma referência à instância 'myfoo' da classe 'foo'. Esta seção dos documentos explica como os argumentos das funções funcionam um pouco mais.
fonte
Obrigado pelas mensagens instrutivas. Gostaria de manter uma observação de que, se você está recebendo "TypeError: foodo (), possui vários valores para o argumento de palavra-chave 'coisa'", também pode ser que você esteja passando o 'self' como parâmetro quando chamando a função (provavelmente porque você copiou a linha da declaração de classe - é um erro comum quando alguém está com pressa).
fonte
@classmethod
, sendo a solução usada emsuper().function(...)
vez de<parentclass>.function(cls, ...)
.Isso pode ser óbvio, mas pode ajudar alguém que nunca viu isso antes. Isso também acontece para funções regulares se você atribuir um parâmetro por posição e explicitamente por nome.
fonte
basta adicionar o decorador 'staticmethod' para funcionar e o problema é corrigido
fonte
myfoo.foodo(thing="something")
, thing = "something" será atribuído ao primeiro argumento, em vez do auto-argumento implícito.self
Quero adicionar mais uma resposta:
there is difference between parameter and argument
você pode ler em detalhes sobre aqui Argumentos e Parâmetros em pythonjá que temos três parâmetros:
a é parâmetro posicional
b = 1 é a palavra-chave e o parâmetro padrão
* args é um parâmetro de comprimento variável
então, primeiro atribuímos um parâmetro como posicional, significa que precisamos fornecer valor ao argumento posicional em sua ordem de posição, aqui a ordem importa. mas estamos passando o argumento 1 no lugar de uma função de chamada e, em seguida, também estamos fornecendo valor a, tratando como argumento de palavra-chave. agora a tem dois valores:
um é o valor posicional: a = 1
segundo é o valor com palavras-chave que é = 12
Solução
Temos que mudar
hello(1, 2, 3, 4,a=12)
parahello(1, 2, 3, 4,12)
agora, a obterá apenas um valor posicional que é 1 e b obterá o valor 2 e o restante dos valores obterá * args (parâmetro de comprimento variável)informação adicional
se quisermos que * args deve ter 2,3,4 e a deve ter 1 eb deve ter 12
então podemos fazer assim
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)
Algo mais :
resultado :
fonte
Este erro também pode ocorrer se você passar um argumento de palavra-chave para o qual uma das chaves é semelhante (tem o mesmo nome de sequência) a um argumento posicional.
"fogo" foi aceito no argumento 'bar'. E, no entanto, há outro argumento 'bar' presente em kwargs.
Você precisaria remover o argumento de palavra-chave dos kwargs antes de passá-lo para o método
fonte
Isso também pode acontecer no Django se você estiver usando jquery ajax para url que reverte para uma função que não contém o parâmetro 'request'
fonte