Le altre risposte hanno fatto un buon lavoro nello spiegare la tipizzazione delle anatre e la semplice risposta di tzot :
Python non ha variabili, come altre lingue in cui le variabili hanno un tipo e un valore; ha nomi che indicano oggetti, che ne conoscono il tipo.
Tuttavia , una cosa interessante è cambiata dal 2010 (quando è stata posta la prima domanda), ovvero l'implementazione di PEP 3107 (implementata in Python 3). Ora puoi effettivamente specificare il tipo di un parametro e il tipo del tipo restituito di una funzione come questa:
def pick(l: list, index: int) -> int:
return l[index]
Possiamo qui vedere che pick
accetta 2 parametri, un elenco l
e un numero intero index
. Dovrebbe anche restituire un numero intero.
Quindi qui è implicito che l
sia un elenco di numeri interi che possiamo vedere senza molto sforzo, ma per funzioni più complesse può essere un po 'confuso su ciò che l'elenco dovrebbe contenere. Vogliamo anche che il valore predefinito index
sia 0. Per risolvere questo problema, puoi scegliere di scrivere in pick
questo modo:
def pick(l: "list of ints", index: int = 0) -> int:
return l[index]
Si noti che ora inseriamo una stringa come tipo di l
, che è sintatticamente consentita, ma non è utile per l'analisi a livello di codice (a cui torneremo più avanti).
È importante notare che Python non rilascerà a TypeError
se passi un float index
, la ragione di ciò è uno dei punti principali nella filosofia di progettazione di Python: "Siamo tutti consenzienti adulti qui" , il che significa che ci si aspetta che sii consapevole di cosa puoi passare a una funzione e cosa non puoi. Se vuoi davvero scrivere il codice che genera TypeErrors puoi usare la isinstance
funzione per verificare che l'argomento passato sia del tipo corretto o di una sua sottoclasse in questo modo:
def pick(l: list, index: int = 0) -> int:
if not isinstance(l, list):
raise TypeError
return l[index]
Maggiori informazioni sul motivo per cui raramente dovresti fare questo e su cosa dovresti fare invece sono discussi nella sezione successiva e nei commenti.
PEP 3107 non solo migliora la leggibilità del codice, ma ha anche diversi casi d'uso adatti che puoi leggere qui .
L'annotazione dei tipi ha suscitato molta più attenzione in Python 3.5 con l'introduzione di PEP 484 che introduce un modulo standard per i suggerimenti sul tipo.
Questi suggerimenti sul tipo provengono dal mypy di controllo del tipo ( GitHub ), che ora è conforme a PEP 484 .
Con il modulo di digitazione viene fornita una raccolta piuttosto completa di suggerimenti sul tipo, tra cui:
List
, Tuple
, Set
, Map
- per list
, tuple
, set
e map
, rispettivamente.
Iterable
- utile per i generatori.
Any
- quando potrebbe essere qualsiasi cosa.
Union
- quando potrebbe essere qualcosa all'interno di un determinato set di tipi, al contrario di Any
.
Optional
- quando potrebbe essere Nessuno. Stenografia per Union[T, None]
.
TypeVar
- usato con generici.
Callable
- Utilizzato principalmente per le funzioni, ma potrebbe essere utilizzato per altri callable.
Questi sono i suggerimenti di tipo più comuni. Un elenco completo è disponibile nella documentazione del modulo di battitura .
Ecco il vecchio esempio che utilizza i metodi di annotazione introdotti nel modulo di digitazione:
from typing import List
def pick(l: List[int], index: int) -> int:
return l[index]
Una potente funzionalità è quella Callable
che consente di digitare metodi annotati che accettano una funzione come argomento. Per esempio:
from typing import Callable, Any, Iterable
def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
"""An immediate version of map, don't pass it any infinite iterables!"""
return list(map(f, l))
L'esempio sopra potrebbe diventare più preciso con l'uso di TypeVar
invece diAny
, ma questo è stato lasciato come un esercizio al lettore poiché credo di aver già riempito la mia risposta con troppe informazioni sulle meravigliose nuove funzionalità abilitate dal suggerimento del tipo.
In precedenza, quando si documentava un codice Python con ad esempio Sphinx alcune delle funzionalità sopra menzionate potevano essere ottenute scrivendo docstring formattati in questo modo:
def pick(l, index):
"""
:param l: list of integers
:type l: list
:param index: index at which to pick an integer from *l*
:type index: int
:returns: integer at *index* in *l*
:rtype: int
"""
return l[index]
Come puoi vedere, questo richiede un numero di righe extra (il numero esatto dipende da quanto esplicitamente vuoi essere e da come formattare la tua docstring). Ma ora ti dovrebbe essere chiaro come PEP 3107 offra un'alternativa che è in molti (tutti?) Modi superiori. Ciò è particolarmente vero in combinazione con PEP 484 che, come abbiamo visto, fornisce un modulo standard che definisce una sintassi per questi suggerimenti / annotazioni di tipo che possono essere utilizzati in modo che sia chiaro e preciso ma flessibile, rendendo combinazione potente.
Secondo la mia opinione personale, questa è una delle più grandi funzionalità di Python di sempre. Non vedo l'ora che le persone inizino a sfruttarne il potere. Ci scusiamo per la lunga risposta, ma questo è ciò che accade quando mi eccito.
Un esempio di codice Python che utilizza pesantemente i suggerimenti sul tipo può essere trovato qui .