Introduzione a Python

Premessa

Ti diamo il benvenuto nel tutorial online di Google su Python. Si basa sul corso introduttivo su Python offerto internamente. Come menzionato nella pagina di configurazione, questo materiale tratta Python 3.

Se stai cercando un corso MOOC complementare, prova quelli di Udacity e Coursera (introduzione alla programmazione [principianti] o introduzione a Python). Infine, se sei alla ricerca di un apprendimento online da seguire in modo autonomo senza guardare video, prova quelli elencati alla fine di questo post, ovvero ognuno dei contenuti per l'apprendimento delle funzionalità e un interprete interattivo Python con cui puoi esercitarti. Cos'è l'"interprete" di cui ci riferiamo? Lo scoprirai nella prossima sezione.

Introduzione al linguaggio

Python è un linguaggio dinamico e interpretato (compilato con bytecode). Nel codice sorgente non sono presenti dichiarazioni del tipo di variabili, parametri, funzioni o metodi. Questo rende il codice breve e flessibile e perderai il controllo del tipo in fase di compilazione del codice sorgente. Python tiene traccia dei tipi di tutti i valori in fase di runtime e segnala il codice che non ha senso durante l'esecuzione.

Un modo eccellente per vedere come funziona il codice Python è eseguire l'interprete Python e digitare il codice direttamente al suo interno. Se dovessi avere domande del tipo: "Cosa succede se aggiungo un int a un list?". Basta digitarlo nell'interprete Python e probabilmente è il modo migliore per capire cosa succede. (vedi di seguito per vedere cosa succede realmente).

$ python3        ## Run the Python interpreter
Python 3.X.X (XXX, XXX XX XXXX, XX:XX:XX) [XXX] on XXX
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 6       ## set a variable in this interpreter session
>>> a           ## entering an expression prints its value
6
>>> a + 2
8
>>> a = 'hi'    ## 'a' can hold a string just as well
>>> a
'hi'
>>> len(a)      ## call the len() function on a string
2
>>> a + len(a)  ## try something that doesn't work
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
>>> a + str(len(a))  ## probably what you really wanted
'hi2'
>>> foo         ## try something else that doesn't work
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'foo' is not defined
>>> ^D          ## type CTRL-d to exit (CTRL-z in Windows/DOS terminal)

Le due righe di Python dopo aver digitato Python e prima del prompt >>> indicano la versione di Python in uso e dove è stata creata. Se la prima cosa che viene stampata è "Python 3", questi esempi dovrebbero fare al caso tuo.

Come puoi vedere sopra, è facile sperimentare con variabili e operatori. Inoltre, l'interprete genera, nel gergo Python, un errore di runtime se il codice cerca di leggere una variabile a cui non è stato assegnato un valore. Come per C++ e Java, Python è sensibile alle maiuscole, quindi "a" e "A" sono variabili diverse. La fine di una riga segna la fine di un'istruzione, quindi a differenza di C++ e Java, Python non richiede un punto e virgola alla fine di ogni istruzione. I commenti iniziano con "#" e si estendono fino alla fine della riga.

Codice sorgente Python

I file di origine Python utilizzano l'estensione ".py" e sono chiamati "moduli". Con un modulo Python hello.py, il modo più semplice per eseguirlo è utilizzare il comando della shell "python hello.py Alice" che chiama l'interprete Python per eseguire il codice in hello.py, passandogli l'argomento della riga di comando "Alice". Consulta la pagina della documentazione ufficiale su tutte le diverse opzioni a tua disposizione quando esegui Python dalla riga di comando.

Ecco un programma hello.py molto semplice (nota che i blocchi di codice sono delimitati rigorosamente utilizzando rientro anziché parentesi graffe. Approfondiremo questo argomento più avanti!):

#!/usr/bin/python3

# import modules used here -- sys is a very standard one
import sys

# Gather our code in a main() function
def main():
    print('Hello there', sys.argv[1])
    # Command line args are in sys.argv[1], sys.argv[2] ...
    # sys.argv[0] is the script name itself and can be ignored

# Standard boilerplate to call the main() function to begin
# the program.
if __name__ == '__main__':
    main()

L'esecuzione di questo programma dalla riga di comando ha il seguente aspetto:

$ python3 hello.py Guido
Hello there Guido
$ ./hello.py Alice  ## without needing 'python3' first (Unix)
Hello there Alice

Importazioni, Argomenti della riga di comando e len()

Le istruzioni più esterne in un file Python, o "modulo", vengono configurate una sola volta. Queste istruzioni vengono eseguite dall'alto verso il basso la prima volta che il modulo viene importato da qualche parte, impostando le relative variabili e funzioni. Un modulo Python può essere eseguito direttamente, come sopra python3 hello.py Bob, oppure importato e utilizzato da un altro modulo. Quando un file Python viene eseguito direttamente, la variabile speciale "__name__" è impostata su "__main__". Pertanto, è comune che il boilerplate if __name__ ==... mostrato sopra chiami una funzione main() quando il modulo viene eseguito direttamente, ma non quando il modulo viene importato da un altro modulo.

In un programma Python standard, l'elenco sys.argv contiene gli argomenti della riga di comando nel modo standard, dove sys.argv[0] è il programma stesso, sys.argv[1] il primo argomento e così via. Se conosci argc o il numero di argomenti, puoi semplicemente richiedere questo valore a Python con len(sys.argv), proprio come abbiamo fatto nel codice dell'interprete interattivo riportato sopra quando hai richiesto la lunghezza di una stringa. In generale, len() può indicare la lunghezza di una stringa, il numero di elementi in elenchi e tuple (un'altra struttura di dati di tipo array) e il numero di coppie chiave/valore in un dizionario.

Funzioni definite dall'utente

Le funzioni in Python sono definite come segue:

# Defines a "repeat" function that takes 2 arguments.
def repeat(s, exclaim):
    """
    Returns the string 's' repeated 3 times.
    If exclaim is true, add exclamation marks.
    """

    result = s + s + s # can also use "s * 3" which is faster (Why?)
    if exclaim:
        result = result + '!!!'
    return result

Nota anche come le righe che compongono la funzione o l'istruzione if vengono raggruppate in base allo stesso livello di rientro. Abbiamo anche presentato due diversi modi per ripetere le stringhe, utilizzando l'operatore +, che è più facile da usare, ma * funziona anche perché è l'operatore "repeat" di Python, il che significa che '-' * 10 fornisce '----------', un modo ordinato per creare una "line" sullo schermo. Nel commento del codice, abbiamo suggerito che * funziona più velocemente del +, il motivo è che * calcola una volta la dimensione dell'oggetto risultante, mentre con +, questo calcolo viene eseguito ogni volta che viene richiamato il valore +. Sia + che * sono chiamati operatori "sovraccarico" perché hanno un significato diverso per i numeri rispetto alle stringhe (e altri tipi di dati).

La parola chiave def definisce la funzione con i parametri tra parentesi e il codice rientrato. La prima riga di una funzione può essere una stringa di documentazione ("docstring") che descrive lo scopo della funzione. La docstring può essere una descrizione a riga singola o su più righe, come nell'esempio precedente. Sì, si tratta delle "citazioni triple", una funzionalità esclusiva di Python. Le variabili definite nella funzione sono locali di quella funzione, quindi il "risultato" nella funzione precedente è separato da una variabile "risultato" in un'altra funzione. L'istruzione return può utilizzare un argomento, nel qual caso si tratta del valore restituito al chiamante.

Di seguito è riportato il codice che chiama la funzione ripeti() di cui sopra, stampando ciò che restituisce:

def main():
    print(repeat('Yay', False))      ## YayYayYay
    print(repeat('Woo Hoo', True))   ## Woo HooWoo HooWoo Hoo!!!

In fase di esecuzione, le funzioni devono essere definite dall'esecuzione di una "def" prima di essere chiamate. È tipico definire una funzione main() nella parte inferiore del file con le funzioni che richiama sopra.

Rientro

Una caratteristica insolita di Python è che il rientro degli spazi vuoti di una porzione di codice influisce sul suo significato. Un blocco logico di istruzioni, come quelli che compongono una funzione, deve avere tutti lo stesso rientro, impostato dal rientro della relativa funzione padre, da "if" o altro. Se una delle righe di un gruppo ha un rientro diverso, viene segnalato come errore di sintassi.

L'uso degli spazi vuoti da parte di Python sembra un po' strano all'inizio, ma è logico e ho scoperto che mi sono abituato a questo campo molto velocemente. Evita di utilizzare le TAB perché complicano notevolmente lo schema di rientro (per non parlare delle TAB possono avere significati diversi su piattaforme diverse). Imposta l'editor in modo da inserire spazi anziché TAB per il codice Python.

Una domanda comune che i principianti si pongono è "Di quanti spazi devo applicare il rientro?". Secondo la guida di stile Python ufficiale (PEP 8), dovresti inserire un rientro di 4 spazi. Curiosità: le linee guida per lo stile interne di Google stabiliscono il rientro di 2 spazi.

Codice verificato in fase di runtime

Python esegue pochissimi controlli al momento della compilazione, rinviando quasi tutti i controlli di tipo, nome e così via su ogni riga fino all'esecuzione di quella riga. Supponiamo che la funzione main() sopra riportata chiami ripetute() come segue:

def main():
    if name == 'Guido':
        print(repeeeet(name) + '!!!')
    else:
        print(repeat(name))

L'istruzione if contiene un errore ovvio, in cui la funzione ripeti() viene accidentalmente digitata come repeeeet(). La cosa divertente in Python ... questo codice viene compilato e funziona bene purché il nome in fase di runtime non sia "Guido". Solo quando un'esecuzione tenta effettivamente di eseguire repeeeet(), noterà che la funzione non esiste e genererà un errore. È presente anche un secondo errore in questo snippet. non è stato assegnato un valore prima di essere confrontato con "Guido". Python genererà un errore "NameError" se provi a valutare una variabile non assegnata. Questi sono alcuni esempi che dimostrano che quando esegui per la prima volta un programma Python, alcuni dei primi errori che vedi sono semplici errori di battitura o variabili non inizializzate come questi. Questa è un'area in cui i linguaggi con un sistema di tipi più dettagliato, come Java, hanno un vantaggio ... possono rilevare questi errori al momento della compilazione (ma ovviamente devi mantenere tutte le informazioni di quel tipo ... si tratta di un compromesso).

Python 3 ha introdotto i suggerimenti per i tipi. I suggerimenti relativi ai tipi consentono di indicare il tipo per ciascun argomento di una funzione nonché il tipo dell'oggetto restituito dalla funzione. Ad esempio, nella funzione annotata def is_positive(n: int) -> bool:, l'argomento n è int e il valore restituito è bool. Esamineremo cosa significano questi tipi più avanti. I suggerimenti relativi al tipo di testo sono però del tutto facoltativi. Vedrai un numero sempre maggiore di suggerimenti relativi all'adozione di codici perché, se li usi, alcuni editor, come cider-v e VS.code, possono eseguire controlli per verificare che le funzioni vengano chiamate con i tipi di argomento corretti. Possono persino suggerire e convalidare gli argomenti mentre modifichi il codice. Questo tutorial non riguarda i suggerimenti relativi ai tipi, ma vogliamo assicurarci che tu ne sia a conoscenza se li conosci o li vedi all'aperto.

Nomi variabili

Poiché le variabili Python non hanno alcun tipo specificato nel codice sorgente, è particolarmente utile assegnare nomi significativi alle variabili per ricordarti cosa sta succedendo. Quindi utilizza "name" se è un nome singolo e "names" se è un elenco di nomi e "tuples" se è un elenco di tuple. Molti errori Python di base derivano dall'abbandono del tipo di valore in ogni variabile, quindi utilizza i nomi delle variabili (tutto ciò che hai a disposizione) per fare in modo che le cose vadano bene.

Per quanto riguarda la denominazione effettiva, alcune lingue preferiscono sottolineare_parti per i nomi delle variabili composti da "più di una parola", mentre altre lingue preferiscono camelCasing. In generale, Python preferisce il metodo del trattino basso, ma guida gli sviluppatori a rimandare a camelCasing se integra il codice Python esistente che utilizza già questo stile. La leggibilità conta. Scopri di più nella sezione sulle convenzioni di denominazione in PEP 8.

Come puoi intuire, parole chiave come "if" e "while" non possono essere utilizzate come nomi di variabili; se scegli di farlo, riceverai un errore di sintassi. Tuttavia, fai attenzione a non utilizzare gli elementi integrati come nomi di variabili. Ad esempio, mentre "str", "list" e "print" possono sembrare nomi validi, vengono sostituite queste variabili di sistema. I componenti integrati non sono parole chiave e, pertanto, sono suscettibili all'uso involontario da parte dei nuovi sviluppatori Python.

Scopri di più sui moduli e sui relativi spazi dei nomi

Supponi di avere un modulo "binky.py" che contiene "def foo()". Il nome completo di tale funzione foo è "binky.foo". In questo modo, vari moduli Python possono denominare le loro funzioni e variabili come preferiscono e i nomi delle variabili non entrano in conflitto: modulo1.foo è diverso da modulo2.foo. Nel vocabolario Python direi che binky, modulo1 e modulo2 hanno ciascuno i propri "spazi dei nomi", che, come puoi intuire, sono associazioni variabili nome-oggetto.

Ad esempio, abbiamo il modulo "sys" standard che contiene alcune funzionalità di sistema standard, come l'elenco argv e la funzione exit(). Con l'istruzione "import sys" puoi accedere alle definizioni nel modulo sys e renderle disponibili con il loro nome completo, ad esempio sys.exit(). (Sì, "sys" ha uno spazio dei nomi!)

  import sys

  # Now can refer to sys.xxx facilities
  sys.exit(0)

Esiste un altro modulo di importazione simile al seguente: "from sys import argv, exit". In questo modo argv e exit() sono disponibili con i loro nomi brevi; tuttavia, consigliamo di utilizzare il formato originale con i nomi completi, perché è molto più facile determinare l'origine di una funzione o di un attributo.

Esistono molti moduli e pacchetti in bundle con un'installazione standard dell'interprete Python, quindi non devi fare nulla per utilizzarli. Questi sono noti collettivamente come "libreria standard di Python". I moduli/pacchetti più utilizzati includono:

  • sys: accesso a exit(), argv, stdin, stdout, ...
  • re: espressioni regolari
  • sistema operativo: interfaccia del sistema operativo, file system

È possibile trovare la documentazione di tutti i moduli e i pacchetti della Libreria standard all'indirizzo http://docs.python.org/library.

Guida online, help() e dir()

Esistono vari modi per ricevere assistenza per Python.

  • Esegui una ricerca su Google, iniziando con la parola "python", ad esempio "python list" o "python string minuscolo". Il primo hit è spesso la risposta. Questa tecnica sembra funzionare meglio per Python che per altri linguaggi, per qualche motivo.
  • Il sito ufficiale dei documenti Python, docs.python.org, contiene documenti di alta qualità. Ciononostante, spesso trovo più rapidamente una ricerca di un paio di parole su Google.
  • Esiste anche una mailing list ufficiale di Tutor progettata appositamente per chi non ha dimestichezza con Python e/o la programmazione.
  • Puoi trovare molte domande (e risposte) su StackOverflow e Quora.
  • Utilizza le funzioni help() e dir() (vedi sotto).

All'interno dell'interprete Python, la funzione help() estrae stringhe di documentazione per vari moduli, funzioni e metodi. Queste stringhe doc sono simili al javadoc di Java. La funzione dir() indica gli attributi di un oggetto. Di seguito sono riportati alcuni modi per chiamare help() e dir() dall'interprete:

  • help(len): stringa della guida per la funzione len() integrata; tieni presente che è "len" e non "len()", che è una chiamata alla funzione, che non vogliamo
  • help(sys): stringa della guida per il modulo sys (deve prima eseguire un import sys)
  • dir(sys): dir() è simile a help(), ma fornisce solo un breve elenco dei suoi simboli definiti o "attributi"
  • help(sys.exit): stringa della guida per la funzione exit() nel modulo sys
  • help('xyz'.split): stringa della guida per il metodo split() per gli oggetti stringa. Puoi chiamare help() con l'oggetto stesso o con un esempio di quell'oggetto e il suo attributo. Ad esempio, chiamare help('xyz'.split) equivale a chiamare help(str.split).
  • help(list): stringa della guida per list oggetti
  • dir(list): mostra list attributi dell'oggetto, inclusi i relativi metodi
  • help(list.append): stringa della guida per il metodo append() per list oggetti