Ga naar hoofdinhoud

Type checking in Python: tutorial

Leer over type checking, de verschillende types typesystemen in diverse talen, plus duck typing en type hinting.
· 7 min lezen

Verken met AI

De hulpfuncties van de eigen interpreter voeren type checking uit in Python. Omdat Python een dynamische taal is, dwingt het je niet om het type van objecten af te dwingen. Dat kan tot bugs leiden en fouten zijn dan lastig op te sporen. Om dit te ondervangen kun je Python combineren met diverse andere tools en features van statische type checking gebruiken, naast Pythons eigen duck typing.

Er zijn twee soorten typesystemen die door verschillende programmeertalen worden gevolgd. Die staan hieronder.

    1. Statisch getypeerde taal
    2. Dynamisch getypeerde taal

Statisch getypeerde taal

Het type van een variabele wordt tijdens compile-time gecontroleerd. Ook dwingt het typesysteem van de taal af dat je het gegevenstype van de variabele expliciet declareert voordat je deze gebruikt. Voorbeelden van statisch getypeerde talen zijn: Scala, Java, C++, enzovoort.
Bijvoorbeeld, de declaratie van een String in Scala is als volgt:
var myCar:String = "Mercedes";
De bovenstaande code laat zien dat de variabelenaam 'myCar' expliciet is gedeclareerd als gegevenstype 'String' met de waarde 'Mercedes'.

Dynamisch getypeerde taal

Het type van een variabele wordt tijdens runtime gecontroleerd. Het typesysteem van de taal dwingt ook niet af dat je het gegevenstype van de variabele expliciet declareert voordat je deze gebruikt. Voorbeelden van dynamisch getypeerde talen zijn: Python, JavaScript, Ruby, enzovoort.
Bijvoorbeeld, een string in Python definieer je zo:
myCar = "Mercedes"
De bovenstaande code laat zien dat de variabelenaam 'myCar' niet expliciet gedeclareerd hoeft te worden.

'type()' en 'isinstance()' in Python

Je kunt het type van variabelen opvragen met Pythons eigen 'type()'. 'type()' kun je tijdens runtime gebruiken voor debugdoeleinden om het exacte variabeletype in het programma te bepalen. Laten we naar het type van een paar variabelen kijken in het onderstaande voorbeeld.

my_var = 12
print(type(my_var))

De bovenstaande code geeft 'int' als output. Het gegevenstype van de variabele is immers een integer, wat door 'type()' wordt geïdentificeerd.

'insinstance('obj','class')' in Python kan gebruikt worden om te bepalen of 'obj', het object, een instantie van de klasse is of niet. De geretourneerde output is een boolean en is True of False.

my_var = "Hello"
print(isinstance(my_var,str))

De bovenstaande code geeft True als output. Het gegevenstype van de variabele is namelijk een string, wat door 'isinstance()' wordt vastgesteld.

Duck typing in Python

Er is een bekend principe in Python: "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck." Het principe zegt kortweg dat het type van het object of de klasse er niet toe doet; als een object vergelijkbare methoden en eigenschappen heeft, kan het voor een bepaald doel worden gebruikt.
Laten we een voorbeeld bekijken om de bovenstaande uitspraak verder te verduidelijken.

Bekijk het volgende voorbeeld met twee klassen: 'Duck' en 'Human'. Duck is een klasse met de methoden 'quack' en 'fly'. Human is eveneens een klasse met een eigen set methoden 'quack' en 'fly'. Duck en Human zijn verschillende klassen en dus ook verschillende objecten of types. Maar Human heeft vergelijkbare methoden als 'fly' en 'quack' in Duck. Er is ook een functie 'fly_quack', die meer op 'Duck' lijkt dan op 'Human', omdat het kan vliegen en kwaken.

class Duck:
    def quack(self):
        print('Quack')
    def fly(self):
        print('Flap')
class Human:
    def quack(self):
        print('Trying to Quack like a duck')
    def fly(self):
        print('Spreading my arm to flap like a duck')      
def fly_quack(thing):
    thing.quack()
    thing.fly()

Maak een instantie van 'Duck' als du en geef die door aan de functie 'fly_quack(du)'. Op dezelfde manier maak je voor Human een instantie 'h' en geef je die door aan 'fly_quack(h)'.

du = Duck()
fly_quack(du)
h = Human()
fly_quack(h)

De output van de bovenstaande code is als volgt:

Trying to Quack like a duck
Spreading my arm to flap like a duck
Quack
Flap

Hoewel de klasse 'Human' een andere klasse is dan 'Duck', roept Python toch de functie 'fly_quack' ook voor Human aan. Ondanks dat de objecttypes verschillend waren, gedroeg 'Human' zich correct en leverde het de vereiste methoden omdat het vergelijkbare 'quack' en 'fly'-methoden heeft.

Type hint en mypy

Dynamisch getypeerde talen zoals Python zijn krachtig, omdat ze de toegankelijkheid en leesbaarheid van code bevorderen. Maar er zijn ook nadelen. Een daarvan is het opsporen van runtimefouten, omdat Python het type van variabelen niet afdwingt; het is immers een dynamisch getypeerde taal. Dat kan tot fouten en bugs leiden, die moeilijk te vinden zijn naarmate de codebasis groeit.

Python ondersteunt type hints sinds versie 3.5. Oudere versies ondersteunen deze functionaliteit mogelijk niet.

Hieronder zie je een eenvoudig voorbeeld zonder type hints en mypy.

De onderstaande functie is bedoeld voor het aftrekken van een integerwaarde: ze trekt twee integers af en retourneert de waarde.

def sub_this(x,y):
    return 'Subtraction'
print(sub_this(8,'hello'))

Hier zou de functie twee integers 'x' en 'y' moeten accepteren, maar omdat er geen regels worden afgedwongen, kan ze elke datatype aannemen. Ook kan de retourwaarde willekeurig zijn: er wordt een 'str'-waarde ('Subtraction') geretourneerd, terwijl 'int' verwacht was.

Laten we een vergelijkbare implementatie van het bovenstaande programma bekijken, maar dan met type hints en 'mypy', wat helpt om statische type checking toe te passen en fouten en bugs in het programma eenvoudig te verminderen.

'mypy' is een Python-module die helpt bij statische type checking. Het combineert Pythons dynamische controle (duck typing) met type hints.

Je moet het pakket 'mypy' installeren
pip install mypy

Maak lokaal een bestand met de naam 'mypy_example.py' en typ de volgende code.
De onderstaande code is een eenvoudig programma dat twee integers als parameter accepteert en na '->' het geretourneerde gegevenstype aangeeft, ook een 'int'. De functie zou een int moeten retourneren, maar er wordt een string 'Subtracted two integers' geretourneerd.

def sub_this(x:int,y:int) -> int:
    return 'Subtracted two integers'
print(sub_this(8,4))

Voer je bovenstaande code uit in de terminal met het volgende commando.

mypy mypy_example.py

Je ziet vervolgens een foutmelding die aangeeft dat er een onverwachte retourwaarde "str" is gevonden en dat deze "int" moet zijn.

Foutmelding

Pas nu het retourtype aan zodat daadwerkelijk de aftrekking van de twee integers wordt geretourneerd.

def sub_this(x:int,y:int) -> int:
    return x - y
print(sub_this(8,4))

Succesmelding

De bovenstaande resultaten laten zien dat de succesmelding wordt weergegeven en er geen problemen zijn gevonden.

Gefeliciteerd

Gefeliciteerd, je bent aan het einde van deze tutorial gekomen!

In deze tutorial heb je geleerd over type checking, de verschillende types typesystemen in diverse talen, Pythons methoden ('type()' en 'isinstance()'), duck typing, en type hinting in combinatie met 'mypy'.

Wil je meer leren over Python? Bekijk dan DataCamp's Software Engineering for Data Scientists in Python.

Referenties:

  1. Corey's YouTube-video over duck typing

Onderwerpen

Gerelateerd