Hinzufügen eines Standardparameterwerts mit Typhinweis in Python

233

Wenn ich eine Funktion wie diese habe:

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

Und ich möchte den Parametern Typhinweise hinzufügen. Wie mache ich das? Die Art und Weise, wie ich angenommen habe, gibt mir einen Syntaxfehler:

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

Das Folgende löst keinen Syntaxfehler aus, aber es scheint nicht die intuitive Art zu sein, diesen Fall zu behandeln:

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

Ich kann in der typingDokumentation oder in einer Google-Suche nichts finden .

Bearbeiten: Ich wusste nicht, wie Standardargumente in Python funktionieren, aber für diese Frage werde ich die obigen Beispiele beibehalten. Im Allgemeinen ist es viel besser, Folgendes zu tun:

def foo(name: str, opts: dict=None) -> str:
  if not opts:
    opts={}
  pass
Josh
quelle
4
Die letzte Funktion ist der richtige Weg. So scalamacht es auch die Sprache.
Israel Unterman
14
Sie haben einen veränderlichen Standardtyp - der zu Problemen führen wird
noɥʇʎԀʎzɐɹƆ
siehe meine Update-Antwort, @josh
noɥʇʎԀʎzɐɹƆ
@ noɥʇʎԀʎzɐɹƆ Nicht, wenn Sie es nicht verwenden, z. B. zum Auswendiglernen. : P
Mateen Ulhaq

Antworten:

279

Dein zweiter Weg ist richtig.

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

print(foo.__annotations__)

dies gibt aus

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

Es ist wahr, dass es nicht in PEP 484 aufgeführt ist , aber Typhinweise sind eine Anwendung von Funktionsanmerkungen, die in PEP 3107 dokumentiert sind. Der Syntaxabschnitt macht deutlich, dass Schlüsselwortargumente auf diese Weise mit Funktionsanmerkungen funktionieren.

Ich rate dringend davon ab, veränderbare Keyword-Argumente zu verwenden. Weitere Informationen hier .

noɥʇʎԀʎzɐɹƆ
quelle
1
Siehe Legacy.python.org/dev/peps/pep-3107/#syntax . Typhinweise sind nur eine Anwendung von Funktionsanmerkungen.
Chepner
@chepner wahr. Ich wusste nicht, dass PEP 3107 etwas mit Schlüsselwortargumenten zu tun hat.
noɥʇʎԀʎzɐɹƆ
2
Wow, ich wusste nichts über die veränderlichen Standardargumente in Python ... insbesondere aus Javascript / Ruby, wo Standardargumente anders funktionieren. Ich werde nur noch einmal aufwärmen, was bereits ad nauseum darüber gesagt wurde. Ich bin nur froh, dass ich davon erfahren habe, bevor es mich gebissen hat. Vielen Dank!
Josh
6
Es wurde mir immer empfohlen, None anstelle eines veränderlichen Typs wie {} oder [] oder eines Standardobjekts zu verwenden, da Mutationen zu diesem Objekt ohne Deep-Copy zwischen den Iterationen bestehen bleiben.
MrMesees
2
Definieren Sie genügend Funktionen mit veränderlichen Schlüsselwortargumenten, und es ist nur eine Frage der Zeit, bis Sie auf eine 4-stündige Debugging-Sitzung zurückblicken, in der Sie Ihre Lebensentscheidungen in Frage stellen
Joseph Sheedy,
20

Wenn Sie die Eingabe verwenden (eingeführt in Python 3.5), können Sie verwenden typing.Optional, wo dies Optional[X]entspricht Union[X, None]. Es wird verwendet, um zu signalisieren, dass der explizite Wert von Nonezulässig ist. Vom Tippen. Optional :

def foo(arg: Optional[int] = None) -> None:
    ...
Tomasz Bartkowiak
quelle
2
Sollte es kein Leerzeichen um das =In geben, Optional[int] = Nonewie es eine Konvention für nicht typangedeutete Schlüsselwortargumente ist?
actual_panda
7

Ich habe kürzlich diesen Einzeiler gesehen:

def foo(name: str, opts: dict=None) -> str:
    opts = {} if not opts else opts
    pass
Kirkalicious
quelle
Hallo @Kirkalicious, danke für deine Antwort. Können Sie erklären, wie es funktioniert?
Nathan
1
Das als Standardparameter übergebene leere Diktat ist für jeden Aufruf das gleiche Diktat. Wenn die Funktion sie mutiert, ist der nächste Standardwert der mutierte Wert vom letzten Mal. Wenn Sie Nonedie Standardeinstellung festlegen und dann die Methode überprüfen, wird dieses Problem vermieden, indem bei jedem Aufruf der Methode ein neues Diktat zugewiesen wird.
Ian Goldby