140 lines
4.0 KiB
Markdown
140 lines
4.0 KiB
Markdown
# Unterschiede zu Vorjahren
|
|
|
|
## Typalias
|
|
|
|
Manchmal braucht man eine Kombination aus Datentypen
|
|
|
|
### Vorher
|
|
|
|
Erstellen von Typaliasen mit `Union`
|
|
|
|
```python
|
|
from typing import Union
|
|
|
|
# `RealNumber` ist also eine `int` oder eine `float`
|
|
RealNumber = Union[int, float]
|
|
|
|
# also geht hier
|
|
# `add(1, 1) -> 2`
|
|
# `add(1.0, 1.0) -> 2.0`
|
|
# aber auch
|
|
# `add(1, 1.0) -> 2.0`
|
|
def add(x: RealNumber, y: RealNumber) -> RealNumber:
|
|
return x + y
|
|
```
|
|
|
|
### In Python3.12
|
|
|
|
Wir haben jetzt das `type`-Keyword für das wir nichts importieren müssen und können einfach Datentypen mit `|` *odern*
|
|
|
|
```python
|
|
# `type` statt `Union`
|
|
type NewRealNumber = int | float
|
|
|
|
# sonst sieht alles gleich aus
|
|
def new_add(x: NewRealNumber, y: NewRealNumber) -> NewRealNumber:
|
|
return x + y
|
|
```
|
|
|
|
## Generiche Typ-Parameter (Generics, Typvariabeln, ...)
|
|
|
|
### Vorher
|
|
|
|
Erstellen von generischen Typvariabeln/Typ-Parametern mit `TypeVar` aus `typing`:
|
|
|
|
```python
|
|
from typing import Generic, TypeVar, Optional
|
|
from dataclasses import dataclass, field
|
|
|
|
# T ist unser Platzhalten für einen beliebigen Datentyp
|
|
T = TypeVar('T')
|
|
|
|
# jetzt können wir `T` einfach als Platzhalter für einen beliebigen Datentyp verwenden
|
|
# praktisch weil wir so wissen dass `x`, `y` und der `return` zumindest den **selben** Datentyp verwenden
|
|
# aber welcher genau wissen wir nicht bis jemand die Funktion mit z.b. `int` oder `float`!
|
|
# Zum Beispiel bedeutet dass
|
|
# `add(1, 2) == 3` => `T == int`
|
|
# `add(1.0, 2.0) == 3.0` => `T == float`
|
|
# ...
|
|
def add(x: T, y: T) -> T:
|
|
return x + y
|
|
|
|
# Ebenso können wir `T` auch für Klassen verwenden
|
|
@dataclass
|
|
# wir müssen hier festlegen dass T in der Klasse verwendet wird
|
|
# indem `MyList` von `Generic[UnsereGenerischeVariabel]` erbt
|
|
class MyList(Generic[T]):
|
|
|
|
def __post_init__(self, ):
|
|
# wir haben intern eine `internal_list` die von außen nicht sichtbar ist
|
|
self.__internal_list: list[T] = field(default_factory=list)
|
|
# hier speichern wir uns die aktuelle Länge unserer Liste
|
|
self.__length: int = 0
|
|
|
|
def append(self, value: T):
|
|
"""fügt ein element mit dem Typ `T` hinzu"""
|
|
self.__internal_list += [value]
|
|
self.__length += 1
|
|
|
|
def remove(self, value: T):
|
|
"""entfert das element `value`, wenn es in unserer Liste ist"""
|
|
if value in self.__internal_list:
|
|
self.__internal_list.remove(value)
|
|
|
|
def get(self, i: int) -> Optional[T]:
|
|
"""gibt das element an `i` Stelle zurück. Wenn Liste kleiner als `i` ist, dann `None`"""
|
|
if i < len(self):
|
|
return self[i]
|
|
return None
|
|
|
|
def __len__(self) -> int:
|
|
return self.__length
|
|
|
|
def __getitem__(self, i: int) -> T:
|
|
return self.__internal_list[i]
|
|
```
|
|
|
|
### In Python3.12
|
|
|
|
Deklaration der Typvariabel direkt im Funktionskopf/Klassenkopf mit `[]`.
|
|
Sprich wir brauchen `TypeVar` nicht mehr
|
|
|
|
```python
|
|
from typing import Optional
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
# hier wird `V` durch `[V]` deklariert und kann in der Funktion benutzt werden
|
|
def new_add[V](x: V, y: V) -> V:
|
|
return x + y
|
|
|
|
|
|
# hier wird `T` für die Klasse `NewMyList` deklariert durch `[T]` und kann überall in der Klasse genutzt werden
|
|
# der Rest ist genau gleich, das einzige was sich eben geändert hat ist dass man dieses `TypeVar` nicht mehr braucht
|
|
# sondern direkt in der Deklaration von Klassen/Funktionen/Methoden die generischen Typvariabeln mit deklariert
|
|
@dataclass
|
|
class NewMyList[T]:
|
|
|
|
def __post_init__(self, ):
|
|
self.__internal_list: list[T] = field(default_factory=list)
|
|
self.__length: int = 0
|
|
|
|
def append(self, value: T):
|
|
self.__internal_list += [value]
|
|
self.__length += 1
|
|
|
|
def remove(self, value: T):
|
|
if value in self.__internal_list:
|
|
self.__internal_list.remove(value)
|
|
|
|
def get(self, i: int) -> Optional[T]:
|
|
if i < len(self):
|
|
return self[i]
|
|
return None
|
|
|
|
def __len__(self) -> int:
|
|
return self.__length
|
|
|
|
def __getitem__(self, i: int) -> T:
|
|
return self.__internal_list[i]
|
|
``` |