Ich beschloss, PEP 544 - Protokolle: Strukturelle Untertypisierung (statische Ententypisierung) im Verlauf einer Diskussion zu lesen, also meine eigene Notieren Sie sich Ihr Verständnis.
Eine Klasse, die "typing.Protocol" erbt, wird als Protokollklasse (oder einfach als Protokoll) bezeichnet. Welcher Typ und welche Art von Mitglied (Variable, Methode) kann als Protokollmitglied in der Protokollklasse definiert werden.
Das folgende Beispiel definiert das "SupportsClose" -Protokoll, das eine Methode namens "close ()" ohne Argumente und ohne Rückgabewert hat.
from typing import Protocol
class SupportsClose(Protocol):
def close(self) -> None:
pass
Beispielsweise kann gesagt werden, dass die folgende Klasse das "SupportsClose" -Protokoll erfüllt.
class Resource:
...
def close(self) -> None:
self.file.close()
self.lock.release()
Daher wird der folgende Code wie vorgesehen typgeprüft.
def close_all(things: Iterable[SupportsClose]) -> None:
for t in things:
t.close()
f = open('foo.txt')
r = Resource()
close_all([f, r]) # OK!
close_all([1]) # Error: 'int' has no 'close' method
Variablen können mithilfe von Variablenanmerkungen als Protokollelemente definiert werden. Beachten Sie, dass beim Initialisieren einer Variablen in einer Methode kein Protokollmitglied vorhanden ist. Daher wird "self.temp" im folgenden Code ignoriert (dies hat keinen Einfluss auf die Überprüfung des Protokolltyps).
from typing import Protocol, List
class Template(Protocol):
name: str # This is a protocol member
value: int = 0 # This one too (with default)
def method(self) -> None:
self.temp: List[int] = [] # Error in type checker
Verwenden Sie für Klassenvariablen übrigens typing.ClassVar
[^ 1].
[^ 1]: Ich habe versucht zu experimentieren, aber es funktioniert nicht ...?: Denken:
Bis zu diesem Punkt wurde die Protokollklasse als Typ behandelt (Typanmerkung). Da die Protokollklasse jedoch eine normale Python-Klasse ist, kann sie vererbt werden, um eine abgeleitete Klasse zu erstellen.
class PColor(Protocol):
@abstractmethod
def draw(self) -> str:
...
def complex_method(self) -> int:
# some complex code here
class NiceColor(PColor):
def draw(self) -> str:
return "deep blue"
Wenn sie geerbt werden, werden die Mitglieder von der abgeleiteten Klasse so geerbt, wie sie sind. Daher wird natürlich davon ausgegangen, dass sie das Protokoll erfüllen [^ 2].
Wenn Sie nur die Typprüfung durchführen, müssen Sie sie nicht erben. Daher ist es gut zu glauben, dass die Freigabe der Implementierung bei Verwendung dieser Verwendung von Vorteil ist. Ein Beispiel für die Verwendung in Kombination mit abc.abstractmethod
wird ebenfalls vorgestellt, und es handelt sich um eine ABC-ähnliche Einführung (Abstract Base Classes) [^ 3].
[^ 2]: Es ist möglich, es mit einer abgeleiteten Klasse zu überschreiben, damit es das Protokoll nicht erfüllt. Da es sich jedoch um eine unregelmäßige Verwendung handelt, wird die Erklärung weggelassen. [^ 3]: Oder besser gesagt, das andere Verhalten als der Typhinweis scheint ABC (zur Laufzeit) fast zu entsprechen.
Er sagte, es wäre schön, eine Protokollklasse mit einer call () -Methode zu verwenden, um komplexe aufrufbare Schnittstellen wie variable Argumente, Überladungen und Generics darzustellen. Dies scheint praktisch.
from typing import Optional, List, Protocol
class Combiner(Protocol):
def __call__(self, *vals: bytes,
maxlen: Optional[int] = None) -> List[bytes]: ...
Recommended Posts