Was ist der richtige Weg, um ein Funktionsargument mit Anmerkungen zu versehen, das ein Klassenobjekt anstelle einer Instanz dieser Klasse erwartet?Wie man Typinstanzen (anstelle von Klasseninstanzen) kommentiert?
Im Beispiel unten wird some_class
Argument erwartet, dass eine Typ-Instanz sein (weicht ist eine Klasse), aber das Problem hier ist, dass type
zu weit gefasst ist:
def construct(some_class: type, related_data:Dict[str, Any]) -> Any:
...
In dem Fall, wo some_class
ein erwartet spezifische Menge von Typen Objekte, mit type
hilft überhaupt nicht. Das typing
Modul könnte in der Notwendigkeit einer Klasse generisch sein, das dies tut:
def construct(some_class: Class[Union[Foo, Bar, Baz]], related_data:Dict[str, Any]) -> Union[Foo, Bar, Baz]:
...
In dem obigen Beispiel some_class
ist die Foo
, Bar
oder Faz
Klasse, keine Instanz davon. Es sollte ihre Positionen im Klassenbaum nicht interessieren, weil some_class: Class[Foo]
auch ein gültiger Fall sein sollte. Daher
# classes are callable, so it is OK
inst = some_class(**related_data)
oder
# instances does not have __name__
clsname = some_class.__name__
oder
# an operation that only Foo, Bar and Baz can perform.
some_class.a_common_classmethod()
sollten OK sein, um mypy, pytype, PyCharm usw.
Wie kann dies mit aktuellen Implementierung erfolgen (Python 3.6 oder früher)?
Wenn Sie spezifischer als "Typ" sein müssen, führen Sie entweder eine Metaklasse oder eine abstrakte Basisklasse ein. – jonrsharpe
@jonrsharpe - Eine Metaklasse würde den Trick machen, glaube ich, aber ich habe dieses Level in Python noch nicht erreicht. Mit der Einführung von Variablenanmerkungen in 3.6 (einschließlich einer 'ClassVar' zur Unterscheidung von Instanzvariablen von Klassenvariablen) frage ich mich, warum ich' type' verwenden sollte, um Klassenobjekte zu kommentieren, wenn es so viele Möglichkeiten gibt, Klasseninstanzen zu kommentieren. Vielleicht muss ich auf ein zukünftiges Update oder ein Rezept warten :). –
Es scheint, dass ich mich auf 'typing.Type' verlassen muss und etwas wie' Foo = TypeVar ['Foo', bond = Bar] 'machen muss, wobei' Bar' ein ABC ist, dann nehmen wir das obige Beispiel: ' def konstruieren (some_class: Typ [Foo], ...) -> Foo'. Ich mag es besonders nicht, 'TypeVar' zu benutzen, aber es scheint der einzige Weg zu sein ... –