Python Crash
Course
Enrico Franchi
Parlando del
futuro...
We will perhaps eventually be
writing only small modules that are
identified by name as they are
used to build larger ones, so that
devices like indentation, rather than
delimiters, might become feasible
for expressing local structure in the
source language.

Donald E. Knuth, Structured
Programming with go to
Statements, 1974
Introduzione
 Python è concepito da Guido Van Rossum alla fine degli anni
 ‘80 per interfacciarsi al sistema operativo distribuito Amoeba
 di Tanenbaum.
 La prima versione pubblica è del 1991, la prima versione
 stabile del 1994.
 Nasce come linguaggio di alto livello ed orientato agli oggetti.
 Utilizzato per programmazione di sistema e di rete, e calcolo
 scientifico
 Si impone in ambito web, con soluzioni come Zope/Plone,
 Django e Nevow (basato su Twisted).
Piattaforma Python
 un “very high-level language” (VHLL), con:
   sintassi pulita e scarna
   semantica semplice, regolare, potente
   object-oriented, ma multi-paradigma
   produttività tramite: modularità,
   uniformità, semplicità, pragmatismo
 una ricca libreria standard di moduli
 tanti strumenti ed estensioni di terze-parti
 un’implementazione in C e altre per .NET e Java
Comunità Python
Una forte comunitá open-source
Molti utenti (individui e compagnie) tutti i campi
Python Software Foundation
Gruppi d’interesse per argomenti specifici
Gruppi locali
Siti web, newsgroup, mailing list, ...
Corsi, laboratori, tutorial, ...
... e tanti LIBRI (+ che altro in inglese...) in linea,
su carta, o entrambi
Fondamentali di Python
 interprete interattivo (prompts: principale
 >>> , ... significa "continua l’istruzione") >>>   a = 4 + 2
                                             >>>   l = [1, 2, 3]
 file sorgenti tipo foo.py                    >>>   if a in l:
                                             ...       print "Got it!"
 auto-compilato a foo.pyc all’import         ...   else:
 assegnazione semplice:                      ...       print "Boo!"
                                             ...
 <nome> = <espressione>                      Boo!
   connette il nome al valore dell’espressione
   i nomi non vengono "dichiarati"
 i nomi non hanno "tipo" (gli oggetti sí!)
 None: segnaposto per "qui non c'é nulla"
I/O elementare
 due funzioni built-in per l'input elementare
   input(prompt): l'utente immette qualsiasi
   espressione Python -- ne torna il valore
   raw_input(prompt): torna    una stringa, rimuove il
   n a fine stringa
 una istruzione per l'output elementare
   print   <0+ espressioni separate da virgole>
   separa i risultati con uno spazio
   n alla fine (ma non se finite con virgola)
   print di suo non fa formattazioni speciali
Esempi Elementari
print 'Ciao, mondo!' # IL classico!-)
x = 23    # il nome x ora significa 23
print x   # emette 23
x = 'foo' # ma ora invece significa 'foo'
print x   # emette foo
del x     # il nome x torna indefinito
print x   # é un errore ("eccezione")
y = None # nome y definito... a None
print y   # emette None
Analogie con Java
 entrambi tipicamente compilati → bytecode
   ma: compilazione implicita ("auto-make")
 “tutto” eredita da “object”
   ma: anche numeri, funzioni, classei, ...
   “tutto é di prima-classe”, no “box/unbox”
 semantica uniforme di object-reference
   assegnazione, argomenti, return
 garbage collection (ma: sottili differenze)
 “marginalia” chiave: vasta librerie standard,
 introspezione, serializzazione, thread, ..
Analogie con C++
multi-paradigma (non solo OOP forzato)
  OOP, procedurale, generico, un po' di FP
ereditarietà multipla
overloading degli operatori
  ma: non per l'assegnazione semplice
polimorfismo “basato su signature”
  come se “tutto fosse un template”
sin troppe scelte per gli aspetti collaterali
  GUI, Web & altri lavori di rete, DB, IPC e calcolo
  concorrente e distribuito, ...
Python vs Java/C++/C
tipi: forti ma dinamici
  i nomi non hanno tipi: gli oggetti li hanno
  “tipizzazione ad anitra” AKA “duck typing” (se
  cammina come un’anitra, &c)
niente “dichiarazioni”, solo istruzioni
sintassi spoglia, niente ornamentazione
  “niente pixel sprecati”
     no { } per i blocchi, solo indentazione
     no ( ) per le condizioni in if e while    j = 1100
     generalmente poca punteggiatura           s = ‘Bianchi’
“tutto” é un oggetto di prima-classe           e = Emp(‘Marco’, s, j)
Controllo di Flusso
 if <expr>: <blocco annidato>
   0+ elif <expr>: <blocco annidato>
   facoltativamente: else: <blocco annidato>
 while <expr>: <blocco annidato>
   nel blocco, puó avere break continue
   facoltativamente: else: <blocco annidato>
 for <name> in <iterable>:
   break, continue, else:, come il while
 with <expr> as <name>: (2.5: importa dal futuro)
Esempi di if e while
a = 23
b = 45
if a > b:
  print a, 'maggiore di', b
elif a == b:
  print a, 'eguale a', b
else:
  print a, 'minore di', b
while a < b:
  print a, b
  a = a * 2
Tipi built-in semplici
 numeri: int, long, float, complex
   23 943721743892819 0x17 2.3 4.5+6.7j
   operatori: + - * ** / // % ~ & | ^ << >>
   built-in: abs min max pow round sum
 stringhe: semplici e Unicode
   'singoli' "doppi" r'cruda' u"nicode" n &c
   operatori: + (cat), * (rep), % (formato)
   ricco "format language" (tipo printf)
   built-in: chr ord unichr
   sono sequenze R/O: len, index/slice, for
   tanti ma tanti metodi: capitalize, center, ...
Scoprire i Metodi
>>> dir('anystring')
['__add__', '__class__', '__contains__', '__delattr__',
'__doc__', '__eq__', '__ge__', '__getattribute__',
'__getitem__', '__getnewargs__', '__getslice__', '__gt__',
'__hash__', '__init__', '__le__', '__len__', '__lt__',
'__mod__', '__mul__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__rmod__', '__rmul__',
'__setattr__', '__str__', 'capitalize', 'center', 'count',
'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index',
'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip',
'partition', 'replace', 'rfind', 'rindex', 'rjust',
'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate',
'upper', 'zfill']
Esplorare più a fondo...

>>> help(''.center)
Help on builtin function center:
center(...)
  S.center(width[, fillchar]) -> string
  Returns S centered in a string of length
  width. Padding is done using the
  specified fill character (default is
  a space)
(END)
>>>
... e sperimentare!
>>> 'ciao'.center(10, '+')
'+++ciao+++'
>>> 'ciao'.center(3, '+')
'ciao'
>>> 'ciao'.center(9, '+')
'+++ciao++'

Puoi anche scrivere unit-tests per il tuo codice in
questo stile (esempio d'uso, risultato previsto); fai
import doctest; help(doctest) al prompt
dell'interprete interattivo
Tipi built-in “contenitori”
tuple: sequenza immutable
  () (23,) (23, 45) tuple('ciao')
list: sequenza mutabile (un "vettore")
  [] [23] [23, 45] list('ciao')
set e frozenzet: semplici tabelle hash
  set() set((23,)) set('ciao')
dict: mappa chiave → valore via tabella hash
  {} {2:3} {4:5, 6:7} dict(ci='ao')
i contenitori hanno: len(c), cicli (for x in c), test di
appartenenza (if x in c)
e di solito metodi (set anche operatori)
Sequenze
stringhe, tuple e liste sono sequenze (altri tipi di
sequenza sono nella libreria standard)
ripetizione (c*N), catenazione (c1+c2)
indici: c[i], fette: c[i:j] e c[i:j:k]:
   'ciao'[2]=='a', 'ciao'[3:1:-1]=='oa'
   sempre: primo limite incluso, ultimo escluso (Koenig)
le liste sono sequenze mutabili, quindi si può
assegnare a un indice o fetta
   assegnare a una fetta cambia lunghezza
dict e set non sono sequenze
Contenitori (again)
 metodi mutatori vs non-mutatori
   i mutatori di solito tornano None
      e.g.: lst.append, st.add, dct.update
   dict ha alcuni mutatori non-None:
      dct.pop, dct.setdefault
 set ha la variante frozenset (immutabile)
 dict ha la variante defaultdict (in collections)
 pure in collections: deque (sequenza con
 metodi ...left, clear, rotate; no fette, no sort)
 non c'é un tipo heap, ma funzioni di heap per le
 liste nel modulo heapq
Paragoni, Test, Verità
 eguaglianza, identitá: == != is is not
 ordine:                < > <= >=
 contenimento:           in not in
 "catena":           3 <= x < 9
 falsi: numeri == 0, "", None, contenitori vuoti,
 False (aka bool(0))
 veri: tutto il resto, True (aka bool(1))
 not x == not bool(x) per qualsiasi x

 and, or “corto-circuito” (→ torna operando)

 idem built-in any, all → torna un bool)
Eccezioni
 Errori (e “anomalie” che non sono errori)
 “sollevano eccezioni” (istanze di Exception o
 qualsiasi sottotipo di Exception -- ma anche no)
 L’istruzione raise solleva un’eccezione
 Le eccezioni si propagano “lungo lo stack delle
 chiamate”, man mano terminando le funzioni,
 sinché non vengono “catturate”
 Se non catturate, terminano il programma
 L'istruzione try/except può catturare eccezioni
 (anche: try/finally, e l'elegante with per
 implementare “RAII”)
Iteratori e cicli for
for i in c: <body>
                              [p for p in nums if isprime(p)]
_t = iter(c)
while True:
  try: i = _t.next()
  except StopIteration: break
  <body>

anche: (<expr>for i in c <opt.clauses>)
      [<expr> for i in c <opt.clauses>]
      ("genexp" e "list comprehension")
Funzioni
 def <nome>(<parametri>): <corpo>
   <corpo> compilato, ma non subito eseguito
   <parametri>: 0+ variabili locali, inizializzate alla
   chiamata dagli <args> passati
   gli 0+ ultimi parameters possono avere "valori di
   default", <nome>=<expr> (expr é valutata una
   sola volta, quando def esegue)
   <parametri> puó finire con *<nome> (tupla di
   arbitrari arg posizionali) e/o **<nome> (dict di
   arbitrari arg con nome)
Esempio: somma di
quadrati
def sumsq(a, b): return a*a+b*b
print sumsq(23, 45)

O, piú generale:
def sumsq(*a): return sum(x*x for x in a)

Minore livello di astrazione, + lento ma OK:
def sumsq(*a):
  total = 0
  for x in a: total += x*x
  return total
Generatori
def couples(l):
    i = 0                    funzioni con yield invece di
    while i < len(l)-1:      return
        yield l[i], l[i+1]
        i += 1               ogni chiamata costruisce e
                             torna un iteratore (oggetto
lst = [1, 2, 3,4 ,5, 6]      con metodo next, adatto a
for pairs in couples(lst):
    print pairs
                             essere iterato in un ciclo for)
                             la fine della funzione solleva
...
(1,   2)                     StopIteration
(2,   3)
(3,   4)
(4,   5)
(5,   6)
Generatori Infiniti

def fibonacci():
  i = j = 1
  while True:
    r, i, j = i, j, i + j
    yield r
for rabbits in fibonacci():
  print rabbits,
  if rabbits > 100: break
1 1 2 3 5 8 13 21 34 55 89 144

Pycrashcourse

  • 1.
  • 2.
    Parlando del futuro... We willperhaps eventually be writing only small modules that are identified by name as they are used to build larger ones, so that devices like indentation, rather than delimiters, might become feasible for expressing local structure in the source language. Donald E. Knuth, Structured Programming with go to Statements, 1974
  • 3.
    Introduzione Python èconcepito da Guido Van Rossum alla fine degli anni ‘80 per interfacciarsi al sistema operativo distribuito Amoeba di Tanenbaum. La prima versione pubblica è del 1991, la prima versione stabile del 1994. Nasce come linguaggio di alto livello ed orientato agli oggetti. Utilizzato per programmazione di sistema e di rete, e calcolo scientifico Si impone in ambito web, con soluzioni come Zope/Plone, Django e Nevow (basato su Twisted).
  • 4.
    Piattaforma Python un“very high-level language” (VHLL), con: sintassi pulita e scarna semantica semplice, regolare, potente object-oriented, ma multi-paradigma produttività tramite: modularità, uniformità, semplicità, pragmatismo una ricca libreria standard di moduli tanti strumenti ed estensioni di terze-parti un’implementazione in C e altre per .NET e Java
  • 5.
    Comunità Python Una fortecomunitá open-source Molti utenti (individui e compagnie) tutti i campi Python Software Foundation Gruppi d’interesse per argomenti specifici Gruppi locali Siti web, newsgroup, mailing list, ... Corsi, laboratori, tutorial, ... ... e tanti LIBRI (+ che altro in inglese...) in linea, su carta, o entrambi
  • 6.
    Fondamentali di Python interprete interattivo (prompts: principale >>> , ... significa "continua l’istruzione") >>> a = 4 + 2 >>> l = [1, 2, 3] file sorgenti tipo foo.py >>> if a in l: ... print "Got it!" auto-compilato a foo.pyc all’import ... else: assegnazione semplice: ... print "Boo!" ... <nome> = <espressione> Boo! connette il nome al valore dell’espressione i nomi non vengono "dichiarati" i nomi non hanno "tipo" (gli oggetti sí!) None: segnaposto per "qui non c'é nulla"
  • 7.
    I/O elementare duefunzioni built-in per l'input elementare input(prompt): l'utente immette qualsiasi espressione Python -- ne torna il valore raw_input(prompt): torna una stringa, rimuove il n a fine stringa una istruzione per l'output elementare print <0+ espressioni separate da virgole> separa i risultati con uno spazio n alla fine (ma non se finite con virgola) print di suo non fa formattazioni speciali
  • 8.
    Esempi Elementari print 'Ciao,mondo!' # IL classico!-) x = 23 # il nome x ora significa 23 print x # emette 23 x = 'foo' # ma ora invece significa 'foo' print x # emette foo del x # il nome x torna indefinito print x # é un errore ("eccezione") y = None # nome y definito... a None print y # emette None
  • 9.
    Analogie con Java entrambi tipicamente compilati → bytecode ma: compilazione implicita ("auto-make") “tutto” eredita da “object” ma: anche numeri, funzioni, classei, ... “tutto é di prima-classe”, no “box/unbox” semantica uniforme di object-reference assegnazione, argomenti, return garbage collection (ma: sottili differenze) “marginalia” chiave: vasta librerie standard, introspezione, serializzazione, thread, ..
  • 10.
    Analogie con C++ multi-paradigma(non solo OOP forzato) OOP, procedurale, generico, un po' di FP ereditarietà multipla overloading degli operatori ma: non per l'assegnazione semplice polimorfismo “basato su signature” come se “tutto fosse un template” sin troppe scelte per gli aspetti collaterali GUI, Web & altri lavori di rete, DB, IPC e calcolo concorrente e distribuito, ...
  • 11.
    Python vs Java/C++/C tipi:forti ma dinamici i nomi non hanno tipi: gli oggetti li hanno “tipizzazione ad anitra” AKA “duck typing” (se cammina come un’anitra, &c) niente “dichiarazioni”, solo istruzioni sintassi spoglia, niente ornamentazione “niente pixel sprecati” no { } per i blocchi, solo indentazione no ( ) per le condizioni in if e while j = 1100 generalmente poca punteggiatura s = ‘Bianchi’ “tutto” é un oggetto di prima-classe e = Emp(‘Marco’, s, j)
  • 12.
    Controllo di Flusso if <expr>: <blocco annidato> 0+ elif <expr>: <blocco annidato> facoltativamente: else: <blocco annidato> while <expr>: <blocco annidato> nel blocco, puó avere break continue facoltativamente: else: <blocco annidato> for <name> in <iterable>: break, continue, else:, come il while with <expr> as <name>: (2.5: importa dal futuro)
  • 13.
    Esempi di ife while a = 23 b = 45 if a > b: print a, 'maggiore di', b elif a == b: print a, 'eguale a', b else: print a, 'minore di', b while a < b: print a, b a = a * 2
  • 14.
    Tipi built-in semplici numeri: int, long, float, complex 23 943721743892819 0x17 2.3 4.5+6.7j operatori: + - * ** / // % ~ & | ^ << >> built-in: abs min max pow round sum stringhe: semplici e Unicode 'singoli' "doppi" r'cruda' u"nicode" n &c operatori: + (cat), * (rep), % (formato) ricco "format language" (tipo printf) built-in: chr ord unichr sono sequenze R/O: len, index/slice, for tanti ma tanti metodi: capitalize, center, ...
  • 15.
    Scoprire i Metodi >>>dir('anystring') ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
  • 16.
    Esplorare più afondo... >>> help(''.center) Help on builtin function center: center(...) S.center(width[, fillchar]) -> string Returns S centered in a string of length width. Padding is done using the specified fill character (default is a space) (END) >>>
  • 17.
    ... e sperimentare! >>>'ciao'.center(10, '+') '+++ciao+++' >>> 'ciao'.center(3, '+') 'ciao' >>> 'ciao'.center(9, '+') '+++ciao++' Puoi anche scrivere unit-tests per il tuo codice in questo stile (esempio d'uso, risultato previsto); fai import doctest; help(doctest) al prompt dell'interprete interattivo
  • 18.
    Tipi built-in “contenitori” tuple:sequenza immutable () (23,) (23, 45) tuple('ciao') list: sequenza mutabile (un "vettore") [] [23] [23, 45] list('ciao') set e frozenzet: semplici tabelle hash set() set((23,)) set('ciao') dict: mappa chiave → valore via tabella hash {} {2:3} {4:5, 6:7} dict(ci='ao') i contenitori hanno: len(c), cicli (for x in c), test di appartenenza (if x in c) e di solito metodi (set anche operatori)
  • 19.
    Sequenze stringhe, tuple eliste sono sequenze (altri tipi di sequenza sono nella libreria standard) ripetizione (c*N), catenazione (c1+c2) indici: c[i], fette: c[i:j] e c[i:j:k]: 'ciao'[2]=='a', 'ciao'[3:1:-1]=='oa' sempre: primo limite incluso, ultimo escluso (Koenig) le liste sono sequenze mutabili, quindi si può assegnare a un indice o fetta assegnare a una fetta cambia lunghezza dict e set non sono sequenze
  • 20.
    Contenitori (again) metodimutatori vs non-mutatori i mutatori di solito tornano None e.g.: lst.append, st.add, dct.update dict ha alcuni mutatori non-None: dct.pop, dct.setdefault set ha la variante frozenset (immutabile) dict ha la variante defaultdict (in collections) pure in collections: deque (sequenza con metodi ...left, clear, rotate; no fette, no sort) non c'é un tipo heap, ma funzioni di heap per le liste nel modulo heapq
  • 21.
    Paragoni, Test, Verità eguaglianza, identitá: == != is is not ordine: < > <= >= contenimento: in not in "catena": 3 <= x < 9 falsi: numeri == 0, "", None, contenitori vuoti, False (aka bool(0)) veri: tutto il resto, True (aka bool(1)) not x == not bool(x) per qualsiasi x and, or “corto-circuito” (→ torna operando) idem built-in any, all → torna un bool)
  • 22.
    Eccezioni Errori (e“anomalie” che non sono errori) “sollevano eccezioni” (istanze di Exception o qualsiasi sottotipo di Exception -- ma anche no) L’istruzione raise solleva un’eccezione Le eccezioni si propagano “lungo lo stack delle chiamate”, man mano terminando le funzioni, sinché non vengono “catturate” Se non catturate, terminano il programma L'istruzione try/except può catturare eccezioni (anche: try/finally, e l'elegante with per implementare “RAII”)
  • 23.
    Iteratori e ciclifor for i in c: <body> [p for p in nums if isprime(p)] _t = iter(c) while True: try: i = _t.next() except StopIteration: break <body> anche: (<expr>for i in c <opt.clauses>) [<expr> for i in c <opt.clauses>] ("genexp" e "list comprehension")
  • 24.
    Funzioni def <nome>(<parametri>):<corpo> <corpo> compilato, ma non subito eseguito <parametri>: 0+ variabili locali, inizializzate alla chiamata dagli <args> passati gli 0+ ultimi parameters possono avere "valori di default", <nome>=<expr> (expr é valutata una sola volta, quando def esegue) <parametri> puó finire con *<nome> (tupla di arbitrari arg posizionali) e/o **<nome> (dict di arbitrari arg con nome)
  • 25.
    Esempio: somma di quadrati defsumsq(a, b): return a*a+b*b print sumsq(23, 45) O, piú generale: def sumsq(*a): return sum(x*x for x in a) Minore livello di astrazione, + lento ma OK: def sumsq(*a): total = 0 for x in a: total += x*x return total
  • 26.
    Generatori def couples(l): i = 0 funzioni con yield invece di while i < len(l)-1: return yield l[i], l[i+1] i += 1 ogni chiamata costruisce e torna un iteratore (oggetto lst = [1, 2, 3,4 ,5, 6] con metodo next, adatto a for pairs in couples(lst): print pairs essere iterato in un ciclo for) la fine della funzione solleva ... (1, 2) StopIteration (2, 3) (3, 4) (4, 5) (5, 6)
  • 27.
    Generatori Infiniti def fibonacci(): i = j = 1 while True: r, i, j = i, j, i + j yield r for rabbits in fibonacci(): print rabbits, if rabbits > 100: break 1 1 2 3 5 8 13 21 34 55 89 144