Type hints in Python zijn een krachtige manier om de leesbaarheid en betrouwbaarheid van je code te verbeteren. Hoewel Python een dynamisch getypeerde taal is, kun je met type hints duidelijk maken welk type gegevens een functie verwacht of retourneert. In dit hoofdstuk beginnen we met een overzicht van vaak gebruikte types en eindigen we met een voorbeeld van een eenvoudige class waarin type hints consistent worden toegepast.
Hieronder volgt een overzicht van de meest voorkomende types die je in Python kunt gebruiken met type hints. Deze types worden gedefinieerd in het standaard “typing”-module of zijn ingebouwde types in Python.
42
of -3
.3.14
of -0.001
.'Hallo'
of "Python"
.True
of False
.[1, 2, 3]
of ['a', 'b', 'c']
. Gebruik List[<type>]
uit de typing
-module om het type van de lijst te specificeren, zoals List[int]
.(1, 2)
of ('x', 'y')
. Gebruik Tuple[<type1>, <type2>]
.{'key': 'value'}
of {1: 'a'}
. Specificeer met Dict[<key_type>, <value_type>]
, zoals Dict[str, int]
.{1, 2, 3}
. Specificeer met Set[<type>]
, zoals Set[str]
.None
kan zijn of een waarde van een ander type, bijvoorbeeld Optional[int]
.Union[int, str]
.Callable[[int, int], int]
voor een functie die twee integers accepteert en een integer retourneert.Hier is een korte functie met type hints:
def optel_sommen(getallen: List[int]) -> int:
totaal = sum(getallen)
return totaal
In dit voorbeeld geeft List[int]
aan dat de parameter getallen
een lijst van gehele getallen moet zijn, en -> int
geeft aan dat de functie een geheel getal retourneert.
Hier is een voorbeeld van een eenvoudige class waarin type hints consistent worden gebruikt:
from typing import List
class Student:
def __init__(self, naam: str, leeftijd: int, cijfers: List[float]):
self.naam: str = naam
self.leeftijd: int = leeftijd
self.cijfers: List[float] = cijfers
def gemiddelde(self) -> float:
return sum(self.cijfers) / len(self.cijfers)
def voeg_cijfer_toe(self, cijfer: float) -> None:
self.cijfers.append(cijfer)
# Gebruik van de class
student = Student(naam="Jan", leeftijd=17, cijfers=[8.5, 7.0, 9.0])
print(f"Gemiddelde: {student.gemiddelde()}")
student.voeg_cijfer_toe(8.0)
print(f"Nieuwe cijfers: {student.cijfers}")
__init__
) gebruikt type hints om aan te geven dat naam
een string is, leeftijd
een integer, en cijfers
een lijst van floats.gemiddelde
geeft een float terug, en voeg_cijfer_toe
retourneert niets (None
).Hier is een class zonder type hints. Voeg type hints toe aan de constructor en methodes zodat duidelijk wordt welke types de class gebruikt.
class Boek:
def __init__(self, titel, auteur, paginas):
self.titel = titel
self.auteur = auteur
self.paginas = paginas
def samenvatting(self):
return f"{self.titel} is geschreven door {self.auteur}."
def is_dik_boek(self):
return self.paginas > 300
# Gebruik van de class
boek = Boek("Python Programmeren", "Jan Jansen", 350)
print(boek.samenvatting())
print(f"Is het een dik boek? {boek.is_dik_boek()}")
Hoewel type hints aangeven welk type verwacht wordt, zijn ze geen harde beperking. Hier is een voorbeeld:
isinstance
def kwadraat_getal(getal: int) -> int:
if not isinstance(getal, int):
print("Onverwacht type!")
return getal ** 2
# Gebruik van de functie met een verkeerd type
resultaat = kwadraat_getal("4") # Geen foutmelding, maar onverwacht gedrag
print(resultaat)
In het bovenstaande voorbeeld wordt een string doorgegeven aan een functie die een integer verwacht. Python geeft geen foutmelding, maar het gedrag is onverwacht.
raise
Het keyword raise
wordt gebruikt om een foutmelding expliciet te genereren. Hiermee kun je typecontroles uitvoeren in je code.
def kwadraat_getal(getal: int) -> int:
if not isinstance(getal, int):
raise TypeError("De waarde moet een integer zijn!")
return getal ** 2
# Correct gebruik
print(kwadraat_getal(4)) # Geeft 16
# Onjuist gebruik
print(kwadraat_getal("4")) # Geeft een TypeError
Hier is een voorbeeld met een lijst:
def optel_sommen(getallen: List[int]) -> int:
if not all(isinstance(x, int) for x in getallen):
raise TypeError("Alle elementen in de lijst moeten integers zijn.")
return sum(getallen)
# Correct gebruik
print(optel_sommen([1, 2, 3])) # Geeft 6
# Onjuist gebruik
print(optel_sommen([1, 2, "3"])) # Geeft een TypeError
Controleer een string:
Schrijf een functie controleer_tekst(tekst: str) -> str
die controleert of de invoer een string is. Geef een foutmelding als dat niet zo is.
Controleer een float:
Schrijf een functie bereken_kwadraat(getal: float) -> float
die controleert of de invoer een float is en het kwadraat retourneert. Geef een foutmelding als dat niet zo is.
Controleer een lijst van strings:
Schrijf een functie combineer_woorden(woorden: List[str]) -> str
die controleert of alle elementen in de lijst strings zijn en ze vervolgens combineert tot één string. Geef een foutmelding als dat niet zo is.
Met de bibliotheek typeguard
kun je typecontroles automatiseren zonder dat je handmatig isinstance
of raise
hoeft te gebruiken. Typeguard valideert automatisch de types van de parameters en retourwaarden van functies.
Je kunt typeguard
installeren met pip:
pip install typeguard
Hier is een voorbeeld van hoe je typeguard
kunt gebruiken:
from typeguard import typechecked
@typechecked
def kwadraat_getal(getal: int) -> int:
return getal ** 2
# Correct gebruik
print(kwadraat_getal(4)) # Geeft 16
# Onjuist gebruik
print(kwadraat_getal("4")) # Geeft een TypeError
In dit voorbeeld controleert typeguard
automatisch of de parameter getal
een integer is en of de retourwaarde overeenkomt met de opgegeven type hint.
Je kunt typeguard
ook gebruiken met complexere types, zoals lijsten:
from typing import List
from typeguard import typechecked
@typechecked
def optel_sommen(getallen: List[int]) -> int:
return sum(getallen)
# Correct gebruik
print(optel_sommen([1, 2, 3])) # Geeft 6
# Onjuist gebruik
print(optel_sommen([1, 2, "3"])) # Geeft een TypeError
isinstance
of raise
te schrijven.Eenvoudige functie:
Schrijf een functie vermenigvuldig_getallen(a: int, b: int) -> int
die de twee parameters vermenigvuldigt. Gebruik typeguard
om de types te controleren.
Lijstfunctie:
Schrijf een functie bereken_gemiddelde(cijfers: List[float]) -> float
die het gemiddelde van een lijst berekent. Gebruik typeguard
om te controleren of alle invoer correct is.
Complexere functie:
Schrijf een functie beschrijf_boek(titel: str, paginas: int, auteurs: List[str]) -> str
die een string retourneert met een beschrijving van een boek. Gebruik typeguard
om de types van de parameters te valideren.
Pylance is een krachtige extensie voor Visual Studio Code die je helpt typefouten in je Python-code al tijdens het typen te detecteren, zonder dat je de code hoeft uit te voeren. Het integreert met type hints en laat je meteen zien of er problemen zijn met de types in je code.
File -> Preferences -> Settings
en zoek naar type checking mode
. Stel in op Standard.Zodra Pylance is geïnstalleerd:
Met type hints krijg je nu meer feedback in VS Code. Je nu, wanneer je met je muis over een functie beweegt, zien welke argumenten de functie verwacht. Zou het nu niet handig zijn als je ook uitleg krijgt over de functie? Dat kan!
Om in Python comments bij een functie te schrijven die Visual Studio Code (en andere editors) weergeeft als hints bij het gebruik van de functie, gebruik je docstrings en type hints. Een docstring is een string die direct onder de definitie van de functie wordt geplaatst en de functionaliteit van de functie beschrijft.
Hier is hoe je dat doet:
"""
of '''
) direct na de functiedefinitie.Hier is een voorbeeld:
def greet(name: str, age: int) -> str:
"""
Geeft een gepersonaliseerde begroeting terug.
Parameters:
name (str): De naam van de persoon.
age (int): De leeftijd van de persoon.
Returns:
str: Een gepersonaliseerde begroetingsstring.
"""
return f"Hallo {name}, je bent {age} jaar oud!"
Wanneer je deze functie aanroept, zie je iets zoals dit in Visual Studio Code:
greet("Alice", 25)
Als je de muis over greet
beweegt of de parameters invult, toont VS Code:
Dit maakt je code veel leesbaarder en gebruiksvriendelijker, zowel voor jezelf als voor anderen die je code gebruiken!