- Python té un sistema de tipus dinàmic.
- El tipus d'una variable depèn del seu valor en aquell moment.
- En programes grans, això incrementa els bugs i complica el seu manteniment.
- Des de fa un temps, els programes en Python es poden anotar amb tipus, de forma semblant al C++.
- Aquestes anotacions no tenen cap efecte en temps d'execució.
- Però hi ha eines que poden comprovar que no hi hagi errors de tipus (igual que fa el compilador de C++).
Funció que hauria de sumar dos enters:
def suma(x, y):
return x + y
Fixeu-vos que no anunciem ni el tipus dels paràmetres ni el tipus del resultat.
Llavors, si fem
print(suma(10, 'hola'))
tindrem un error en temps d'execució.
Podem anotar la capçalera de suma
amb tipus:
def suma(x: int, y: int) -> int:
return x + y
Si tornem a fer
print(suma(10, 'hola'))
continuem tenint un error en temps d'execució.
Però si processem el programa amb mypy
, ens informarà de l'error sense executar-lo:
> mypy prova.py
diu
prova.py:5: error: Argument 2 to "suma" has incompatible type "str"; expected "int"
Per tant, mymy
ajuda a detectar errors.
Notes:
- Cal fer
pip3 install mypy
per instal·lar-lo. - Es poden configurar els editors perquè mostrin els errors mentre es programa.
- Alternatives:
pyright
,pytype
,pyre
.
Tipus bàsics:
int
float
str
bool
None
Any
Tipus estructurats:
list[]
, per exemple,list[int]
olist[list[float]]
dict[]
, per exemple,dict[str, int]
tuple[]
, per exemple,tuple[str, int, bool]
Tipus sinònims:
Vector = list[float]
Tipus que cal importar:
from typing import Union, Optional
Union[]
, per exempleUnion[int, str]
Optional[]
, per exempleOptional[int]
és igual queUnion[int, None]
.
Molta més informació a https://docs.python.org/3/library/typing.html
Les anotacions es poden posar als paràmetres, al resultat de les funcions i a les declaracions de variables.
def suma(x: int, y: int) -> int:
s: int = x + y
return s
De totes formes, el sistema ja sol inferrir automàticament el tipus de les variables locals (usant el tipus de l'expressió que se'ls assigna).
També es poden declarar els tipus dels atributs (camps) de les classes:
class Punt:
x: float
y: float
...
El nom de la classe es pot utilitzar com a tipus:
def distància(p: Punt, q: Punt) -> float: ...
Per cert, amb
from dataclasses import dataclass
@dataclass
class Punt:
x: float
y: float
color: int = 0
...
Python ja crea automàticament un constructor per a punts:
def __init__(self, x: float, y: float, color: int = 0):
self.x = x
self.y = y
self.color = color