Introduzione al
Linguaggio Python
Enrico Franchi
enrico.franchi@gmail.com
franchi@cs.unipr.it
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
Introduzione
 Python è concepito da Guido van Rossum alla fine
 degli anni ‘80 per Amoeba
Introduzione
 Python è concepito da Guido van Rossum alla fine
 degli anni ‘80 per Amoeba
 Pubblico 1991, stabile 1994.
Introduzione
 Python è concepito da Guido van Rossum alla fine
 degli anni ‘80 per Amoeba
 Pubblico 1991, stabile 1994.
 Linguaggio di alto livello ed orientato agli oggetti.
Introduzione
 Python è concepito da Guido van Rossum alla fine
 degli anni ‘80 per Amoeba
 Pubblico 1991, stabile 1994.
 Linguaggio di alto livello ed orientato agli oggetti.
 Utilizzato per programmazione di sistema e di rete, e
 calcolo scientifico, applicazioni desktop, integrazione di
 videogiochi
Introduzione
 Python è concepito da Guido van Rossum alla fine
 degli anni ‘80 per Amoeba
 Pubblico 1991, stabile 1994.
 Linguaggio di alto livello ed orientato agli oggetti.
 Utilizzato per programmazione di sistema e di rete, e
 calcolo scientifico, applicazioni desktop, integrazione di
 videogiochi
 Si impone in ambito web/enterprise, con soluzioni
 come Zope/Plone, Django e Nevow (basato su
 Twisted).
Piattaforma Python
 “Very high-level language” (VHLL):
   sintassi pulita e scarna
   semantica semplice, regolare, potente
   object-oriented, ma multi-paradigma
   produttività tramite: modularità, uniformità,
   semplicità, pragmatismo
 Offre una ricca libreria standard di moduli
 Tanti strumenti ed estensioni di terze-parti
 Implementazione in C, Java e.NET
Comunità Python
Una forte comunitá open-source
Molti utenti (individui e compagnie) in tutti i campi
Python Software Foundation (in Italia, Python Italia)
Gruppi d’interesse per argomenti specifici
Siti web, newsgroup, mailing list, ...
Corsi, laboratori, tutorial, conferenze (Pycon Italia, tre
edizioni, più grande conferenza open italiana)
Molti (specialmente in inglese...) in linea, su carta, o
entrambi
Indice TIOBE Marzo 2009
Sesto linguaggio più diffuso
secondo l’indice TIOBE e in        Linguaggio Pos.   Diff.
crescita continua              1     Java            -1.7%
Utilizzato presso Google       2      C              +1%
(linguaggio principale),       3     C++             +1%
NASA, Industrial Lights and
Magic, Frequentis (sicurezza   4     PHP             -0.4%
aerea), ...                    5      VB             -3.3%
                               6    Python           +0.4%
                               7      C#             -0.2%
Python da 3000 metri (1)
 Python é un linguaggio ad oggetti a tipizzazione
 dinamica e forte
   Tipizzazione forte:
     Gli errori di tipo sono sempre generati. Es. Stringhe
     non diventano interi e viceversa
     Ogni oggetto ha una classe, questa non cambia
   Tipizzazione dinamica
     Gli errori di tipo sono generati a runtime
     Duck typing
Python da 3000 metri
 In Python tutto é un oggetto:
   Un numero, una stringa sono oggetti
   Gli oggetti sono oggetti (ehm...)
   Una funzione é un oggetto
   Una classe é un oggetto
 Gli oggetti sono cittadini di prima classe,
 possiamo manipolarli riccamente e
 comodamente
 Possiamo fare, in definitiva, tutto
Versioni
 Python é notevolmente compatibile fra versioni
 diverse
 Gli esempi di queste slides funzioneranno con
 Python 2.5 o Python 2.6, a meno che altrimenti
 specificato
   La maggior parte funzioneranno anche con
   Python 2.4 e Python 2.3
 Python 3.0 é una major release non pensata
 ancora per essere usata in produzione. É il
 Python di domani, ma oggi é oggi
Dettagli implementativi
 Tipicamente Python viene       % cat hello.py
                                #!/usr/bin/python
 compilato a byte-code e
 questo viene interpretato da   print "Hello, world!"
 una macchina virtuale (come
                                % python hello.py
 Java)                          Hello, world!
 Diversamente da Java la        % chmod 755 hello.py
                                % ./hello.py
 compilazione é trasparente     Hello, world!
 per l’utente                   % python
                                Python 2.5.1 (...)
 Possiamo anche usare           ...
 l’interprete interattivo       >>> print "Hello, world"
                                Hello, world
Interprete interattivo
 L’interprete interattivo ufficiale ha
                                        >>> import os
 come prompt >>>                        >>> print 'foo'
                                        foo
 Scriviamo comandi (statements)         >>> os.getcwd()
                                        '/Users/enric/uni/pycourse'
 che vengono byte-compilati ed          >>> import sys
                                        >>> sys.stdout.write('ciaon')
 eseguiti                               ciao
                                        >>> def f(a):
 Se il comando valuta in un             ...   sys.stdout.write(a)
                                        ...   return a
 espressione (es. un expression         ...
 statement), l’espressione viene        >>> f('ciaon')
                                        ciao
 stampata                               'ciaon'
Letterali
                                    >>> 12            >>> 3.2E10
 Numeri interi, float                12                32000000000.0
                                    >>> -27           >>> 'ciao'
   Base 10, 8, 16                   -27               'ciao'
                                    >>> 0x6A          >>> "ciao"
   Scientifica, fixpoint              106               'ciao'
                                    >>> 0.216         >>> 'c'
                                    0.216             'c'
 Stringhe
                                    >>> [1, 2, "a", 2.32, "ciao"]
   Apici singoli o doppi            [1, 2, 'a', 2.3199999999999998, 'ciao']
                                    >>> '''Testo con
   Tre apici per testo multilinea   ... piu' linee
                                    ... di testo'''
 Liste                              "Testo connpiu' lineendi testo"
                                    >>> """Ancora testo con
                                    ... piu' linee di testo"""
   Fra quadre, separate da          "Ancora testo connpiu' linee di testo"
   virgola
a = 16
                                                          print a
                                                          a = 7.6


Variabili
                                                          print a
                                                          print a * 2
                                                          a = 'ciao'



                                  i=1
 In Python una variabile é        print i, type(i)
 semplicemente un nome, un        # => 1 <type 'int'>
                                  d = 217.217
 etichetta, un modo per           print d, type(d)
                                  # => 217.217 <type 'float'>
 riferirsi ad un oggetto          s = '''Solito testo
                                  su piu' righe'''
 Le variabili non hanno tipo,     print s, type(s)
                                  # => Solito testo
 gli oggetti hanno tipo           # su piu' righe <type 'str'>
                                  d=2
 Una etichetta può riferirsi ad   print d, type(d)
                                  # => 2 <type 'int'>
 oggetti di diverso tipo nel      i = 32761293836219387269827
                                  print i, type(i)
 tempo                            # => 32761293836219387269827 <type
                                  'long'>
 Assegnamento é statement
Ancora letterali
 Tuple:                            >>> t = 1, 2, 'a'
                                   >>> a, b, c = t
   Sequenza di oggetti non         >>> print b
                                   2
   modificabile                     >>> print t
                                   (1, 2, 'a')
   Facile da pack/unpack           >>> str(1, 2, 3)
                                   Traceback (most recent call last):
   Precedenza                        File "<stdin>", line 1, in <module>
                                   TypeError: str() takes at most 1
                                   argument (3 given)
 Dizionario (array associativo):   >>> str((1, 2, 3))
                                   '(1, 2, 3)'
   Coppie chiave/valore            >>> d = {'foo' : 1, 'bar': 8}
                                   >>> d
   Inserimento/Accesso O(1)        {'foo': 1, 'bar': 8}


   Chiavi “immutabili”
Help system
                                 >>> help(os.getcwd)
La funzione help() da aiuto su   getcwd(...)
                                   getcwd() -> path
una funzione/classe/modulo
                                   Return a string representing the current working direc
etc.                             >>> help(sys)
                                 Help on built-in module sys:
Se chiamata sull’istanza di
                                 NAME
una classe (quindi anche un        sys
numero o una stringa) da         FILE
informazioni sulla classe           (built-in)

Di fatto va a leggere le         MODULE DOCS
                                   http://www.python.org/doc/current/lib/module-sys.h
‘docstring’ (vediamo poi...)
                                 DESCRIPTION
                                   This module provides access to some objects used or
Consideriamo anche pydoc           interpreter and to functions that interact strongly with
Help system
>>> help(os.getcwd)
getcwd(...)
  getcwd() -> path

  Return a string representing the current working directory.
>>> help(sys)
Help on built-in module sys:

NAME
  sys

FILE
   (built-in)

MODULE DOCS
  http://www.python.org/doc/current/lib/module-sys.html

DESCRIPTION
  This module provides access to some objects used or maintained by the
  interpreter and to functions that interact strongly with the interpreter.
>>> help(sys.stdout)
Help on file object:

class file(object)
 | file(name[, mode[, buffering]]) -> file object
 |
 | Open a file. The mode can be 'r', 'w' or 'a' for reading (default),
 | writing or appending. The file will be created if it doesn't exist
 | when opened for writing or appending; it will be truncated when
 | opened for writing. Add a 'b' to the mode for binary files.
                                 ...
bash> pydoc os.path.join
Help on function join in os.path:

os.path.join = join(a, *p)
  Join two or more pathname components, inserting '/' as needed


bash> pydoc -p 8080
pydoc server ready at http://localhost:8080/


% python
>>> help()

Welcome to Python 2.5! This is the online help utility.

help>
>>> help(sys.stdout)
Help on file object:

class file(object)
 | file(name[, mode[, buffering]]) -> file object
 |
 | Open a file. The mode can be 'r', 'w' or 'a' for reading (default),
 | writing or appending. The file will be created if it doesn't exist
 | when opened for writing or appending; it will be truncated when
 | opened for writing. Add a 'b' to the mode for binary files.
                                 ...
bash> pydoc os.path.join
Help on function join in os.path:

os.path.join = join(a, *p)
  Join two or more pathname components, inserting '/' as needed


bash> pydoc -p 8080
pydoc server ready at http://localhost:8080/


% python
>>> help()

Welcome to Python 2.5! This is the online help utility.

help>
Controllo di flusso
 Condizionale:           Su if c’é poco da dire; while
    if cond:             si usa rarissimamente, grazie ai
    statement
 else:                   generatori si preferisce for
    statement
                         Siccome l’assegnamento é uno
 if cond:
     statement           statement, non é possibile
 Iterazione unbounded:   metterlo come condizione
  while cond:
   statement             (fortunatamente)
else:
   statement
                         Disponibili break/continue
                         else di for/while esegue su
while cond:
  statement              terminazione naturale (no exc/
                         cont/break/return)
Liste
                                  >>> a = [1, 2, 'a', 'ciao', 4]
 La lista é in realtà un array:   >>> a[0]
                                  1
 accesso O(1) agli elementi       >>> a[3]
                                  'ciao'
 Inserimento e rimozione in       >>> a[-1]
                                  4
 coda O(1)                        >>> a[10]
                                  Traceback (most recent call last):
 Controllo sugli indici             File "<stdin>", line 1, in <module>
                                  IndexError: list index out of range
 (IndexError)                     >>> a.append(3)
                                  >>> a
 Indici negativi contano a        [1, 2, 'a', 'ciao', 4, 3]
                                  >>> l = range(1, 4)
 partire dal fondo                >>> a.extend(l)
                                  >>> a
 Possibilità di slice             [1, 2, 'a', 'ciao', 4, 3, 1, 2, 3]
                                  >>> a.pop()
                                  3
Liste (altri metodi)
                                  >>> a
 Presenti anche:                  [1, 2, 'a', 'ciao', 4, 3, 1, 2]
                                  >>> a[1:4]
                                  [2, 'a', 'ciao']
   insert(i, o): inserisci o in   >>> a[1:8:2]
   posizione i                    [2, 'ciao', 3, 2]
                                  >>> a[::-1]
                                  [2, 1, 3, 4, 'ciao', 'a', 2, 1]
   remove(v): togli la prima      >>> a
   occorrenza di v                [1, 2, 'a', 'ciao', 4, 3, 1, 2]

   count(v): ...
                                  >>> for el in a:
   index(v): ...                  ...  print el,
                                  ...
   sort(): ...                    1 2 a ciao 4 3 1 2

 Le liste sono mutabili
Liste (altri metodi)
                                  >>> a
 Presenti anche:                  [1, 2, 'a', 'ciao', 4, 3, 1, 2]
                                  >>> a[1:4]
                                  [2, 'a', 'ciao']
   insert(i, o): inserisci o in   >>> a[1:8:2]
   posizione i                    [2, 'ciao', 3, 2]
                                  >>> a[::-1]
                                  [2, 1, 3, 4, 'ciao', 'a', 2, 1]
   remove(v): togli la prima      >>> a
   occorrenza di v                [1, 2, 'a', 'ciao', 4, 3, 1, 2]

   count(v): ...
                                  >>> for el in a:
   index(v): ...                  ...  print el,
                                  ...
   sort(): ...                    1 2 a ciao 4 3 1 2

 Le liste sono mutabili                      Virgola finale non va a capo
Tuple
                                     >>> t = tuple(a)
 “Simili” alle liste, tuttavia non   >>> t[3]
                                     'ciao'
 sono mutabili                       >>> t[-1]
                                     2
   Non possiamo aggiungere           >>> t[1:]
                                     (2, 'a', 'ciao', 4, 3, 1, 2)
   elementi                          >>> a, b, c = t[:3]
                                     >>> print a, b, c
   Non possiamo cambiare             12a
   elementi nella tupla              >>> t = 1, 2, 'x'
                                     >>> l = list(t)
   Possiamo agire su questi, se      >>> t.append(5)
                                     Traceback (most recent call last):
   non sono immutabili                File "<stdin>", line 1, in <module>
                                     AttributeError: 'tuple' object has no attribute 'append'
   Per il resto funziona tutto       >>> l.append(5)
                                     >>> l
   come previsto                     [1, 2, 'x', 5]
Stringhe
                                 >>> s = 'Hello, world! '
 Anche le stringhe sono          >>> s.strip()
 immutabili                      'Hello, world!'
                                 >>> s.replace('o', '0')
                                 'Hell0, w0rld! '
 Supportano slicing, indexing,   >>> s.find('o')
 etc.                            4
                                 >>> s.rfind('o')
                                 8
 isdigit(), ...                  >>> s.upper()
                                 'HELLO, WORLD! '
 strip()...                      >>> s.center(60)
                                 '                Hello, world!   '
 find/rfind/index/rindex(ch)       >>> s.startswith('He')
                                 True
                                 >>> s.split(‘, ‘)
 startswith/endswith(s)          ['Hello', ' world! ']

 upper/lower/capitalize()        ... andate a guardarli tutti!
Operazioni se sequenze
                                >>> s = 'ciao'
 Stringhe, tuple e liste sono   >>> m = 'mondo'
                                >>> min(s) # <= 'a'
 sequenze                       >>> max(m) # <= 'o'
                                >>> l = [1, 2, 3]
 Tutte le sequenze              >>> sum(l) # <= 6
                                >>> s + m # <= 'ciaomondo'
 supportano alcune              >>> s + l
                                Traceback (most recent call last):
 operazioni                       File "<stdin>", line 1, in <module>
                                TypeError: cannot concatenate 'str' and 'list' objects
 min/max/sum                    >>> list(s) + l
                                ['c', 'i', 'a', 'o', 1, 2, 3]
 + : concatenazione             >>> '=' * 10
                                '=========='
                                >>> [1, ] * 10
 S * n/ n * S: ripetizione      [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
                                >>> ‘a’ in s
 el in S: appartenenza          True
                                >>> ‘pippo’ in l
                                False
Attenzione!
 Sommare tanti oggetti immutabili funziona, ma crea ogni volta un
 nuovo elemento:
   Sommare 10 stringhe crea 10 nuove stringhe. E se sono 10000?
   Potrebbe essere l’ultimo pezzo di codice prima del licenziamento.
   Si usa join nella forma sep.join(elements)
   >>> l = ['usr', 'local', 'lib']
   >>> '/'.join(l)
   'usr/local/lib'
   >>> ' => '.join(l)
   'usr => local => lib'


 Per concatenare pezzi di path, usare os.path.join e i metodi
 presenti in os.path
Statement For
                                 for ch in 'ciao mondo':
 For é il modo più comune di        print ch,
 iterare in Python               print

                                 for n in range(10):
   Funziona con un generico         print n
   iterabile                     for n in xrange(10):
                                    print n
   Esprime il concetto di “per   for n in range(1, 20):
   ogni elemento in questa          print n
                                 for n in xrange(1, 10000000000):
   sequenza” fai qualcosa           print n

   Invece che usare una
   sequenza (finita), possiamo
   usare un generatore
   (potenzialmente infinito)
Statement For
                                 for ch in 'ciao mondo':
 For é il modo più comune di        print ch,
 iterare in Python               print

                                 for n in range(10):
   Funziona con un generico         print n
   iterabile                     for n in xrange(10):
                                    print n
   Esprime il concetto di “per   for n in range(1, 20):
   ogni elemento in questa          print n
                                 for n in xrange(1, 10000000000):
   sequenza” fai qualcosa           print n

   Invece che usare una
   sequenza (finita), possiamo       Attenzione! range ritorna
   usare un generatore              una lista xrange un iteratore.
   (potenzialmente infinito)         Restituiscono intervalli [a, b)
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")
Dizionari
 Array associativi/dizionari:    >>> d = {'foo' : (1, 2, 3),
                                 ...     'bar' : (2, 3, 4)}
 coppie chiave-valore            >>> d['foo']
                                 (1, 2, 3)
   Operazioni tipicamente O(1)   >>> d['baz']
                                 Traceback (most recent call last):
                                   File "<stdin>", line 1, in <module>
   Implementazione               KeyError: 'baz'
   esageratamente efficiente      >>> d['bar'] = 'foo'
                                 >>> d
                                 {'foo': (1, 2, 3), 'bar': 'foo'}
 La chiave deve essere
 hashabile e immutabile (ecco
 perché le stringhe...)
Dizionari (altri metodi)
 D.pop(k[, d]): rimuove k (se presente) restituendo
 il valore corrispondente. Altrimenti restituisce d
 se specificato o da AttributeError
 D.popitem(): ritorna una coppia k-v (qualsiasi)
 D.get(k[,d]): ritorna il valore di k o d se k non é
 presente. Se non specificato d vale None.
 D.setdefault(k[,d]): D.get(k,d), setta D[k]=d se k
 non é in D
 D.update(E, **F): aggiunge le coppie k-v di E (ed F)
 aD
Dizionari (Iterazione)
                                                                      % python dicts_example.py
d = {'foo' : (1, 2, 3),                                               foo
   'bar' : (2, 3, 4)}                                                 bar
                                                                      foo
for k in d:                                                           bar
   print k                                                            (1, 2, 3)
                                                                      (2, 3, 4)
for k in d.iterkeys():                                                foo (1, 2, 3)
   print k                                                            bar (2, 3, 4)
                                                                      foo (1, 2, 3)
for v in d.itervalues():                                              bar (2, 3, 4)
   print v

for k, v in d.iteritems(): # iteritems restituisce un iteratore alle coppie
   print k, v

for k, v in d.items(): # items restituisce una *lista*
   print k, v
Dimensione di oggetti
iterabili
 Il builtin (funzione) len dice il numero di elementi
 di ogni oggetto iterabile
 Se dispongono di un metodo __len__ chiama
 quello. Per esempio per liste, tuple, dizionari,
 stringhe, insiemi (set)
 Funziona anche su un generatore, ma in questo
 caso potrebbe doverlo scorrere
Format
Le stringhe hanno un operatore % che permette di fare “format
string” simili alla printf del C -- doc per maggiori informazioni --
stringa % tupla: sostituzione posizionale:
>>> '%s %d %s' % ('ciao', 9, ('h', 'p'))
"ciao 9 ('h', 'p')"

stringa % dizionario: sostituzione per nome:
>>> 'Mi chiamo %(surname)s, %(fname)s %(surname)s.' % {'surname': 'Bond', 'fname' : 'James'}
'Mi chiamo Bond, James Bond.'

Estremamente comodo. Usando %s si passa per str(obj), usando
%r per repr(obj)
I/O elementare
 due funzioni built-in per l'input elementare
   input(prompt): immette    qualsiasi espressione -- 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
   print >> writable, <0+ espressioni separate da virgole>
SPERIMENTATE!
Non é possibile imparare un linguaggio con una
corso frontale.
I linguaggi si imparano programmando, provando
codice etc.
In Python trovate tutto quello che vi serve o
direttamente nella libreria standard o in qualche
modulo esterno: dateci qualche occhiata
Leggete la documentazione. Studiate il codice
altrui. É estremamente leggibile e didattico
Diffidate dal codice che ha un brutto aspetto
“semplice wget” (GvR)
import sys, urllib, os

def hook(*a):
    print '%s: %s' % (fn, a)

for url in sys.argv[1:]:
    fn = os.path.basename(url)
    print url, "->", fn
    urllib.urlretrieve(url, fn, hook)
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”)
LBYL vs. EAFP
LBYL: Look before you leap
EAFP: Easier to ask forgiveness
than permission                   try:
                                     emp = employees[user_name]
                                  except KeyError:
Normalmente EAFP é la                report_error(...)
strategia migliore in Python      if user_name in emp:
                                     emp = employees[user_name]
  Eccezioni relativamente poco    else:
  costose                            report_error(...)


  Atomicità, ...
Vari tipi di try
try:
   # codice che potrebbe lanciare eccezione
except IndexError, exc:
   # un tipo di errore
   # opzionalmente si mette ‘, nome’ per avere
   # l’oggetto eccezione da gestire
except AnotherException:
   # gestione di un altro errore
except:
   # gestione di ogni eccezione
   # tipicamente *NON* e' una buona pratica
   # a meno di non rilanciare
   raise # raise vuoto rilancia l'eccezione corrente
finally:
   # questo codice e' eseguito *sempre*
   # codice di pulizia sia con errore che senza
With statement


     from __future__ import with_statement
     with file('foo.txt') as f:
        for line in f:
           print line.strip()
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
Scope delle variabili
 I parametri di una funzione e ogni variabile che
 viene legata (con assegnamento o statement
 come def o class) nel corpo di una funzione
 costituisce il namespace della funzione (local
 scope)
 Lo scope di queste variabili é tutto il corpo della
 funzione (ma usarle prima che siano state legate
 é un errore)
 Le variabili non locali sono dette globali, il loro
 scope é il modulo intero
   Normalmente non ci sono motivi per usarle
Scope delle variabili
 I parametri di una funzione e ogni variabile che
 viene legata (con assegnamento o statement
 come def o class) nel corpo di una funzione
 costituisce il namespace None funzione (local
                            della
                       a=
 scope)               if s.startswith(t):
                        a = s[:4]
 Lo scope di queste variabili é tutto il corpo della
                     else:
 funzione (ma usarle prima tche siano state legate
                        a=
 é un errore)        print a
 Le variabili non locali sono dette globali, il loro
                            SBAGLIATO
 scope é il modulo intero
   Normalmente non ci sono motivi per usarle
Scope delle variabili
 I parametri di una funzione e ogni variabile che
 viene legata (con assegnamento o statement
 come def o class) nel corpo di una funzione
 costituisce il namespace della funzione (local
 scope)               if s.startswith(t):
                        a = s[:4]
 Lo scope di queste variabili é tutto il corpo della
                     else:
 funzione (ma usarle prima tche siano state legate
                        a=
 é un errore)        print a
 Le variabili non locali sono dette globali, il loro
                              GIUSTO
 scope é il modulo intero
   Normalmente non ci sono motivi per usarle
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
Classi
class <nome>(<basi>):
  <corpo>


 <corpo> é di solito una serie di istruzioni def e
 assegnazioni; i nomi definiti o assegnati divengono
 attributi del nuovo oggetto classe <nome> (le
 funzioni divengono "metodi")
 gli attributi di una qualsiasi base sono anche
 attributi della nuova classe, se non
 "overridden" (assegnati o definiti nel corpo)
 Iniziare con singolo _ indica essere privati
Istanziare una Classe
class eg(object):
  cla = []                 #   attrib. di classe
  def __init__(self):      #   inizializzatore
    self.ins = {}          #   attrib. d'istanza
  def meth1(self, x):      #   un metodo
    self.cla.append(x)
  def meth2(self, y, z):   # altro metodo
    self.ins[y] = z

es1 = eg()
es2 = eg()
Classi e Istanze
print es1.cla, es2.cla, es1.ins, es2.ins
[] [] {} {}

es1.meth1(1); es1.meth2(2, 3)
es2.meth1(4); es2.meth2(5, 6)

print es1.cla, es2.cla, es1.ins, es2.ins
[1, 4] [1, 4] {2: 3} {5: 6}

print es1.cla is es2.cla
True
print es1.ins is es2.ins
False
Risoluzione degli Attributi
inst.method(arg1, arg2)

type(inst).method(inst, arg1, arg2)
inst.nome [[che sia poi chiamato o meno!]]
    (i "descrittori" possono alterarlo...)
 prova inst.__dict__['nome']
 prova type(inst).__dict__['nome']
 prova ciascuna delle type(inst).__bases__
 prova type(inst).__getattr__(inst, 'nome')
 se tutto fallisce, raise AttributeError
Sottoclassi
class sub(eg):
  def meth2(self, x, y=1):   # override
    eg.meth2(self, x, y)     # super-call
    # or: super(sub, self).meth2(x, y)


class repeater(list):
  def append(self, x):
    for i in 1, 2:
      list.append(self, x)

class data_overrider(sub):
  cla = repeater()
Proprietà
class blah(object):
  def getter(self):
    return ...
  def setter(self, value): ...
  name = property(getter, setter)
inst = blah()

Ora...:

print inst.name # come inst.getter()
inst.name = 23 # come inst.setter(23)
Overload di Operatori
“metodi speciali”: nomi che iniziano e
finiscono con due _ (pron “dunder”!):
__new__ __init__ __del__    # init/final.
__repr__ __str__ __int__    # conversioni
__lt__ __gt__ __eq__ ...    # paragoni
__add__ __sub__ __mul__ ... # aritmetica
__call__ __hash__ __nonzero_ ...
__getattr__ __setattr__ __delattr__
__getitem__ __setitem__ __delitem__
__len__ __iter__ __contains__
Python chiama i metodi speciali del tipo
quando tu operi sulle istanze del tipo
Overload di Operatori
“metodi speciali”: nomi che iniziano e
finiscono con due _ (pron “dunder”!):
__new__ __init__ __del__    # init/final.
__repr__ __str__ __int__    # conversioni
__lt__ __gt__ __eq__ ...    # paragoni
__add__ __sub__ __mul__ ... # aritmetica
__call__ __hash__ __nonzero_ ...
__getattr__ __setattr__ __delattr__
                                         N.B. : In Python
__getitem__ __setitem__ __delitem__
                                     l’overload dei metodi
__len__ __iter__ __contains__
                                           non esiste e non
Python chiama i metodi speciali del tipo
                                                serve!
quando tu operi sulle istanze del tipo
Convenzioni (PEP8)



     http://www.python.it/doc/articoli/pep-8.html
Decoratori
                                def log(f):
Un decoratore nella sua           def _aux(*args, **kargs):
                                      print 'Called %s' % f.__name__
generalità é una funzione che         return f(*args, **kargs)
                                  return _aux
accetta una funzione come
parametro e ne restituisce      @log
                                def double(n):
una versione modificata            return 2 * n

É come:                         class eg(object):
                                   @log
def f(...):                        def foo(self):
                                      print 'foo'
   ...
                                double(10)
f = deco(f)                     eg().foo()
Metodi static/class
 Python offre due decoratori staticmethod e
 classmethod per metodi “statici” e metodi “di
 classe”
 Convenzionalmente il primo parametro dei
 metodi di classe si chiama cls e non self
 I metodi “statici” non hanno “primo argomento”
 Cercare nell’help maggiori informazioni, se
 interessa. Si vive anche senza.
Funzioni Builtin
 non chiamare metodi speciali direttamente:
 operatori e funzioni built-in lo fanno "bene"
   ad es.: abs(x), NON x.__abs__()
 ci sono molti built-in interessanti, come:
 abs any all chr cmp compile dir enumerate
 eval getattr hasattr hex id intern
 isinstance iter len max min oct open ord pow
 range repr reversed round setattr sorted sum
 unichr xrange zip

 molti altri tipi e funzioni utili e interessanti sono
 nei moduli della libreria standard!
Esempio
# costruiamo mappa parola->[numeri riga]
indx = {}
try:
     f = open(filename)
     for n, line in enumerate(f):
         for word in line.split():
             indx.setdefault(word, []).append(n)
finally:
     f.close()

# mostriamola in indice alfabetico
for word in sorted(indx):
    print "%s:" % word,
    for n in indx[word]: print n,
    print
Altre possibilità
# le 7 parole piú frequenti nel testo:
import heapq
for w in heapq.nlargest(7, indx, key=indx.get):
    print w

# linee che contengono N parole date:
def enwhack(*parole):
    parole = list(parole)
    r = set(indx[parole.pop()])
    for p in parole:
        r &= set(indx[p])
    return sorted(r)
Importare Moduli
import nomemodulo
from un.certo.package import nomemodulo

  poi si usa nomemodulo.blah
  ci sono abbreviazioni (non nec. buone...):
    accorciare i nomi con la clausola as:
    import nometroppolungo as z
       poi si usa z.blah
    from nometroppolungo import blah
    from nometroppolungo import *
Esempio di Import
import math
print math.atan2(1, 3)
# emette 0.321750554397
print atan2(1, 3)
# solleva un'eccezione NameError
from math import atan2

  inietta atan2 nel namespace corrente
  comodo in interattivo, ma spesso illeggibile in
  "veri" programmi: evitare!
  peggio ancora (evitare COME LA PESTE!):
    from math import *
Definire Moduli
ogni sorgente Python wot.py é un modulo
basta fare import wot
  deve vivere nella path d'importazione
  ...che é la lista path nel modulo sys, ogni elemento
  una stringa che nomina un dir (o zipfile, ...)
  contenente moduli Python
  pure importabili: file di bytecode (wot.pyc),
  automaticamente creati dal compilatore Python
  quando importi un .py
  pure importabili: estensioni binarie (wot.pyd),
  scritte in C (or pyrex, SWIG, ...)
Cosa è un Modulo
Un modulo é un semplice oggetto con attributi;
gli attributi sono i nomi “toplevel” connessi da
assegnazioni, o istruzioni assegnanti: class, def,
import, from

Gli attributi di modulo sono detti anche “variabili
globali” del modulo
Possono venir connessi o sconnessi anche “da
fuori” (prassi discutibile, ma comoda in
particolare per i test con la design pattern Mock
[ma Dependency Injection é meglio])
Tempi di Apprendimento
Tempi necessari a un programmatore esperto per
imparare bene...:
  Python vero e proprio (il linguaggio Python): 1-3 giorni
  builtin, metodi speciali, metaprogramming, ecc: 2-4 giorni
  la libreria standard (moduli fondamentali: os, sys, re,
  struct, itertools, collections, array, atexit, math, pickle,
  StringIO, heapq, weakref, threading...): 10-15 giorni
  tutta la libreria std: 30-50 giorni
Estensioni
 GUI (Tkinter, wxPython, PyQt, ...)
 DB SQL (sqlite, gadfly, mysql, postgresql, Oracle, DB2, SAP/DB,
 Firebird, MSSQL...) e wrapper (SQLObject, SQLAlchemy...)
 calcolo (numpy &c, PIL, SciPy, gmpy, mxNumber, MDP, pycripto, ...)
 rete/web (mod_python, WSGI, TurboGears, Django, pylons,
 paste, Quixote, Twisted, ...)
 ambienti e strumenti di sviluppo
 giochi, multimedia, visualizzazione, ...
 integrazione c/C, C++, Java, .NET, Fortran...
Panoramica Libreria
Standard                                                               62

 fondamentali: bisect, copy, collections, functools, heapq, inspect,
 itertools, re, struct, sys, subprocess, threading, Queue...
 testing/debugging: doctest, unittest, pdb, ...
 elaborazione file/testi: fileinput, linecache, cStringIO, readline,
 curses, textwrap, csv, tempfile, codecs, unicodedata, gzip, bz2...
 persistenza/DB: marshal, pickle, shelve, dbm, bsddb, sqlite3 (altri
 DB: 3e-parti)
 ora/data: time, datetime, sched, calendar
 3e-parti utilissimi: pytz, dateutil
 math, cmath, operator, random, decimal
 piú: tonnellate di roba net/web

Pycrashcourse2.0

  • 1.
    Introduzione al Linguaggio Python EnricoFranchi enrico.franchi@gmail.com franchi@cs.unipr.it
  • 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.
  • 4.
    Introduzione Python èconcepito da Guido van Rossum alla fine degli anni ‘80 per Amoeba
  • 5.
    Introduzione Python èconcepito da Guido van Rossum alla fine degli anni ‘80 per Amoeba Pubblico 1991, stabile 1994.
  • 6.
    Introduzione Python èconcepito da Guido van Rossum alla fine degli anni ‘80 per Amoeba Pubblico 1991, stabile 1994. Linguaggio di alto livello ed orientato agli oggetti.
  • 7.
    Introduzione Python èconcepito da Guido van Rossum alla fine degli anni ‘80 per Amoeba Pubblico 1991, stabile 1994. Linguaggio di alto livello ed orientato agli oggetti. Utilizzato per programmazione di sistema e di rete, e calcolo scientifico, applicazioni desktop, integrazione di videogiochi
  • 8.
    Introduzione Python èconcepito da Guido van Rossum alla fine degli anni ‘80 per Amoeba Pubblico 1991, stabile 1994. Linguaggio di alto livello ed orientato agli oggetti. Utilizzato per programmazione di sistema e di rete, e calcolo scientifico, applicazioni desktop, integrazione di videogiochi Si impone in ambito web/enterprise, con soluzioni come Zope/Plone, Django e Nevow (basato su Twisted).
  • 9.
    Piattaforma Python “Veryhigh-level language” (VHLL): sintassi pulita e scarna semantica semplice, regolare, potente object-oriented, ma multi-paradigma produttività tramite: modularità, uniformità, semplicità, pragmatismo Offre una ricca libreria standard di moduli Tanti strumenti ed estensioni di terze-parti Implementazione in C, Java e.NET
  • 10.
    Comunità Python Una fortecomunitá open-source Molti utenti (individui e compagnie) in tutti i campi Python Software Foundation (in Italia, Python Italia) Gruppi d’interesse per argomenti specifici Siti web, newsgroup, mailing list, ... Corsi, laboratori, tutorial, conferenze (Pycon Italia, tre edizioni, più grande conferenza open italiana) Molti (specialmente in inglese...) in linea, su carta, o entrambi
  • 11.
    Indice TIOBE Marzo2009 Sesto linguaggio più diffuso secondo l’indice TIOBE e in Linguaggio Pos. Diff. crescita continua 1 Java -1.7% Utilizzato presso Google 2 C +1% (linguaggio principale), 3 C++ +1% NASA, Industrial Lights and Magic, Frequentis (sicurezza 4 PHP -0.4% aerea), ... 5 VB -3.3% 6 Python +0.4% 7 C# -0.2%
  • 12.
    Python da 3000metri (1) Python é un linguaggio ad oggetti a tipizzazione dinamica e forte Tipizzazione forte: Gli errori di tipo sono sempre generati. Es. Stringhe non diventano interi e viceversa Ogni oggetto ha una classe, questa non cambia Tipizzazione dinamica Gli errori di tipo sono generati a runtime Duck typing
  • 13.
    Python da 3000metri In Python tutto é un oggetto: Un numero, una stringa sono oggetti Gli oggetti sono oggetti (ehm...) Una funzione é un oggetto Una classe é un oggetto Gli oggetti sono cittadini di prima classe, possiamo manipolarli riccamente e comodamente Possiamo fare, in definitiva, tutto
  • 14.
    Versioni Python énotevolmente compatibile fra versioni diverse Gli esempi di queste slides funzioneranno con Python 2.5 o Python 2.6, a meno che altrimenti specificato La maggior parte funzioneranno anche con Python 2.4 e Python 2.3 Python 3.0 é una major release non pensata ancora per essere usata in produzione. É il Python di domani, ma oggi é oggi
  • 15.
    Dettagli implementativi TipicamentePython viene % cat hello.py #!/usr/bin/python compilato a byte-code e questo viene interpretato da print "Hello, world!" una macchina virtuale (come % python hello.py Java) Hello, world! Diversamente da Java la % chmod 755 hello.py % ./hello.py compilazione é trasparente Hello, world! per l’utente % python Python 2.5.1 (...) Possiamo anche usare ... l’interprete interattivo >>> print "Hello, world" Hello, world
  • 16.
    Interprete interattivo L’interpreteinterattivo ufficiale ha >>> import os come prompt >>> >>> print 'foo' foo Scriviamo comandi (statements) >>> os.getcwd() '/Users/enric/uni/pycourse' che vengono byte-compilati ed >>> import sys >>> sys.stdout.write('ciaon') eseguiti ciao >>> def f(a): Se il comando valuta in un ... sys.stdout.write(a) ... return a espressione (es. un expression ... statement), l’espressione viene >>> f('ciaon') ciao stampata 'ciaon'
  • 17.
    Letterali >>> 12 >>> 3.2E10 Numeri interi, float 12 32000000000.0 >>> -27 >>> 'ciao' Base 10, 8, 16 -27 'ciao' >>> 0x6A >>> "ciao" Scientifica, fixpoint 106 'ciao' >>> 0.216 >>> 'c' 0.216 'c' Stringhe >>> [1, 2, "a", 2.32, "ciao"] Apici singoli o doppi [1, 2, 'a', 2.3199999999999998, 'ciao'] >>> '''Testo con Tre apici per testo multilinea ... piu' linee ... di testo''' Liste "Testo connpiu' lineendi testo" >>> """Ancora testo con ... piu' linee di testo""" Fra quadre, separate da "Ancora testo connpiu' linee di testo" virgola
  • 18.
    a = 16 print a a = 7.6 Variabili print a print a * 2 a = 'ciao' i=1 In Python una variabile é print i, type(i) semplicemente un nome, un # => 1 <type 'int'> d = 217.217 etichetta, un modo per print d, type(d) # => 217.217 <type 'float'> riferirsi ad un oggetto s = '''Solito testo su piu' righe''' Le variabili non hanno tipo, print s, type(s) # => Solito testo gli oggetti hanno tipo # su piu' righe <type 'str'> d=2 Una etichetta può riferirsi ad print d, type(d) # => 2 <type 'int'> oggetti di diverso tipo nel i = 32761293836219387269827 print i, type(i) tempo # => 32761293836219387269827 <type 'long'> Assegnamento é statement
  • 19.
    Ancora letterali Tuple: >>> t = 1, 2, 'a' >>> a, b, c = t Sequenza di oggetti non >>> print b 2 modificabile >>> print t (1, 2, 'a') Facile da pack/unpack >>> str(1, 2, 3) Traceback (most recent call last): Precedenza File "<stdin>", line 1, in <module> TypeError: str() takes at most 1 argument (3 given) Dizionario (array associativo): >>> str((1, 2, 3)) '(1, 2, 3)' Coppie chiave/valore >>> d = {'foo' : 1, 'bar': 8} >>> d Inserimento/Accesso O(1) {'foo': 1, 'bar': 8} Chiavi “immutabili”
  • 20.
    Help system >>> help(os.getcwd) La funzione help() da aiuto su getcwd(...) getcwd() -> path una funzione/classe/modulo Return a string representing the current working direc etc. >>> help(sys) Help on built-in module sys: Se chiamata sull’istanza di NAME una classe (quindi anche un sys numero o una stringa) da FILE informazioni sulla classe (built-in) Di fatto va a leggere le MODULE DOCS http://www.python.org/doc/current/lib/module-sys.h ‘docstring’ (vediamo poi...) DESCRIPTION This module provides access to some objects used or Consideriamo anche pydoc interpreter and to functions that interact strongly with
  • 21.
    Help system >>> help(os.getcwd) getcwd(...) getcwd() -> path Return a string representing the current working directory. >>> help(sys) Help on built-in module sys: NAME sys FILE (built-in) MODULE DOCS http://www.python.org/doc/current/lib/module-sys.html DESCRIPTION This module provides access to some objects used or maintained by the interpreter and to functions that interact strongly with the interpreter.
  • 22.
    >>> help(sys.stdout) Help onfile object: class file(object) | file(name[, mode[, buffering]]) -> file object | | Open a file. The mode can be 'r', 'w' or 'a' for reading (default), | writing or appending. The file will be created if it doesn't exist | when opened for writing or appending; it will be truncated when | opened for writing. Add a 'b' to the mode for binary files. ... bash> pydoc os.path.join Help on function join in os.path: os.path.join = join(a, *p) Join two or more pathname components, inserting '/' as needed bash> pydoc -p 8080 pydoc server ready at http://localhost:8080/ % python >>> help() Welcome to Python 2.5! This is the online help utility. help>
  • 23.
    >>> help(sys.stdout) Help onfile object: class file(object) | file(name[, mode[, buffering]]) -> file object | | Open a file. The mode can be 'r', 'w' or 'a' for reading (default), | writing or appending. The file will be created if it doesn't exist | when opened for writing or appending; it will be truncated when | opened for writing. Add a 'b' to the mode for binary files. ... bash> pydoc os.path.join Help on function join in os.path: os.path.join = join(a, *p) Join two or more pathname components, inserting '/' as needed bash> pydoc -p 8080 pydoc server ready at http://localhost:8080/ % python >>> help() Welcome to Python 2.5! This is the online help utility. help>
  • 24.
    Controllo di flusso Condizionale: Su if c’é poco da dire; while if cond: si usa rarissimamente, grazie ai statement else: generatori si preferisce for statement Siccome l’assegnamento é uno if cond: statement statement, non é possibile Iterazione unbounded: metterlo come condizione while cond: statement (fortunatamente) else: statement Disponibili break/continue else di for/while esegue su while cond: statement terminazione naturale (no exc/ cont/break/return)
  • 25.
    Liste >>> a = [1, 2, 'a', 'ciao', 4] La lista é in realtà un array: >>> a[0] 1 accesso O(1) agli elementi >>> a[3] 'ciao' Inserimento e rimozione in >>> a[-1] 4 coda O(1) >>> a[10] Traceback (most recent call last): Controllo sugli indici File "<stdin>", line 1, in <module> IndexError: list index out of range (IndexError) >>> a.append(3) >>> a Indici negativi contano a [1, 2, 'a', 'ciao', 4, 3] >>> l = range(1, 4) partire dal fondo >>> a.extend(l) >>> a Possibilità di slice [1, 2, 'a', 'ciao', 4, 3, 1, 2, 3] >>> a.pop() 3
  • 26.
    Liste (altri metodi) >>> a Presenti anche: [1, 2, 'a', 'ciao', 4, 3, 1, 2] >>> a[1:4] [2, 'a', 'ciao'] insert(i, o): inserisci o in >>> a[1:8:2] posizione i [2, 'ciao', 3, 2] >>> a[::-1] [2, 1, 3, 4, 'ciao', 'a', 2, 1] remove(v): togli la prima >>> a occorrenza di v [1, 2, 'a', 'ciao', 4, 3, 1, 2] count(v): ... >>> for el in a: index(v): ... ... print el, ... sort(): ... 1 2 a ciao 4 3 1 2 Le liste sono mutabili
  • 27.
    Liste (altri metodi) >>> a Presenti anche: [1, 2, 'a', 'ciao', 4, 3, 1, 2] >>> a[1:4] [2, 'a', 'ciao'] insert(i, o): inserisci o in >>> a[1:8:2] posizione i [2, 'ciao', 3, 2] >>> a[::-1] [2, 1, 3, 4, 'ciao', 'a', 2, 1] remove(v): togli la prima >>> a occorrenza di v [1, 2, 'a', 'ciao', 4, 3, 1, 2] count(v): ... >>> for el in a: index(v): ... ... print el, ... sort(): ... 1 2 a ciao 4 3 1 2 Le liste sono mutabili Virgola finale non va a capo
  • 28.
    Tuple >>> t = tuple(a) “Simili” alle liste, tuttavia non >>> t[3] 'ciao' sono mutabili >>> t[-1] 2 Non possiamo aggiungere >>> t[1:] (2, 'a', 'ciao', 4, 3, 1, 2) elementi >>> a, b, c = t[:3] >>> print a, b, c Non possiamo cambiare 12a elementi nella tupla >>> t = 1, 2, 'x' >>> l = list(t) Possiamo agire su questi, se >>> t.append(5) Traceback (most recent call last): non sono immutabili File "<stdin>", line 1, in <module> AttributeError: 'tuple' object has no attribute 'append' Per il resto funziona tutto >>> l.append(5) >>> l come previsto [1, 2, 'x', 5]
  • 29.
    Stringhe >>> s = 'Hello, world! ' Anche le stringhe sono >>> s.strip() immutabili 'Hello, world!' >>> s.replace('o', '0') 'Hell0, w0rld! ' Supportano slicing, indexing, >>> s.find('o') etc. 4 >>> s.rfind('o') 8 isdigit(), ... >>> s.upper() 'HELLO, WORLD! ' strip()... >>> s.center(60) ' Hello, world! ' find/rfind/index/rindex(ch) >>> s.startswith('He') True >>> s.split(‘, ‘) startswith/endswith(s) ['Hello', ' world! '] upper/lower/capitalize() ... andate a guardarli tutti!
  • 30.
    Operazioni se sequenze >>> s = 'ciao' Stringhe, tuple e liste sono >>> m = 'mondo' >>> min(s) # <= 'a' sequenze >>> max(m) # <= 'o' >>> l = [1, 2, 3] Tutte le sequenze >>> sum(l) # <= 6 >>> s + m # <= 'ciaomondo' supportano alcune >>> s + l Traceback (most recent call last): operazioni File "<stdin>", line 1, in <module> TypeError: cannot concatenate 'str' and 'list' objects min/max/sum >>> list(s) + l ['c', 'i', 'a', 'o', 1, 2, 3] + : concatenazione >>> '=' * 10 '==========' >>> [1, ] * 10 S * n/ n * S: ripetizione [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] >>> ‘a’ in s el in S: appartenenza True >>> ‘pippo’ in l False
  • 31.
    Attenzione! Sommare tantioggetti immutabili funziona, ma crea ogni volta un nuovo elemento: Sommare 10 stringhe crea 10 nuove stringhe. E se sono 10000? Potrebbe essere l’ultimo pezzo di codice prima del licenziamento. Si usa join nella forma sep.join(elements) >>> l = ['usr', 'local', 'lib'] >>> '/'.join(l) 'usr/local/lib' >>> ' => '.join(l) 'usr => local => lib' Per concatenare pezzi di path, usare os.path.join e i metodi presenti in os.path
  • 32.
    Statement For for ch in 'ciao mondo': For é il modo più comune di print ch, iterare in Python print for n in range(10): Funziona con un generico print n iterabile for n in xrange(10): print n Esprime il concetto di “per for n in range(1, 20): ogni elemento in questa print n for n in xrange(1, 10000000000): sequenza” fai qualcosa print n Invece che usare una sequenza (finita), possiamo usare un generatore (potenzialmente infinito)
  • 33.
    Statement For for ch in 'ciao mondo': For é il modo più comune di print ch, iterare in Python print for n in range(10): Funziona con un generico print n iterabile for n in xrange(10): print n Esprime il concetto di “per for n in range(1, 20): ogni elemento in questa print n for n in xrange(1, 10000000000): sequenza” fai qualcosa print n Invece che usare una sequenza (finita), possiamo Attenzione! range ritorna usare un generatore una lista xrange un iteratore. (potenzialmente infinito) Restituiscono intervalli [a, b)
  • 34.
    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")
  • 35.
    Dizionari Array associativi/dizionari: >>> d = {'foo' : (1, 2, 3), ... 'bar' : (2, 3, 4)} coppie chiave-valore >>> d['foo'] (1, 2, 3) Operazioni tipicamente O(1) >>> d['baz'] Traceback (most recent call last): File "<stdin>", line 1, in <module> Implementazione KeyError: 'baz' esageratamente efficiente >>> d['bar'] = 'foo' >>> d {'foo': (1, 2, 3), 'bar': 'foo'} La chiave deve essere hashabile e immutabile (ecco perché le stringhe...)
  • 36.
    Dizionari (altri metodi) D.pop(k[, d]): rimuove k (se presente) restituendo il valore corrispondente. Altrimenti restituisce d se specificato o da AttributeError D.popitem(): ritorna una coppia k-v (qualsiasi) D.get(k[,d]): ritorna il valore di k o d se k non é presente. Se non specificato d vale None. D.setdefault(k[,d]): D.get(k,d), setta D[k]=d se k non é in D D.update(E, **F): aggiunge le coppie k-v di E (ed F) aD
  • 37.
    Dizionari (Iterazione) % python dicts_example.py d = {'foo' : (1, 2, 3), foo 'bar' : (2, 3, 4)} bar foo for k in d: bar print k (1, 2, 3) (2, 3, 4) for k in d.iterkeys(): foo (1, 2, 3) print k bar (2, 3, 4) foo (1, 2, 3) for v in d.itervalues(): bar (2, 3, 4) print v for k, v in d.iteritems(): # iteritems restituisce un iteratore alle coppie print k, v for k, v in d.items(): # items restituisce una *lista* print k, v
  • 38.
    Dimensione di oggetti iterabili Il builtin (funzione) len dice il numero di elementi di ogni oggetto iterabile Se dispongono di un metodo __len__ chiama quello. Per esempio per liste, tuple, dizionari, stringhe, insiemi (set) Funziona anche su un generatore, ma in questo caso potrebbe doverlo scorrere
  • 39.
    Format Le stringhe hannoun operatore % che permette di fare “format string” simili alla printf del C -- doc per maggiori informazioni -- stringa % tupla: sostituzione posizionale: >>> '%s %d %s' % ('ciao', 9, ('h', 'p')) "ciao 9 ('h', 'p')" stringa % dizionario: sostituzione per nome: >>> 'Mi chiamo %(surname)s, %(fname)s %(surname)s.' % {'surname': 'Bond', 'fname' : 'James'} 'Mi chiamo Bond, James Bond.' Estremamente comodo. Usando %s si passa per str(obj), usando %r per repr(obj)
  • 40.
    I/O elementare duefunzioni built-in per l'input elementare input(prompt): immette qualsiasi espressione -- 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 print >> writable, <0+ espressioni separate da virgole>
  • 41.
    SPERIMENTATE! Non é possibileimparare un linguaggio con una corso frontale. I linguaggi si imparano programmando, provando codice etc. In Python trovate tutto quello che vi serve o direttamente nella libreria standard o in qualche modulo esterno: dateci qualche occhiata Leggete la documentazione. Studiate il codice altrui. É estremamente leggibile e didattico Diffidate dal codice che ha un brutto aspetto
  • 42.
    “semplice wget” (GvR) importsys, urllib, os def hook(*a): print '%s: %s' % (fn, a) for url in sys.argv[1:]: fn = os.path.basename(url) print url, "->", fn urllib.urlretrieve(url, fn, hook)
  • 43.
    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”)
  • 44.
    LBYL vs. EAFP LBYL:Look before you leap EAFP: Easier to ask forgiveness than permission try: emp = employees[user_name] except KeyError: Normalmente EAFP é la report_error(...) strategia migliore in Python if user_name in emp: emp = employees[user_name] Eccezioni relativamente poco else: costose report_error(...) Atomicità, ...
  • 45.
    Vari tipi ditry try: # codice che potrebbe lanciare eccezione except IndexError, exc: # un tipo di errore # opzionalmente si mette ‘, nome’ per avere # l’oggetto eccezione da gestire except AnotherException: # gestione di un altro errore except: # gestione di ogni eccezione # tipicamente *NON* e' una buona pratica # a meno di non rilanciare raise # raise vuoto rilancia l'eccezione corrente finally: # questo codice e' eseguito *sempre* # codice di pulizia sia con errore che senza
  • 46.
    With statement from __future__ import with_statement with file('foo.txt') as f: for line in f: print line.strip()
  • 47.
    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)
  • 48.
    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
  • 49.
    Scope delle variabili I parametri di una funzione e ogni variabile che viene legata (con assegnamento o statement come def o class) nel corpo di una funzione costituisce il namespace della funzione (local scope) Lo scope di queste variabili é tutto il corpo della funzione (ma usarle prima che siano state legate é un errore) Le variabili non locali sono dette globali, il loro scope é il modulo intero Normalmente non ci sono motivi per usarle
  • 50.
    Scope delle variabili I parametri di una funzione e ogni variabile che viene legata (con assegnamento o statement come def o class) nel corpo di una funzione costituisce il namespace None funzione (local della a= scope) if s.startswith(t): a = s[:4] Lo scope di queste variabili é tutto il corpo della else: funzione (ma usarle prima tche siano state legate a= é un errore) print a Le variabili non locali sono dette globali, il loro SBAGLIATO scope é il modulo intero Normalmente non ci sono motivi per usarle
  • 51.
    Scope delle variabili I parametri di una funzione e ogni variabile che viene legata (con assegnamento o statement come def o class) nel corpo di una funzione costituisce il namespace della funzione (local scope) if s.startswith(t): a = s[:4] Lo scope di queste variabili é tutto il corpo della else: funzione (ma usarle prima tche siano state legate a= é un errore) print a Le variabili non locali sono dette globali, il loro GIUSTO scope é il modulo intero Normalmente non ci sono motivi per usarle
  • 52.
    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)
  • 53.
    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
  • 54.
    Classi class <nome>(<basi>): <corpo> <corpo> é di solito una serie di istruzioni def e assegnazioni; i nomi definiti o assegnati divengono attributi del nuovo oggetto classe <nome> (le funzioni divengono "metodi") gli attributi di una qualsiasi base sono anche attributi della nuova classe, se non "overridden" (assegnati o definiti nel corpo) Iniziare con singolo _ indica essere privati
  • 55.
    Istanziare una Classe classeg(object): cla = [] # attrib. di classe def __init__(self): # inizializzatore self.ins = {} # attrib. d'istanza def meth1(self, x): # un metodo self.cla.append(x) def meth2(self, y, z): # altro metodo self.ins[y] = z es1 = eg() es2 = eg()
  • 56.
    Classi e Istanze printes1.cla, es2.cla, es1.ins, es2.ins [] [] {} {} es1.meth1(1); es1.meth2(2, 3) es2.meth1(4); es2.meth2(5, 6) print es1.cla, es2.cla, es1.ins, es2.ins [1, 4] [1, 4] {2: 3} {5: 6} print es1.cla is es2.cla True print es1.ins is es2.ins False
  • 57.
    Risoluzione degli Attributi inst.method(arg1,arg2) type(inst).method(inst, arg1, arg2) inst.nome [[che sia poi chiamato o meno!]] (i "descrittori" possono alterarlo...) prova inst.__dict__['nome'] prova type(inst).__dict__['nome'] prova ciascuna delle type(inst).__bases__ prova type(inst).__getattr__(inst, 'nome') se tutto fallisce, raise AttributeError
  • 58.
    Sottoclassi class sub(eg): def meth2(self, x, y=1): # override eg.meth2(self, x, y) # super-call # or: super(sub, self).meth2(x, y) class repeater(list): def append(self, x): for i in 1, 2: list.append(self, x) class data_overrider(sub): cla = repeater()
  • 59.
    Proprietà class blah(object): def getter(self): return ... def setter(self, value): ... name = property(getter, setter) inst = blah() Ora...: print inst.name # come inst.getter() inst.name = 23 # come inst.setter(23)
  • 60.
    Overload di Operatori “metodispeciali”: nomi che iniziano e finiscono con due _ (pron “dunder”!): __new__ __init__ __del__ # init/final. __repr__ __str__ __int__ # conversioni __lt__ __gt__ __eq__ ... # paragoni __add__ __sub__ __mul__ ... # aritmetica __call__ __hash__ __nonzero_ ... __getattr__ __setattr__ __delattr__ __getitem__ __setitem__ __delitem__ __len__ __iter__ __contains__ Python chiama i metodi speciali del tipo quando tu operi sulle istanze del tipo
  • 61.
    Overload di Operatori “metodispeciali”: nomi che iniziano e finiscono con due _ (pron “dunder”!): __new__ __init__ __del__ # init/final. __repr__ __str__ __int__ # conversioni __lt__ __gt__ __eq__ ... # paragoni __add__ __sub__ __mul__ ... # aritmetica __call__ __hash__ __nonzero_ ... __getattr__ __setattr__ __delattr__ N.B. : In Python __getitem__ __setitem__ __delitem__ l’overload dei metodi __len__ __iter__ __contains__ non esiste e non Python chiama i metodi speciali del tipo serve! quando tu operi sulle istanze del tipo
  • 62.
    Convenzioni (PEP8) http://www.python.it/doc/articoli/pep-8.html
  • 63.
    Decoratori def log(f): Un decoratore nella sua def _aux(*args, **kargs): print 'Called %s' % f.__name__ generalità é una funzione che return f(*args, **kargs) return _aux accetta una funzione come parametro e ne restituisce @log def double(n): una versione modificata return 2 * n É come: class eg(object): @log def f(...): def foo(self): print 'foo' ... double(10) f = deco(f) eg().foo()
  • 64.
    Metodi static/class Pythonoffre due decoratori staticmethod e classmethod per metodi “statici” e metodi “di classe” Convenzionalmente il primo parametro dei metodi di classe si chiama cls e non self I metodi “statici” non hanno “primo argomento” Cercare nell’help maggiori informazioni, se interessa. Si vive anche senza.
  • 65.
    Funzioni Builtin nonchiamare metodi speciali direttamente: operatori e funzioni built-in lo fanno "bene" ad es.: abs(x), NON x.__abs__() ci sono molti built-in interessanti, come: abs any all chr cmp compile dir enumerate eval getattr hasattr hex id intern isinstance iter len max min oct open ord pow range repr reversed round setattr sorted sum unichr xrange zip molti altri tipi e funzioni utili e interessanti sono nei moduli della libreria standard!
  • 66.
    Esempio # costruiamo mappaparola->[numeri riga] indx = {} try: f = open(filename) for n, line in enumerate(f): for word in line.split(): indx.setdefault(word, []).append(n) finally: f.close() # mostriamola in indice alfabetico for word in sorted(indx): print "%s:" % word, for n in indx[word]: print n, print
  • 67.
    Altre possibilità # le7 parole piú frequenti nel testo: import heapq for w in heapq.nlargest(7, indx, key=indx.get): print w # linee che contengono N parole date: def enwhack(*parole): parole = list(parole) r = set(indx[parole.pop()]) for p in parole: r &= set(indx[p]) return sorted(r)
  • 68.
    Importare Moduli import nomemodulo fromun.certo.package import nomemodulo poi si usa nomemodulo.blah ci sono abbreviazioni (non nec. buone...): accorciare i nomi con la clausola as: import nometroppolungo as z poi si usa z.blah from nometroppolungo import blah from nometroppolungo import *
  • 69.
    Esempio di Import importmath print math.atan2(1, 3) # emette 0.321750554397 print atan2(1, 3) # solleva un'eccezione NameError from math import atan2 inietta atan2 nel namespace corrente comodo in interattivo, ma spesso illeggibile in "veri" programmi: evitare! peggio ancora (evitare COME LA PESTE!): from math import *
  • 70.
    Definire Moduli ogni sorgentePython wot.py é un modulo basta fare import wot deve vivere nella path d'importazione ...che é la lista path nel modulo sys, ogni elemento una stringa che nomina un dir (o zipfile, ...) contenente moduli Python pure importabili: file di bytecode (wot.pyc), automaticamente creati dal compilatore Python quando importi un .py pure importabili: estensioni binarie (wot.pyd), scritte in C (or pyrex, SWIG, ...)
  • 71.
    Cosa è unModulo Un modulo é un semplice oggetto con attributi; gli attributi sono i nomi “toplevel” connessi da assegnazioni, o istruzioni assegnanti: class, def, import, from Gli attributi di modulo sono detti anche “variabili globali” del modulo Possono venir connessi o sconnessi anche “da fuori” (prassi discutibile, ma comoda in particolare per i test con la design pattern Mock [ma Dependency Injection é meglio])
  • 72.
    Tempi di Apprendimento Tempinecessari a un programmatore esperto per imparare bene...: Python vero e proprio (il linguaggio Python): 1-3 giorni builtin, metodi speciali, metaprogramming, ecc: 2-4 giorni la libreria standard (moduli fondamentali: os, sys, re, struct, itertools, collections, array, atexit, math, pickle, StringIO, heapq, weakref, threading...): 10-15 giorni tutta la libreria std: 30-50 giorni
  • 73.
    Estensioni GUI (Tkinter,wxPython, PyQt, ...) DB SQL (sqlite, gadfly, mysql, postgresql, Oracle, DB2, SAP/DB, Firebird, MSSQL...) e wrapper (SQLObject, SQLAlchemy...) calcolo (numpy &c, PIL, SciPy, gmpy, mxNumber, MDP, pycripto, ...) rete/web (mod_python, WSGI, TurboGears, Django, pylons, paste, Quixote, Twisted, ...) ambienti e strumenti di sviluppo giochi, multimedia, visualizzazione, ... integrazione c/C, C++, Java, .NET, Fortran...
  • 74.
    Panoramica Libreria Standard 62 fondamentali: bisect, copy, collections, functools, heapq, inspect, itertools, re, struct, sys, subprocess, threading, Queue... testing/debugging: doctest, unittest, pdb, ... elaborazione file/testi: fileinput, linecache, cStringIO, readline, curses, textwrap, csv, tempfile, codecs, unicodedata, gzip, bz2... persistenza/DB: marshal, pickle, shelve, dbm, bsddb, sqlite3 (altri DB: 3e-parti) ora/data: time, datetime, sched, calendar 3e-parti utilissimi: pytz, dateutil math, cmath, operator, random, decimal piú: tonnellate di roba net/web