Adicionando valor de parâmetro padrão com o tipo hint no Python


236

Se eu tiver uma função como esta:

def foo(name, opts={}):
  pass

E eu quero adicionar dicas de tipo aos parâmetros, como faço isso? A maneira que assumi me dá um erro de sintaxe:

def foo(name: str, opts={}: dict) -> str:
  pass

O seguinte não gera um erro de sintaxe, mas não parece a maneira intuitiva de lidar com este caso:

def foo(name: str, opts: dict={}) -> str:
  pass

Não consigo encontrar nada na typingdocumentação ou em uma pesquisa no Google.

Edit: Eu não sabia como os argumentos padrão funcionavam no Python, mas, para o bem desta pergunta, vou manter os exemplos acima. Em geral, é muito melhor fazer o seguinte:

def foo(name: str, opts: dict=None) -> str:
  if not opts:
    opts={}
  pass

4
A última função é a maneira correta. É da mesma maneira que a scalalinguagem também.
Israel Unterman

14
você tem um tipo padrão mutável - que levará a problemas
noɥʇʎԀʎzɐɹƆ

consulte a minha resposta de atualização, @josh
noɥʇʎԀʎzɐɹƆ 2/08/16

@ noɥʇʎԀʎzɐɹƆ Não, a menos que você esteja usando, por exemplo, memorização. : P
Mateen Ulhaq

Respostas:


281

Seu segundo caminho está correto.

def foo(opts: dict = {}):
    pass

print(foo.__annotations__)

isso gera

{'opts': <class 'dict'>}

É verdade que não está listado no PEP 484 , mas as dicas de tipo são uma aplicação de anotações de funções, documentadas no PEP 3107. A seção de sintaxe deixa claro que os argumentos das palavras-chave funcionam com as anotações de funções dessa maneira.

Eu desaconselho fortemente o uso de argumentos de palavras-chave mutáveis. Mais informações aqui .


1
Consulte legacy.python.org/dev/peps/pep-3107/#syntax . A dica de tipo é apenas uma aplicação de anotações de função.
Chepner

@chepner true. não sabia que o PEP 3107 tinha algo sobre argumentos de palavras-chave.
noɥʇʎԀʎzɐɹƆ

2
Uau, eu não sabia sobre os argumentos padrão mutáveis ​​em Python ... especialmente provenientes de Javascript / Ruby, onde os argumentos padrão funcionam de maneira diferente. Não vou repetir o que já foi dito ad nauseum sobre o SO, apenas estou feliz por ter descoberto isso antes que me mordesse. Obrigado!
Josh2

6
Sempre fui aconselhado a usar None, em vez de um tipo mutável como {} ou [] ou um objeto padrão, pois as mutações nesse objeto sem uma cópia aprofundada persistirão entre as iterações.
26418 MrMesees

2
definir funções suficientes com argumentos nomeados mutáveis e é apenas uma questão de tempo antes de encontrar-se olhando para trás em uma sessão de depuração 4 horas questionando suas escolhas de vida
Joseph Sheedy

20

Se você estiver usando digitação (introduzido no Python 3.5), poderá usar typing.Optional, onde Optional[X]é equivalente Union[X, None]. É usado para sinalizar que o valor explícito de Noneé permitido. Desde a digitação .

def foo(arg: Optional[int] = None) -> None:
    ...

2
Não deveria haver espaço em branco em torno da entrada =, Optional[int] = Nonecomo é a convenção para argumentos de palavras-chave sem sugestões de tipo?
actual_panda 24/03

7

Eu vi recentemente essa frase:

def foo(name: str, opts: dict=None) -> str:
    opts = {} if not opts else opts
    pass

Olá @Kirkalicious, obrigado pela sua resposta. Você poderia explicar como isso funciona?
Nathan

1
O ditado vazio transmitido como parâmetro padrão é o mesmo ditado para cada chamada. Portanto, se a função a modificar, a próxima vez padrão será o valor alterado da última vez. Tornar Noneo padrão e depois verificar dentro do método evita esse problema, alocando um novo ditado cada vez que o método é chamado.
Ian Goldby
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.