Python Academy · Lektion

TypeVar, generiske klasser og Protocol

Definér genanvendelige generiske typer og strukturel subtyping med Protocol.

Lektion 3 af 413 trin

TypeVar, generiske klasser og Protocol er en gratis Python Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Python Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Python Academy-kurset indeholder 4 lektioner i alt.

Hvad er TypeVar

TypeVar erklærer en typevariabel — en pladsholder, der kan være enhver type og om nødvendigt begrænses. Den bruges i generiske funktioner og klasser.

from typing import TypeVar

T = TypeVar("T")

def identity(value: T) -> T:
    return value

print(identity(42))      # int
print(identity("hello")) # str

Generiske funktioner

En funktion, der bruger TypeVar i både parameter- og returtyperne, giver mypy mulighed for at udlede returtypen ud fra argumenttypen.

from typing import TypeVar

T = TypeVar("T")

def first(items: list[T]) -> T:
    return items[0]

x: int = first([1, 2, 3])     # mypy knows x is int
s: str = first(["a","b","c"]) # mypy knows s is str

Begrænset TypeVar

Videregiv typebegrænsninger til TypeVar for at begrænse, hvilke typer der accepteres.

from typing import TypeVar

Numeric = TypeVar("Numeric", int, float)

def double(n: Numeric) -> Numeric:
    return n * 2

print(double(5))    # 10
print(double(2.5))  # 5.0
# double("x")  # mypy error

Generiske klasser

Nedarv fra Generic[T] for at oprette en klasse, der parameteriseres af en typevariabel.

from typing import Generic, TypeVar

T = TypeVar("T")

class Stack(Generic[T]):
    def __init__(self) -> None:
        self._items: list[T] = []

    def push(self, item: T) -> None:
        self._items.append(item)

    def pop(self) -> T:
        return self._items.pop()

stack: Stack[int] = Stack()
stack.push(1)
print(stack.pop())   # 1

Flere TypeVars

Brug flere TypeVars til at parameterisere en klasse eller funktion ud fra to uafhængige typer.

from typing import Generic, TypeVar

K = TypeVar("K")
V = TypeVar("V")

class Pair(Generic[K, V]):
    def __init__(self, key: K, value: V) -> None:
        self.key = key
        self.value = value

p: Pair[str, int] = Pair("age", 30)
print(p.key, p.value)   # age 30

Protocol — strukturel subtyping

Protocol definerer en interface ud fra de metoder og attributter, en klasse skal have, uden at kræve eksplicit nedarvning ("duck typing med typekontrol").

from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None: ...

def render(obj: Drawable) -> None:
    obj.draw()

class Circle:
    def draw(self) -> None:
        print("Drawing circle")

render(Circle())   # works — Circle satisfies Drawable

Protocol med runtime_checkable

Tilføj @runtime_checkable til en Protocol for at aktivere isinstance()-tjek under kørsel.

from typing import Protocol, runtime_checkable

@runtime_checkable
class Closeable(Protocol):
    def close(self) -> None: ...

class File:
    def close(self) -> None: print("closed")

print(isinstance(File(), Closeable))   # True

Protocol kontra ABC

ABC'er kræver eksplicit nedarvning (class Dog(Animal)). Protocols fungerer gennem strukturel matching — hvis en klasse har de rigtige metoder, opfylder den protokollen uanset nedarvning.

from typing import Protocol
from abc import ABC, abstractmethod

# ABC: nominal typing
class Printable(ABC):
    @abstractmethod
    def display(self) -> None: ...

# Protocol: structural typing
class Displayable(Protocol):
    def display(self) -> None: ...

TypeVar med bound

TypeVar("T", bound=BaseClass) begrænser T til BaseClass eller en af dens subklasser.

from typing import TypeVar

class Animal:
    def speak(self) -> str: return "..."

A = TypeVar("A", bound=Animal)

def make_speak(animal: A) -> str:
    return animal.speak()

Generisk alias — Python 3.12

Python 3.12 introducerer type-sætningen til rene typealiaser og syntaksen class Foo[T] til generiske typer uden import af TypeVar.

# Python 3.12+
type Vector = list[float]
type Matrix = list[Vector]

class Stack[T]:
    def __init__(self) -> None: self._items: list[T] = []
    def push(self, item: T) -> None: self._items.append(item)
    def pop(self) -> T: return self._items.pop()

Self-typen

Self (fra typing i 3.11+) annoterer metoder, der returnerer den aktuelle klasse, hvilket er nyttigt i flydende interfaces og subklasser.

from typing import Self

class Builder:
    def __init__(self) -> None:
        self.parts: list[str] = []

    def add(self, part: str) -> Self:
        self.parts.append(part)
        return self

b = Builder().add("a").add("b")
print(b.parts)   # ["a", "b"]

Hurtigt tjek

Hvad er den vigtigste forskel på en Protocol og en ABC i Pythons typeannotering?

Opsummering

TypeVar opretter typepladsholdere til generiske funktioner og klasser. Generic[T] parameteriserer klasser. Protocol muliggør strukturel subtyping uden nedarvning. Brug bound= eller typebegrænsninger på TypeVar for at begrænse de typer, der accepteres.

Gratis at komme i gang

Lær Python med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
76
Lektioner
320

Ofte stillede spørgsmål

Er lektionen “TypeVar, generiske klasser og Protocol” gratis?

Ja — hele teksten til “TypeVar, generiske klasser og Protocol” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Python Academy-kurset, skal du opgradere til CoddyKit PRO. Python Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “TypeVar, generiske klasser og Protocol”?

Definér genanvendelige generiske typer og strukturel subtyping med Protocol. Du øver dig i Python Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Python Academy?

Der kræves ingen tidligere erfaring. Python Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “TypeVar, generiske klasser og Protocol”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Python Academy-lektion?

Ja. Alle Python Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Grundlæggende typeannoteringer
  2. Komplekse typer: List, Dict, Optional, Union
  3. TypeVar, generiske klasser og Protocol
  4. Kørsel af mypy og rettelse af typefejl
← Tilbage til Python Academy