2. Parlando del
futuro... 2
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
3. Introduzione 3
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 Twisted.
4. Piattaforma Python 4
“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
Implementazioni in C, Java, .NET e Python stesso
5. Comunità Python 5
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,
quattro edizioni, fra le maggiori conferenze open italiana)
Molti (specialmente in inglese...) in linea, su carta, o
entrambi
6. MESSAGGIO PROMOZIONALE
6
7-8-9 MAGGIO 2010
FIRENZE
SCONTO STUDENTI, SESSIONI RECRUITING, ETC ETC
http://www.pycon.it
~400 partecipanti
7. Tempi di Apprendimento 7
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
8. Python da 3000 metri (1) 8
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
9. Python da 3000 metri (II) 9
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 (introspezione, etc.)
Possiamo fare, in definitiva, tutto
10. Versioni 10
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.x rappresenta il futuro, ma per ora si
utilizza ancora 2.x, la transizione sarà morbida e
lunga anni
12. Dettagli implementativi 12
% cat hello.py
Tipicamente Python viene #!/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
13. Interprete interattivo 13
L’interprete interattivo ufficiale ha
>>> import os
come prompt >>> >>> print “foo”
foo
Scriviamo comandi (statements) >>> os.getcwd()
“/Users/enric/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”
14. Letterali 14
>>> 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
15. a = 16
print a
a = 7.6
Variabili
print a
print a * 2
a = 'ciao'
15
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
16. Variabili/Oggetti 16
[java] Pet fido = new Dog();
tipo a compile-time tipo a runtime
oggetto (dell’oggetto)
(della variabile)
variabile
[python] fido = Dog()
17. Controllo di flusso 17
Condizionale: Su if c’è poco da dire; while si
if cond: 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: Disponibili break/continue
statement
else di for/while esegue su
while cond:
statement
terminazione naturale (no exc/
cont/break/return)
18. Liste (I) 18
>>> a = [1, 2, 'a', 'ciao', 4]
La lista è in realtà un vector: >>> 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
19. Liste (II) 19
>>> a
Presenti anche: [1, 2, 'a', 'ciao', 4, 3, 1, 2]
>>> a[1:4]
insert(i, o): inserisci o in [2,
>>>
'a', 'ciao']
a[1:8:2]
posizione i [2, 'ciao', 3, 2]
>>> a[::-1]
remove(v): togli la prima [2, 1, 3, 4, 'ciao', 'a', 2, 1]
>>> a
occorrenza di v [1, 2, 'a', 'ciao', 4, 3, 1, 2]
count(v): ...
index(v): ...
sort(): ...
...
Le liste sono mutabili
20. Tuple 20
>>> 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 1 2 a
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 attribut
Per il resto funziona tutto >>> l.append(5)
>>> l
come previsto [1, 2, 'x', 5]
22. Operazioni su sequenze 22
>>> s = 'ciao'
Stringhe, tuple e liste sono >>> m = 'mondo'
>>> min(s) # <= 'a'
sequenze >>> max(m) # <= 'o'
>>> l = [1, 2, 3]
Tutte le sequenze supportano >>> sum(l) # <= 6
>>> s + m # <= 'ciaomondo'
alcune operazioni >>> s + l
Traceback (most recent call last):
min/max/sum File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'list'
>>> list(s) + l
+ : concatenazione ['c', 'i', 'a', 'o', 1, 2, 3]
>>> '=' * 10
S * n/ n * S: ripetizione '=========='
>>> [1, ] * 10
el in S: appartenenza [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>> 'a' in s
True
>>> 'pippo' in l
False
23. Attenzione! 23
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)
>>> lst = ['usr', 'local', 'lib']
>>> '/'.join(lst)
'usr/local/lib'
>>> ' => '.join(lst)
'usr => local => lib'
Per concatenare pezzi di path, usare os.path.join e i metodi
presenti in os.path
24. Statement For 24
For è il modo più comune di for ch in 'ciao mondo':
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)
25. Statement For 24
For è il modo più comune di for ch in 'ciao mondo':
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)
26. 99 Bottles of Beer 25
def pluralize(s, quantity):
if quantity == 1:
return s
else:
return s + "s"
for how_many in range(99, 0, -1):
print how_many, pluralize("bottle", how_many), "on the wall!"
print "Take one down and pass it around,", how_many-1,
print pluralize("bottle", how_many-1),
print "of beer on the wall."
27. More on for... 26
import os
import shutil
for fname in os.listdir(os.getcwd()):
if fname.endswith(('pyc', 'pyo')):
os.remove(fname)
elif fname.endswith('py'):
shutil.copy(fname, fname + '.bak')
28. Dizionari 27
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...)
Essenzialmente è una hash-
table
29. Dizionari (altri metodi) 28
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) a D
30. Format (printf-on-steroids) 29
Le stringhe hanno un operatore % che permette di fare “format
string” simili alla printf del C. -- man printf --
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)
31. Esempio dizionari 30
import sys
filename = sys.argv[1]
indx = {}
try:
f = open(filename)
for n, line in enumerate(f):
for word in line.split():
indx.setdefault(word, []).append(n)
finally:
f.close()
for word in sorted(indx): # indice alfabetico
print "%s:" % word,
for n in indx[word]: print n,
print
32. I/O elementare 31
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
un’istruzione per l'output elementare
print <0+ espressioni separate da virgole>
separa i risultati con uno spazio
n alla fine (ma non se terminate con virgola)
print di suo non fa formattazioni speciali
print >> writable, <0+ espressioni separate da virgole>
33. Eccezioni 32
Errori (e “anomalie” che non sono errori)
“sollevano eccezioni”
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”)
34. LBYL vs. EAFP 33
LBYL: Look before you leap # LBYL -- cattivo
if user_name in employees:
EAFP: Easier to ask forgiveness emp =
than permission employees[user_name]
else:
Normalmente EAFP è la report_error(...)
strategia migliore in Python
Eccezioni relativamente poco
costose #EAFP -- buono
try:
Atomicità, ... emp =
employees[user_name]
except KeyError:
report_error(...)
35. Vari tipi di try 34
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
36. List Comprehensions 35
“Matematichese”: { f (x) | ∀x ∈S tali che p(x)}
Python:
[f(x) for x in seq if p(x)]
Lista di tutti gli f(x) per tutti gli x contenuti in
seq, a patto che p(x) sia vero.
Simile a:
tmp = []
for x in seq:
if p(x):
tmp.append(f(x))
37. Generator Expressions 36
Si può fare restituendo un generatore, ovvero un
iterabile “lazy”
Il calcolo avviene solo mano a mano che i nuovi
elementi sono “richiesti”
Sintassi: (f(x) for x in seq if p(x))
Comodo con altre funzioni
sum(f(x) for x in seq if p(x))
set(f(x) for x in seq if p(x))
dict((x, i) for (i, x) in enumerate(sorted(seq)))
38. Funzioni 37
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)
39. Esempio:
somma di quadrati 38
def sumsq(a, b):
return a*a+b*b
print sumsq(23, 45) # => 2554
O, piú generale:
def sumsq(*a):
return sum(x*x for x in a)
print sumsq(23, 45) # => 2554
print sumsq(23, 45, 44, 2) # => 4494
Minore livello di astrazione, + lento ma OK:
def sumsq(*a):
total = 0
for x in a:
total += x*x
return total
40. “semplice wget” (GvR) 39
import sys
import urllib
import 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)
41. Classi 40
class Stack(object):
Classe Stack, eredita da def __init__(self, seq):
object (come tutto) self._els = list(seq)
Costruttore __init__, ha per def pop(self):
return self._els.pop()
parametro qualcosa di
convertibile in lista def push(self, el):
return self._els.append(el)
Metodo pop delega al pop def __len__(self):
della lista return len(self._els)
>>> import stack
Push “delega” all’append della >>> s = stack.Stack([1, 4, 7, 8])
lista >>> s.pop()
8
__len__, numero di elementi >>> s.push(3)
>>> s.pop()
3
42. Con documentazione 41
class Stack(object):
'Implements a stack'
def __init__(self, seq):
'Create a new stack with elements from seq'
self._elements = list(seq)
def pop(self):
'Remove and return the head of the stack'
return self._elements.pop()
def push(self, element):
'Add el to the head of the stack'
return self._elements.append(element)
def __len__(self):
return len(self._elements)
53. class MusicRecord(object):
def __init__(self, title, tracks):
self.title = title
if not tracks:
raise ValueError("Empty track list.") 52
self.tracks = tuple(tracks)
self._artists = set(track.artist for track in self.tracks)
self._duration = sum((track.duration for track
in self.tracks), Duration())
@property
def is_compilation(self):
return len(self._titles) > 1
@property
def duration(self):
return self._duration
@property
def artist(self):
if self.is_compilation:
return 'AA. VV.'
else:
return self.tracks[0].title
54. Adulti e vaccinati... 53
Possiamo impedire l’accesso usando le properties
Possiamo usare meta-programmazione1 per
scrivere meno codice
Es... namedtuple, definita nella libreria standard
Track = collections.namedtuple(
'Track', ['title', 'artist', 'duration'])
1. meta-programmazione: scrittura di programmi che scrivono
o modificano altri programmi (o se stessi) come i loro dati
55. Decoratori (I) 54
def log(f):
Un decoratore nella sua def _aux(*args, **kargs):
generalità è una funzione che print 'Called %s' % f.__name__
return f(*args, **kargs)
accetta una funzione come return _aux
parametro e ne restituisce @log
def double(n):
una versione modificata return 2 * n
@deco class eg(object):
def f(...): ... @log
def foo(self):
equivale a: print 'foo'
def f(...): ... double(10) # => Called double
eg().foo()
f = deco(f) # => Called foo
# => foo
56. Decoratori (II) 55
Esempio da Django (web framework)
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
Un decoratore può anche avere argomenti
I decoratori si possono combinare
class Bank(object):
# ...
@with_logger(default_logger)
@atomic
def transfer(self, from_, to, amount):
self.accounts[from_] -= amount # raises NegativeAccountError
self.accounts[to] += amount
57. Dinamismo e
introspezione 56
Quando un attributo di un oggetto non viene
trovato, se è definito il metodo __getattr__
Se si, viene chiamato con come parametro il
nome dell’attributo cercato
Esempio: delega [prossima slide]
Funzione getattr: prende un attributo per nome
f.foo getattr(f, ‘foo’)
60. Importare Moduli 59
import nomemodulo
from un.certo.package import nomemodulo
poi si usa nomemodulo.foo
ci sono abbreviazioni (non necessariamente buone...):
accorciare i nomi con la clausola as:
import itertools as it
poi si usa it.izip
from itertools import izip
from itertools import *
61. Esempio di Import 60
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 *
62. Definire Moduli 61
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, ...)
63. Persistenza 62
cPickle: tutti gli oggetti sono facilmente e
automaticamente serializzabili su disco
Modulo shelve
Si usa come un dizionario, offre gratis persistenza
su disco per strutture chiave-valore
Esigenze maggiori? SQLite integrato con Python
Non basta? PostgreSQL
Scriptabile in Python
Accessibile da Python (+ ORM, SQLAlchemy)
66. Calcolo scientifico 65
PIL
Manipolazione immagini
Numpy+Matplotlib
Calcolo numerico, simile a Matlab/Octave
Scipy
Ulteriori librerie
http://www.scipy.org/
67. Web 66
cgi (sconsigliato)/fastcgi
WSGI: modulo di medio livello per interfacciarsi
con i server
Django: framework completo, molto usato
Nevow: framework completo basato su Twisted
Zope2/3: “mega framework”
Google App Engine (+web.py ev. Django)
web.py: modulo minimalista, facile comprensione
68. Q&A
Help System Ancora su Classi e Istanze
67
Generatori &
Attributi di Classe
Generatori Infiniti
Scope
With Statement
Duck Typing
69. Help system 68
>>> 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
70. Help system 68
>>> 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.
71. >>> 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 69
| 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>
To Q&A
72. >>> 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 69
| 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>
To Q&A
73. Attributi
di istanza e di classe 70
class A(object):
Fino ad ora abbiamo visto cattr = []
def __init__(self):
come aggiungere attributi alle self.iattr = []
istanze delle classi (banale) def add(self, obj):
self.cattr.append(obj)
Sappiamo che le funzioni, in self.iattr.append(obj)
un certo senso sono attributi a1 = A()
degli “oggetti classe” a2 = A()
a1.add('x')
print a1.cattr, a1.iattr
Se definiamo un attributo nel # => ['x'], ['x']
corpo di una classe, è un print a2.cattr, a2.iattr
# => ['x'], []
attributo di classe a2.add('y')
print a1.cattr, a1.iattr
# => ['x', 'y'], ['x']
print a2.cattr, a2.iattr
# => ['x', 'y'], ['y']
74. Metodi di classe 71
I metodi di classe si class A(object):
@classmethod
definiscono con il decoratore def say(cls, m):
classmethod
print cls.__name__, m
Hanno come primo
A.say('hello') # => A hello
argomento l’oggetto classe a = A()
Accedono ad attributi di a.say('hello') # => A hello
classe (ma non d’istanza)
Convenzionalmente,
chiamiamo il primo
parametro cls e non self
To Q&A
75. With statement 72
with file('foo.txt') as f:
for line in f:
print line.strip()
with gestisce un “contesto”, quando si esce dal
blocco with (con eccezione o meno), viene
gestita la chiusura di file
Simile agli idiomi RAII (resource allocation is
initialization) di C++, ma molto più facile da
gestire
76. Vecchio esempio... 73
import sys
filename = sys.argv[1]
indx = {}
with open(filename) as f:
for n, line in enumerate(f):
for word in line.split():
indx.setdefault(word, []).append(n)
# mostriamola in indice alfabetico
for word in sorted(indx):
print "%s:" % word,
for n in indx[word]: print n,
print To Q&A
77. Generatori 74
def couples(l):
funzioni con yield invece di i = 0
return length = len(l)
while i < length-1:
ogni chiamata costruisce e yield l[i], l[i+1]
torna un iteratore (oggetto i += 1
con metodo next, adatto a
lst = [1, 2, 3, 4, 5, 6]
essere iterato in un ciclo for) for pairs in couples(lst):
la fine della funzione solleva print pairs
StopIteration (1, 2)
(2, 3)
(3, 4)
(4, 5)
(5, 6)
78. Generatori Infiniti 75
def fibonacci():
i = j = 1
while True:
r, i, j = i, j, i + j
yield r
for rabbits in fibonacci():
if rabbits > 100:
break
else:
print rabbits,
1 1 2 3 5 8 13 21 34 55 89
To Q&A
79. Classi 76
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
80. Istanziare una Classe 77
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()
82. Risoluzione degli Attributi 79
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 To Q&A
83. Scope delle variabili 80
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 To Q&A
84. Scope delle variabili 80
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 To Q&A
85. Scope delle variabili 80
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 To Q&A
86. Pensiamo a Java/C++... 81
Nei linguaggi con un type-system derivato da C+
+ chiediamo che i parametri di una certa
funzione abbiano un dato tipo (o siano di un
sottotipo)
Questo è poco flessibile: programmare per un
interfaccia
Interfacce di Java (vero polimorfismo din.)
Templates di C++ (polimorfismo statico)
Sono soluzioni con problemi
87. Libri, ricerca per titolo 82
Chiamare su una lista che class Book(object):
def __init__(self, title, author):
contiene un “non libro” self.title = title
self.author = author
lancia eccezione
def find_by_title(seq, title):
Eppure non gestiamo for item in seq:
if type(item) == Book: # horrible
nemmeno sottoclassi if item.title == title:
return item
Peggior codice possibile, else:
raise TypeError
inoltre stiamo risolvendo
def find_by_author(seq, author):
un non-problema for item in seq:
if type(item) == Book: # horrible
if item.author == author:
return item
else:
raise TypeError
88. Libri, ricerca per titolo 82
Chiamare su una lista che
contiene un “non libro”
lancia eccezione
Eppure non gestiamo
nemmeno sottoclassi
Peggior codice possibile,
inoltre stiamo risolvendo
un non-problema
89. Libri, ricerca per titolo 83
Ora gestiamo sottoclassi class Book(object):
def __init__(self, title, author):
self.title = title
Eppure noi non usiamo mai self.author = author
il fatto che la cosa sia un def find_by_title(seq, title):
libro for item in seq:
if isinstance(item, Book): # bad
if item.title == title:
Solo che ha un titolo return item
else:
Solo che ha un autore raise TypeError
Cosa succede se abbiamo def find_by_author(seq, author):
for item in seq:
una classe Song? if isinstance(item, Book): # bad
if item.author == author:
return item
else:
raise TypeError
90. Libri, ricerca per titolo 83
Ora gestiamo sottoclassi
Eppure noi non usiamo mai
il fatto che la cosa sia un def find_by_title(seq, title):
libro for item in seq:
if isinstance(item, Book): # bad
if item.title == title:
Solo che ha un titolo return item
else:
Solo che ha un autore raise TypeError
Cosa succede se abbiamo def find_by_author(seq, author):
for item in seq:
una classe Song? if isinstance(item, Book): # bad
if item.author == author:
return item
else:
raise TypeError
91. Libri, ricerca per titolo 83
Ora gestiamo sottoclassi class Song(object):
def __init__(self, title, author):
self.title = title
Eppure noi non usiamo mai self.author = author
il fatto che la cosa sia un def find_by_title(seq, title):
libro for item in seq:
if isinstance(item, Book): # bad
if item.title == title:
Solo che ha un titolo return item
else:
Solo che ha un autore raise TypeError
Cosa succede se abbiamo def find_by_author(seq, author):
for item in seq:
una classe Song? if isinstance(item, Book): # bad
if item.author == author:
return item
else:
raise TypeError
92. Libri e canzoni 84
La cosa più semplice è la migliore
class Book(object): I programmatori tendono a non
def __init__(self, t, a):
self.title = t
scrivere codice a caso
self.author = a
Abbiamo sempre eccezioni
def find_by_title(seq, title):
for item in seq:
lanciate
if item.title == title:
return item I test servono apposta per
def find_by_author(seq, author): prendere ‘sta roba
for item in seq:
if item.author == author:
return item
93. E se avessimo film? 85
I film hanno sempre un titolo, ma non hanno un
autore, bensì un regista
find_by_title dovrebbe funzionare,
find_by_author, no
Interfaccia per Book e Song. E per Movie?
Design Pattern o duplicazione di codice
Ruota quadrata strade per ruote quadrate
Con il duck typing non dobbiamo cambiare nulla
94. def find_by(seq, **kwargs):
for obj in seq: To Q&A
for key, val in kwargs.iteritems():
try:
if getattr(obj, key) != val:
break
except KeyError:
break
else:
return obj
raise NotFound
print find_by(books, title='Python in a Nutshell')
print find_by(books, author='M. Beri')
print find_by(books, title='Python in a Nutshell',
author='A. Martelli')
try:
print find_by(books, title='Python in a Nutshell',
author='M.Beri')
print find_by(books, title='Python in a Nutshell',
pages=123)
except NotFound: pass