Aggiunta del valore del parametro predefinito con suggerimento tipo in Python


236

Se ho una funzione come questa:

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

E voglio aggiungere suggerimenti di tipo ai parametri, come posso fare? Il modo in cui ho assunto mi dà un errore di sintassi:

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

Quanto segue non genera un errore di sintassi ma non sembra il modo intuitivo di gestire questo caso:

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

Non riesco a trovare nulla nella typingdocumentazione o su una ricerca su Google.

Modifica: non sapevo come funzionassero gli argomenti predefiniti in Python, ma per il bene di questa domanda, terrò gli esempi sopra. In generale è molto meglio fare quanto segue:

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

4
L'ultima funzione è quella corretta. È allo stesso modo anche la scalalingua.
Israel Unterman,

14
hai un tipo predefinito mutevole - che porterà a problemi
noɥʇʎԀʎzɐɹƆ

vedi la mia risposta di aggiornamento, @josh
noɥʇʎԀʎzɐɹƆ

@ noɥʇʎԀʎzɐɹƆ A meno che tu non lo stia usando, ad es. memoization. : P
Mateen Ulhaq,

Risposte:


281

Il tuo secondo modo è corretto.

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

print(foo.__annotations__)

questo produce

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

È vero che non è elencato in PEP 484 , ma i suggerimenti sul tipo sono un'applicazione di annotazioni di funzioni, che sono documentate in PEP 3107. La sezione della sintassi chiarisce che gli argomenti di parole chiave funzionano in questo modo con le annotazioni di funzioni.

Consiglio vivamente di non utilizzare argomenti per parole chiave mutabili. Maggiori informazioni qui .


1
Vedi legacy.python.org/dev/peps/pep-3107/#syntax . Il suggerimento per tipo è solo un'applicazione di annotazioni di funzioni.
Chepner,

@chepner true. non sapevo che PEP 3107 avesse qualcosa sugli argomenti delle parole chiave.
noɥʇʎԀʎzɐɹƆ

2
Wow, non sapevo degli argomenti di default mutabili in Python ... specialmente quelli provenienti da Javascript / Ruby dove gli argomenti di default funzionano diversamente. Non ripeterò ciò che è già stato detto fino alla nausea a proposito di ciò, sono solo felice di averlo scoperto prima che mi mordesse. Grazie!
josh

6
Mi è sempre stato consigliato di usare Nessuno anziché un tipo mutabile come {} o [] o un oggetto predefinito poiché le mutazioni a quell'oggetto senza una copia profonda persistono tra le iterazioni.
MrMesees,

2
definire funzioni sufficienti con argomenti di parole chiave mutabili ed è solo una questione di tempo prima che ti ritrovi a guardare indietro in una sessione di debug di 4 ore che mette in discussione le tue scelte di vita
Joseph Sheedy,

20

Se stai usando la digitazione (introdotta in Python 3.5) puoi usare typing.Optional, dove Optional[X]è equivalente Union[X, None]. Viene utilizzato per segnalare che Noneè consentito il valore esplicito di . Dalla digitazione . Opzionale :

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

2
Non dovrebbero esserci spazi bianchi attorno a =in Optional[int] = Nonecome è una convenzione per argomenti di parole chiave non tipizzati?
actual_panda il

7

Di recente ho visto questo one-liner:

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

Ciao @Kirkalicious, grazie per la tua risposta. Potresti spiegare come funziona?
Nathan,

1
Il dict vuoto passato come parametro predefinito è lo stesso dict per ogni chiamata. Quindi, se la funzione la muta, la volta successiva sarà il valore mutato dell'ultima volta. Rendendo Noneil difetto e quindi il controllo all'interno del metodo evita questo problema assegnando un nuovo __dict__ ogni volta che il metodo viene richiamato.
Ian Goldby,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.