Às vezes, parece natural ter um parâmetro padrão que é uma lista vazia. Ainda assim, o Python apresenta um comportamento inesperado nessas situações .
Se, por exemplo, tenho uma função:
def my_func(working_list = []):
working_list.append("a")
print(working_list)
A primeira vez que for chamado de padrão funcionará, mas as chamadas posteriores atualizarão a lista existente (com um "a" em cada chamada) e imprimirão a versão atualizada.
Então, qual é a forma pítônica de obter o comportamento que desejo (uma lista nova em cada ligação)?
python
python-3.x
John Mulder
fonte
fonte
Respostas:
Os documentos dizem que você deve usar
None
como padrão e testar explicitamente no corpo da função.fonte
f()
uma lista, terá que chamar of(*l)
que é bruto. Pior, implementarmate(['larch', 'finch', 'robin'], ['bumble', 'honey', 'queen'])
seria SUCK w / varargs. Muito melhor se fordef mate(birds=[], bees=[]):
.As respostas existentes já forneceram as soluções diretas solicitadas. No entanto, como essa é uma armadilha muito comum para novos programadores de Python, vale a pena adicionar a explicação de por que o python se comporta dessa maneira, que está bem resumida no " Guia do Hitchhikers para Python " como " Argumentos padrão mutáveis ": http: // docs .python-guide.org / en / latest / writing / gotchas /
Citação: " Os argumentos padrão do Python são avaliados uma vez quando a função é definida, não toda vez que a função é chamada (como em Ruby, digamos). Isso significa que se você usar um argumento padrão mutável e alterá-lo, você terá modificou esse objeto para todas as chamadas futuras para a função também "
Código de amostra para implementá-lo:
fonte
Não que isso importe neste caso, mas você pode usar a identidade do objeto para testar nenhum:
Você também pode tirar proveito de como o operador booleano ou é definido em python:
No entanto, isso irá se comportar de forma inesperada se o chamador fornecer uma lista vazia (que conta como falsa) como working_list e esperar que sua função modifique a lista fornecida por ele.
fonte
Se a intenção da função é modificar o parâmetro passado como
working_list
, consulte a resposta de HenryR (= None, verifique se há None dentro).Mas se você não pretendia transformar o argumento, apenas use-o como ponto de partida para uma lista, você pode simplesmente copiá-lo:
(ou, neste caso simples,
print starting_list + ["a"]
mas acho que foi apenas um exemplo de brinquedo)Em geral, modificar seus argumentos é um estilo ruim em Python. As únicas funções que podem sofrer mutação em um objeto são os métodos do objeto. É ainda mais raro transformar um argumento opcional - um efeito colateral que acontece apenas em algumas chamadas é realmente a melhor interface?
Se você fizer isso a partir do hábito C de "argumentos de saída", isso é completamente desnecessário - você sempre pode retornar vários valores como uma tupla.
Se você fizer isso para construir com eficiência uma longa lista de resultados sem construir listas intermediárias, considere escrevê-la como um gerador e usá-la
result_list.extend(myFunc())
ao chamá-la. Dessa forma, suas convenções de chamada permanecem muito claras.Um padrão em que a mutação de um arg opcional é frequentemente feita é um arg "memo" oculto em funções recursivas:
fonte
Posso estar fora do assunto, mas lembre-se de que se você quiser apenas passar um número variável de argumentos, a forma pythônica é passar uma tupla
*args
ou um dicionário**kargs
. Eles são opcionais e são melhores do que a sintaxemyFunc([1, 2, 3])
.Se você quiser passar uma tupla:
Se você quiser passar um dicionário:
fonte
Já foram fornecidas respostas boas e corretas. Eu só queria dar outra sintaxe para escrever o que você deseja fazer, o que acho mais bonito quando você, por exemplo, deseja criar uma classe com listas vazias padrão:
Este snippet usa a sintaxe do operador if else. Eu gosto especialmente porque é uma linha simples sem dois pontos, etc. envolvida e quase se parece com uma frase normal em inglês. :)
No seu caso, você poderia escrever
fonte
Eu fiz o curso de extensão UCSC
Python for programmer
O que é verdadeiro para: def Fn (dados = []):
Responda:
fonte