by Guest » 22 Dec 2024, 20:54
Betrachten Sie den folgenden Code, den ich einer Typprüfung unterziehen möchte:
def foo(add_count: bool = False) -> int:
return 5 if add_count else 0
def A(x: int, y: int, **kwargs: dict) -> int:
return x + y + foo(**kwargs)
def B(a: int, b: int, **kwargs: dict) -> int:
return a - b + foo(**kwargs)
def C(s: int, t: int, **kwargs: dict) -> int:
return A(s, t, **kwargs) + B(s, t, **kwargs)
mypy beschwert sich über dieses Muster:
typing.py:6: error: Argument 1 to "foo" has incompatible type "**dict[str, dict[Any, Any]]"; expected "bool" [arg-type]
typing.py:10: error: Argument 1 to "foo" has incompatible type "**dict[str, dict[Any, Any]]"; expected "bool" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
Aber ich denke, dieser Code ist völlig in Ordnung. Es ermöglicht die Übergabe von Schlüsselwortargumenten an innere Funktionen (foo):
C(5, 6, add_count=True)
# 20
Während weiterhin ungültige oder unbekannte Schlüsselwortargumente abgefangen werden:
C(5, 6, add_num=1)
# TypeError: foo() got an unexpected keyword argument 'add_num'
Da ich einen R-Hintergrund habe, verwende ich dieses Muster häufig in Situationen, in denen die von mir geschriebenen Funktionen (A, B und C) umschließen/rufen eine externe Bibliotheksfunktion foo auf, die selbst viele Parameter hat (z. B. 30+).
Ich habe die vorgeschlagene Lösung gelesen, z. B. hier und hier, aber ich halte es für inakzeptabel, da es einer bestehenden Codebasis viel zu viel Komplexität hinzufügt; Warum sollte ich ein TypedDict für die Parameter einer externen Bibliotheksfunktion foo entwerfen müssen?
Ich kann nicht anders, als zu glauben, dass mir etwas fehlt. Was ist hier die empfohlene Best Practice?
Bearbeiten:
Diese Frage wurde als Duplikat dieser Frage markiert, wobei ich mir eigentlich nicht sicher bin, ob die Lösung irgendwo in diesem Thread und den zugehörigen Referenzen enthalten ist (soweit ich das beurteilen kann, ist das nicht der Fall).
Die zweite Antwort auf die verlinkte „doppelte“ Antwort kommt meiner Meinung nach der Lösung nahe. Es wird vorgeschlagen, die Unpack-Konstruktion zu verwenden. Lassen Sie mich mein obiges Beispiel um etwas ergänzen, von dem ich dachte, dass es funktionieren würde:
from typing import Unpack, TypedDict
Params = TypedDict("Params", {}, total=False)
def A(x: int, y: int, **kwargs: Unpack[Params]) -> int: ...
def B(a: int, b: int, **kwargs: Unpack[Params]) -> int: ...
def C(s: int, t: int, **kwargs: Unpack[Params]) -> int: ...
Ich dachte, ich könnte dies verwenden, um beliebige Typen einzuschließen, da „total=False“ angibt, dass das Wörterbuch nicht vollständig sein muss. Dies schlägt jedoch bei der Typprüfung fehl, obwohl die Laufzeit in Ordnung ist:
C(1, 5, add_count=True) # error: Unexpected keyword argument "add_count" for "C" [call-arg]
Betrachten Sie den folgenden Code, den ich einer Typprüfung unterziehen möchte:
def foo(add_count: bool = False) -> int:
return 5 if add_count else 0
def A(x: int, y: int, **kwargs: dict) -> int:
return x + y + foo(**kwargs)
def B(a: int, b: int, **kwargs: dict) -> int:
return a - b + foo(**kwargs)
def C(s: int, t: int, **kwargs: dict) -> int:
return A(s, t, **kwargs) + B(s, t, **kwargs)
mypy beschwert sich über dieses Muster:
typing.py:6: error: Argument 1 to "foo" has incompatible type "**dict[str, dict[Any, Any]]"; expected "bool" [arg-type]
typing.py:10: error: Argument 1 to "foo" has incompatible type "**dict[str, dict[Any, Any]]"; expected "bool" [arg-type]
Found 2 errors in 1 file (checked 1 source file)
Aber ich denke, dieser Code ist völlig in Ordnung. Es ermöglicht die Übergabe von Schlüsselwortargumenten an innere Funktionen (foo):
C(5, 6, add_count=True)
# 20
Während weiterhin ungültige oder unbekannte Schlüsselwortargumente abgefangen werden:
C(5, 6, add_num=1)
# TypeError: foo() got an unexpected keyword argument 'add_num'
Da ich einen R-Hintergrund habe, verwende ich dieses Muster häufig in Situationen, in denen die von mir geschriebenen Funktionen (A, B und C) umschließen/rufen eine externe Bibliotheksfunktion foo auf, die selbst viele Parameter hat (z. B. 30+).
Ich habe die vorgeschlagene Lösung gelesen, z. B. hier und hier, aber ich halte es für inakzeptabel, da es einer bestehenden Codebasis viel zu viel Komplexität hinzufügt; Warum sollte ich ein TypedDict für die Parameter einer externen Bibliotheksfunktion foo entwerfen müssen?
Ich kann nicht anders, als zu glauben, dass mir etwas fehlt. Was ist hier die empfohlene Best Practice?
[b]Bearbeiten:[/b]
Diese Frage wurde als Duplikat dieser Frage markiert, wobei ich mir eigentlich nicht sicher bin, ob die Lösung irgendwo in diesem Thread und den zugehörigen Referenzen enthalten ist (soweit ich das beurteilen kann, ist das nicht der Fall).
Die zweite Antwort auf die verlinkte „doppelte“ Antwort kommt meiner Meinung nach der Lösung nahe. Es wird vorgeschlagen, die Unpack-Konstruktion zu verwenden. Lassen Sie mich mein obiges Beispiel um etwas ergänzen, von dem ich dachte, dass es funktionieren würde:
from typing import Unpack, TypedDict
Params = TypedDict("Params", {}, total=False)
def A(x: int, y: int, **kwargs: Unpack[Params]) -> int: ...
def B(a: int, b: int, **kwargs: Unpack[Params]) -> int: ...
def C(s: int, t: int, **kwargs: Unpack[Params]) -> int: ...
Ich dachte, ich könnte dies verwenden, um beliebige Typen einzuschließen, da „total=False“ angibt, dass das Wörterbuch nicht vollständig sein muss. Dies schlägt jedoch bei der Typprüfung fehl, obwohl die Laufzeit in Ordnung ist:
C(1, 5, add_count=True) # error: Unexpected keyword argument "add_count" for "C" [call-arg]