Angenommen, eine Python-Bibliothek definiert eine Schnittstelle, die durch Code von Drittanbietern implementiert werden soll. Wie könnte diese Bibliothek eine Factory-Funktion bereitstellen, die Instanzen dieser Implementierungen mit angemessener statischer Typsicherheit erstellt?
Beispiel
Betrachten wir zur Veranschaulichung ein Minimalbeispiel mit Formen.
Die Bibliothek definiert ein Protokoll für Formen und stellt eine Factory-Funktion bereit, die Instanzen (entweder integrierte oder von Drittanbietern) basierend auf einem Zeichenfolgenschlüssel und einem Weiterleitungskonstruktor erstellt Argumente.
Implementierungen können unterschiedliche Konstruktorparameter haben.
Code: Select all
# core.py
from typing import Protocol, Any
class Shape(Protocol):
def area(self) -> float: ...
def perimeter(self) -> float: ...
SHAPE_REGISTRY: dict[str, type[Shape]] = {}
def register_shape(name: str, cls: type[Shape]) -> None:
SHAPE_REGISTRY[name] = cls
def create_shape(kind: str, **kwargs: Any) -> Shape:
cls = SHAPE_REGISTRY[kind]
return cls(**kwargs)
Code: Select all
# shapes.py
from core import Shape, register_shape
class Circle:
def __init__(self, radius: float):
self.radius = radius
def area(self) -> float: return 3.14 * self.radius ** 2
def perimeter(self) -> float: return 2 * 3.14 * self.radius
class Square:
def __init__(self, side: float):
self.side = side
def area(self) -> float: return self.side ** 2
def perimeter(self) -> float: return 4 * self.side
register_shape("circle", Circle)
register_shape("square", Square)
Code: Select all
shape1 = create_shape("circle", radius=1)
shape2 = create_shape("square", side=2)
Ich möchte jedoch statische Typhinweise bereitstellen, damit:
- Der Rückgabetyp von create_shape("circle", radius=1) als Kreis abgeleitet wird
- Die Schlüsselwortargumente radius und side werden vom Typprüfer validiert
- Pakete von Drittanbietern können neue Formen registrieren (z. B. Rechteck, Dreieck), ohne die Kernbibliothek zu ändern
Frage:
Gibt es eine Möglichkeit, eine dynamisch erweiterbare Factory-Funktion wie diese typsicher zu machen, sodass statische Typprüfer (wie mypy oder pyright) weiterhin die richtigen Konstruktorparameter und Rückgabetypen ableiten können – auch für von Drittanbietern registrierte Klassen?
Müsste ich:
- die Registrierung oder das Factory-Muster neu entwerfen?
- Verwenden Sie a TypedDictbasiertes Parametersystem?
- Oder ist das nur mit einem benutzerdefinierten Mypy-Plugin möglich?
Mobile version