[PYTHON] Ich las PEP-544 (Protokolle: Strukturelle Subtypisierung (statische Ententypisierung))

Ich beschloss, PEP 544 - Protokolle: Strukturelle Untertypisierung (statische Ententypisierung) im Verlauf einer Diskussion zu lesen, also meine eigene Notieren Sie sich Ihr Verständnis.

Überblick

Ansatz

Protokolldefinition

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

Definition von Protokollmitgliedern (Variablen)

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:

Vererbung von Protokollklassen

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.

Rückrufprotokoll

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]: ...

Impressionen

Recommended Posts

Ich las PEP-544 (Protokolle: Strukturelle Subtypisierung (statische Ententypisierung))
Ich habe PEP 560 gelesen (Kernunterstützung für das Schreiben von Modulen und generischen Typen).
Ich habe PEP 613 (Explicit Type Aliases) gelesen.
Ich habe PEP 612 (Parameter Specification Variables) gelesen.
Ich habe PEP 604 (Komplementäre Syntax für Union []) gelesen.
Ich habe PEP-362 (Function Signature Object) gelesen.
Ich habe PEP 618 gelesen (Optionale Längenprüfung zum Reißverschluss hinzufügen)
Ich habe PEP 584 gelesen (Add Union Operators To dict)
Ich habe PEP 614 (Lockerung der Grammatikbeschränkungen für Dekorateure) gelesen.
Ich habe PEP-593 gelesen (Flexible Funktion und variable Anmerkungen)