Ich probiere Pythons Typanmerkungen mit abstrakten Basisklassen aus, um einige Schnittstellen zu schreiben. Gibt es eine Möglichkeit, die möglichen Arten von *args
und mit Anmerkungen zu versehen **kwargs
?
Wie würde man zum Beispiel ausdrücken, dass die sinnvollen Argumente für eine Funktion entweder ein int
oder zwei int
s sind? type(args)
gibt Tuple
so meine Vermutung , die Art , wie mit Anmerkungen versehen war Union[Tuple[int, int], Tuple[int]]
nicht, aber das funktioniert nicht.
from typing import Union, Tuple
def foo(*args: Union[Tuple[int, int], Tuple[int]]):
try:
i, j = args
return i + j
except ValueError:
assert len(args) == 1
i = args[0]
return i
# ok
print(foo((1,)))
print(foo((1, 2)))
# mypy does not like this
print(foo(1))
print(foo(1, 2))
Fehlermeldungen von mypy:
t.py: note: In function "foo":
t.py:6: error: Unsupported operand types for + ("tuple" and "Union[Tuple[int, int], Tuple[int]]")
t.py: note: At top level:
t.py:12: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:14: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:15: error: Argument 1 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
t.py:15: error: Argument 2 to "foo" has incompatible type "int"; expected "Union[Tuple[int, int], Tuple[int]]"
Es ist sinnvoll, dass mypy dies für den Funktionsaufruf nicht mag, da erwartet wird, dass tuple
im Aufruf selbst ein a vorhanden ist. Das Hinzufügen nach dem Auspacken führt auch zu einem Tippfehler, den ich nicht verstehe.
Wie kommentiert man die sinnvollen Typen für *args
und **kwargs
?
quelle
Optional
? Hat sich etwas an Python geändert oder haben Sie Ihre Meinung geändert? Ist es aufgrund derNone
Standardeinstellung immer noch nicht unbedingt erforderlich ?Optional
Annotation, wenn Sie sieNone
als Standardwert verwenden, bestimmte Anwendungsfälle erschwert, und diese werden jetzt aus dem PEP entfernt.Optional
in Zukunft explizite Anforderungen gestellt werden.Callable
unterstützt keine Erwähnung eines Typhinweises für*args
oder**kwargs
Punkt . Bei diesem speziellen Problem geht es darum, Callables zu markieren, die bestimmte Argumente und eine beliebige Anzahl anderer akzeptieren , und daher*args: Any, **kwargs: Any
einen sehr spezifischen Typhinweis für die beiden Catch-Alls zu verwenden. Für Fälle, in denen Sie*args
und / oder**kwargs
auf etwas Spezifischeres setzen, können Sie a verwendenProtocol
.Der richtige Weg, dies zu tun, ist die Verwendung von
@overload
Beachten Sie, dass Sie
@overload
der tatsächlichen Implementierung keine Anmerkungen hinzufügen oder eingeben, die zuletzt erfolgen müssen.Sie benötigen eine neue Version von beiden
typing
und mypy, um Unterstützung für @overload außerhalb von Stub-Dateien zu erhalten .Sie können dies auch verwenden, um das zurückgegebene Ergebnis so zu variieren, dass explizit angegeben wird, welche Argumenttypen welchem Rückgabetyp entsprechen. z.B:
quelle
(type1)
vs(type1, type1)
Funktionsaufrufe als mein Beispiel verwenden sollen. Vielleicht wäre(type1)
vs(type2, type1)
ein besseres Beispiel gewesen und zeigt, warum mir diese Antwort gefällt. Dies ermöglicht auch unterschiedliche Rückgabetypen. In dem speziellen Fall, in dem Sie nur einen Rückgabetyp haben*args
und*kwargs
alle gleich sind, ist die Technik in Martjins Antwort sinnvoller, sodass beide Antworten nützlich sind.*args
einer maximalen Anzahl von Argumenten (hier 2) ist jedoch immer noch falsch .*args
unbedingt falsch? Wenn die erwarteten Aufrufe(type1)
vs waren(type2, type1)
, ist die Anzahl der Argumente variabel und es gibt keinen geeigneten Standard für das nachfolgende Argument. Warum ist es wichtig, dass es ein Maximum gibt?*args
ist wirklich da für null oder mehr , unbegrenzte, homogene Argumente oder dafür, diese unberührt weiterzugeben. Sie haben ein erforderliches und ein optionales Argument. Das ist völlig anders und wird normalerweise dadurch behandelt, dass dem zweiten Argument ein Sentinel-Standardwert zugewiesen wird, um festzustellen, dass dieser weggelassen wurde.*args
, ist eine noch bessere Antwort auf die Frage, dass dies überhaupt nicht getan werden sollte.Als kurz neben der vorherigen Antwort, wenn Sie versuchen , mypy auf Python 2 - Dateien und verwenden müssen , um Kommentare zu verwenden Typen anstelle von Anmerkungen hinzufügen möchten , müssen Sie die Typen für Präfix
args
undkwargs
mit*
und**
jeweils:Dies wird von mypy als dasselbe behandelt wie die folgende Python 3.5-Version von
foo
:quelle