Salta al contenuto principale

Python, nozioni sulla sintassi

di Donato Taddei
su nvda, 14\04\2008,, h. 17.36.

Prendendo spunto dall'amico Domenico che candidamente commentava:

Ed ora, un po' di pubblicità

:

sorgio.

poi si parla di programmazione, di piton serpenti buoni che fanno bene alla programmazione, io non ci capisco una mazza però qui ci sono dei buoni maestri!
 

ma come?

Bene poichè so che hai un sito pure grossicello, che fai stramazzare esausti i discotecari più dell'estasi, e vuoi prendere la mazza per tenere a bada il
serpente.

Ma no.

Poichè molti di voi hanno un sito e per forwa di cose qualche rudimento di html Partiamo da qua:

Ce l'hai presente la struttura di una pagina html?

vale a dire una gerarchia di elementi, demarcati da marcatori o tags ai quali possono essere associati un certo numero di attributi, in funzione dell'elemento
o della classe o raggruppamento o insieme di elementi? 

Il pitone ragiona allo stesso modo. 

Alt! Che mi sparano!

L'analogia proposta riguarda solo il modo di organizzarsi i dati:

per il resto sono due mondi distanti:

l'html è un linguaggio per rappresentare dati, o più precisamente uno standard condiviso per il loro scambio,

il pitone invece è un linguaggio di programmazione, ovvero per elaborare dati.

Il pitone, come tutti i linguaggi di alto livello, appunto perchè è un linguaggio per elaborare dati, implementa anch'esso un parser html. 

Tornando all'analogia:

Cambiano i simboli, in questo caso sibili utilizzati:

anzicchè l'annidamento dei marcatori, c'è l'indentazione, e le amenità tipiche di ciascun linguaggio di programmazione, ma diciamo pure di qualsiasi linguaggio
in genere.

Infatti quasi ognuno è capace, specie in presenza di belle fighe, di masticare qualche parola in inglese;

Poi però ti rendi subito conto che non diciamo per scrivere un libro ma solo per fare un biglietto che non si può scappottare

dal conoscere un minimo di alfabeto, di ortografia, di sintassi.

Viceversa resti al livello del vucumbrà!

Così, giusto perchè ce l'ho per le mani, in questo e nei prossimi messaggi,

vi posterò una riduzione del manuale di riferimento Python,

I nemeri di paragrafo sono appunto quelli del manuale, ovviamente sfoltito.

Questo testo  parte da come è fatto un file pythonspiega l'uso dei ghirgori (es. parentesi, apici, ecc., dà una definizione dei "modi di dire, dello slang"
di questo linguaggio, elenca gli ingredienti base, (parole chiave) passando poi a spiegare la gerarchia dei differenti tipi dato.

Risulta utile:

a) - nella decifrazione del codice

b) - nella comprensione della terminologia specifica

c) - nel reperire riferimenti alla documentazione.

D) - nel capire immediatamente i messaggi di errore del compilatore. 

Nota:

chi ha seguito  la serie di questi miei interventi in merito ricorderà che ho spesso detto che in realtà si può anche fare a meno di avere un pitone a casa,
potendosi usare direttamente l'interprete implementato in nvda.

Ho anche fornto un paio di esempi di questo utilizzo.

Tuttavia tengo a sottolineare che quella può essere una soluzione di prova, per piccole modifche stante che l'infallibilità non è prerogativa umana e in
caso di eccezioni nvda si limita se va bene a emettere dei beep e ignorare il tutto.

Perciòper chi abbia velleità di fare il domatore di serpeti, foss'anche per farsi fare il caffè come usava fare la buonanima del dottor Jaws, sarà comunque
bene portarsi il pitone a casa. 

Quando c'è qualcosa che non va lo dice e poi tra le spire nasconde una cospicua documentazione.

Di solito si esprime quasi a monosillabi, o monosibili, ma con sufficiente chiarezza, specie se appunto si conoscono i tipi dato e come sono rappresentati. 

                        Donato Taddei 

2. Analisi lessicale

Un programma Python viene letto da un parser. L'input da analizzare è

una sequenza di token, generati dall'analizzatore lessicale. Questo

capitolo descrive come l'analizzatore lessicale divide il file in

token.

Python utilizza il set di caratteri ASCII a 7 bit per il testo del

programma. Nuovo nella versione 2.3: può essere dichiarata una

codifica per indicare che le stringhe costanti manifeste ed i commenti

sono in una codifica diversa da ASCII. uer compatibilità con vecchie

versioni, Python vi avvisa solo se trova caratteri ad 8 bit; questi

avvertimenti devono essere corretti utilizzando una specifica codifica

o utilizzando delle sequenza di escape (NdT: di protezione) se questi

byte sono dati binari anziché caratteri.

L'insieme di caratteri a runtime dipende dal dispositivo di I/O

connesso al programma, ma è generalmente un superinsieme di ASCII.

2.1 Struttura delle righe

Un programma Python è diviso in un certo numero di righe logiche.

2.1.1 Righe logiche

La fine di una riga fisica è rappresentato dal token NEWLINE. Le

dichiarazioni non possono attraversare i limiti delle righe logiche ad

eccezione di dove NEWLINE è ammesso dalla sintassi (per esempio tra

istruzioni in ``compount statements''). Una riga logica è costituita

da una o più righe fisiche seguendo le regole implicite o esplicite di

unione tra righe.

2.1.2 Righe fisiche

Una riga fisica termina dove si trova il terminatore di riga, secondo

la convenzione della piattaforma corrente. Su Unix, è il carattere

ASCII LF (linefeed). Su Windows è la sequenza ASCII CR LF (return

seguito da linefeed). Su Macintosh è il carattere ASCII CR (return).

2.1.3 Commenti

Un commento inizia con un carattere cancelletto (#) che non sia parte

di una stringa costante manifesta e termina alla fine della riga

fisica. Un commento indica la fine di una riga logica, a meno che non

siano invocate speciali regole di unione. I commenti vengono ignorati

dalla sintassi; non sono token.

2.1.5 Unione esplicita di righe

Due o più righe fisiche possono essere unite in righe logiche,

utilizzando il carattere backslash (\), come di seguito: quando una

riga fisica termina con un backslash che non è parte di una stringa

costante o un commento, viene unita alla seguente, formando una

singola riga logica, cancellando il backslash ed il seguente

terminatore di riga. Per esempio:

if 1900 < year < 2100 and 1 <= month <= 12 \

and 1 <= day <= 31 and 0 <= hour < 24 \

and 0 <= minute < 60 and 0 <= second < 60: # Per date valide

return 1

Una linea che termina in backslash non può avere un commento. Un

backslash non continua un commento. Un backslash non continua un

token, ad eccezione delle stringhe costanti (token che non siano

stringhe costanti non possono essere divisi tra righe fisiche

utilizzando un backslash). Un backslash è illegale in altre posizioni

in una riga, al di fuori di una stringa costante.

2.1.6 Unione implicita di righe

Le espressioni in parentesi tonde, quadre o graffe possono essere

divise su più righe fisiche senza utilizzare backslash. Per esempio:

month_names = ['Januari', 'Februari', 'Maart', # Questi sono i

'April', 'Mei', 'Juni', # nomi olandesi

'Juli', 'Augustus', 'September', # per i mesi

'Oktober', 'November', 'December'] # dell'anno

Le righe che continuano implicitamente possono avere dei commenti.

L'indentazione delle righe di continuazione non è importante. Sono

ammesse righe di continuazione vuote. Non c'è un token NEWLINE tra le

righe di continuazione implicite. Le righe di continuazione implicite

possono capitare anche in stringhe con tripla quotatura (vedete

sotto); in questo caso non possono contenere commenti.

2.1.7 Righe vuote

Una riga logica che contiene solo spazi, tabulazioni, avanzamenti di

pagina e facoltativamente un commento, viene ignorata (cioè non viene

generato un token NEWLINE). Durante sessioni interattive di istruzioni

in input, la gestione delle righe vuote può differire a seguito

dell'implementazione del ciclo di lettura-valutazione-stampa.

Nell'implementazione standard, una riga logica interamente vuota (cioè

priva di caratteri di spaziatura o commenti) termina un'istruzione

multiriga.

2.1.8 Indentazione

I caratteri di spaziatura (spazi e tab) all'inizio di una riga logica,

vengono utilizzati per computare il livello di indentazione di questa

riga; in pratica determina il raggruppamento delle istruzioni.

Come prima cosa, i tab vengono sostituiti (da sinistra a destra) da un

numero di spazi variabile da uno ad 8, in modo che il numero totale di

caratteri incluso la sostituzione sia un multiplo di otto (questo si

intende come la regola utilizzata dai sistemi Unix). Il numero totale

di spazi che precedono il primo carattere che non sia di spaziatura

determinano quindi l'indentazione della riga. L'indentazione non può

essere divisa su più righe fisiche utilizzando i backslash; gli spazi

fino al primo backslash determinano il livello di indentazione.

Prima che venga letta la prima riga del file, un singolo zero viene

messo sullo stack; questo non verrà mai rimosso. Il numero messo nello

stack sarà sempre strettamente crescente, dal fondo alla cima.

All'inizio di ogni riga logica, il livello di indentazione della riga

viene confrontato con la cima dello stack. Se uguale non accade

niente. Se è maggiore, viene messo nello stack e viene generato un

token INDENT. Se minore, deve essere uno dei numeri presenti nello

stack; tutti i numeri maggiori vengono eliminati dallo stack e, per

ognuno di questi, viene generato un token DEDENT. Alla fine del file

viene generato un token DEDENT per ogni numero rimasto nello stack che

sia maggiore di zero.

Ecco un esempio di una porzione di codice python correttamente

indentato, anche se fuorviante:

def perm(l):

# Compute the list of all permutations of l

if len(l) <= 1:

return [l]

r = []

for i in range(len(l)):

s = l[:i] + l[i+1:]

p = perm(s)

for x in p:

r.append(l[i:i+1] + x)

return r

2.1.9 Spaziature tra i token

Ad eccezione dell'inizio di una riga logica o una stringa costante, i

caratteri di spaziatura (spazi, tab e avanzamento di pagina) possono

essere utilizzati in modo intercambiabile per separare i token. Una

spaziatura è necessaria tra due token solo se la loro concatenazione

possa altrimenti essere interpretata come un token differente (per

esempio "ab" è un token, ma "a" e "b" sono due token).

2.2 Altri token

A parte NEWLINE, INDENT e DEDENT, esistono le seguenti categorie di

token: identifiers, keywords, literals , operators e delimiters (NdT:

identificatori, parole chiave, costanti manifeste, operatori e

delimitatori). I caratteri di spaziatura (a parte i terminatori di

riga, come discusso precedentemente) non sono token, ma servono per

delimitare i token. Quando esiste un'ambiguità, un token comprende la

maggior porzione di stringa che possa formare un token legale, quando

letto da sinistra a destra.

2.3 Identificatori e keywords

Gli identificatori (anche chiamati nomi) sono descritti dalle seguenti

definizioni lessicali:

Gli identificatori possono essere di lunghezza arbitraria. La

distinzione tra lettere maiuscole e minuscole è significativa.

2.3.1 Parole chiave

I seguenti identificatori vengono utilizzati come parole riservate o

parole chiave del linguaggio e non possono essere utilizzati come

identificatori ordinari. Devono essere scritti esattamente come sono

scritti qui:

and del for is raise

assert elif from lambda return

break else global not try

class except if or while

continue exec import pass yield

def finally in print

2.3.2 Classi riservate di identificatori

Alcune classi di identificatori (a parte le parole chiave) hanno un

significato speciale. Queste classi vengono identificate come un

modello caratterizzato da un carattere di sottolineatura all'inizio o

2.4 Literals

Le costanti manifeste sono le notazioni per i valori costanti di

alcuni tipi built-in.

2.4.1 Stringhe costanti manifeste

Le stringhe costanti vengono descritte dalle seguenti definizioni

lessicali:

stringliteral ::= [stringprefix](shortstring | longstring)

stringprefix ::= "r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"

shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"'

longstring ::= "'''" longstringitem* "'''"

| '"""' longstringitem* '"""'

shortstringitem ::= shortstringchar | escapeseq

longstringitem ::= longstringchar | escapeseq

shortstringchar ::=

longstringchar ::=

escapeseq ::= "\"

Una restrizione sintattica non indicata da queste produzioni è che non

sono ammesse spaziature tra stringprefix ed il resto della stringa

costante.

In Italiano: le stringhe costanti possono essere racchiuse in

caratteri di quotatura singola (') o doppia ("). Possono anche essere

racchiusi in gruppi di stringhe composte da tuple di tre elementi di

quotatura (NdT: queste sono in genere indicate come ``triple-quoted

strings''). Il carattere backslash (\) viene utilizzato come carattere

di escape, che altrimenti avrebbe un significato speciale, come il

fine riga, la stessa backslash o il carattere di quotatura. Le

stringhe costanti manifeste possono facoltativamente avere come

prefisso le lettere "r" o "R"; queste stringhe sono dette stringhe raw

e utilizzano differenti regole per l'interpretazione dei backslash

nelle sequenze di escape.

A meno che il prefisso "r" o "R" non sia presente, le sequenze di

escape in una stringa vengono interpretate in accordo a regole simili

a quelle utilizzate nello standard C. Le sequenze di escape

riconosciute sono:

Sequenza di escape Significato Note

\newline Ignorato

\\ Backslash (\)

\' Carattere di quotatura singola (')

\" Carattere di quotatura doppia (")

\a ASCII Bell (BEL)

\b ASCII Backspace (BS)

\f ASCII Formfeed (FF)

\n ASCII Linefeed (LF)

\N{name} Carattere chiamato name nel database Unicode (solamente in

Unicode)

\r ASCII Carriage Return (CR)

\t ASCII Tab orizzontale (TAB)

\uxxxx Carattere con valore esadecimale a 16 bit xxxx (valido solo per

Unicode) (1)

\Uxxxxxxxx Carattere con valore esadecimale a 32 bit xxxxxxxx (valido

solo per Unicode) (2)

\v ASCII Tab verticale (VT)

\ooo Carattere ASCII con valore ottale ooo (3)

\xhh Carattere ASCII con valore esadecimale hh (4)

2.4.2 Concatenazione di stringhe costanti manifeste

Stringhe costanti manifeste multiple ed adiacenti (delimitate da

caratteri di spaziatura), che possibilmente utilizzano differenti

convenzioni di quotatura, sono ammesse ed hanno lo stesso significato

di una concatenazione. Perciò "hello" 'world' è equivale ad

"helloworld". Questa funzionalità può essere utilizzata per ridurre il

numero di backslash necessari, per suddividere stringhe lunghe in modo

conveniente, attraverso lunghe righe o anche per aggiungere commenti

ad alcune parti della stringa; per esempio:

re.compile("[A-Za-z_]" # lettere o sottolineature

"[A-Za-z0-9_]*" # lettere, numeri o sottolineature

)

2.4.3 Costanti numeriche

Ci sono quattro tipi di costanti manifeste numeriche: interi, interi

long, numeri in virgola mobile e numeri immaginari. Non ci sono

costanti complesse (i numeri complessi possono essere formati sommando

un numero reale ed un numero immaginario).

Si noti che le costanti numeriche non includono il segno; una frase

come -1 è in realtà un'espressione composta dall'operatore unario `-'

e dalla costante numerica 1.

2.4.4 Costanti di tipo intero e long

Anche se si puó utilizzare sia il suffisso "l" che "L" per indicare

una costante long, è altamente raccomandato di utilizzare sempre "L",

poiché la lettera "l" è troppo simile alla cifra "1".

Le costanti intere che sono maggiori del più grande numero intero

rappresentabile (per esempio 2147483647 quando si utilizza

un'aritmetica a 32 bit) vengono accettate come se fossero costanti

long. ^2.1Non c'é limite alla lunghezza delle costanti long, a parte

la limitazione dovuta alla dimensione della memoria disponibile.

Alcuni esempi di costanti numeriche intere (prima riga) e long

(seconda e terza riga):

7 2147483647 0177

3L 79228162514264337593543950336L 0377L 0x100000000L

Si noti che la parte intera e l'esponente di un numero in virgola

mobile possono sembrare come interi in notazione ottale, ma vengono

interpretati utilizzando la base 10. Per esempio, "077e010" è legale e

denota lo stesso numero come "77e10". La gamma di costanti numeriche

in virgola mobile ammessa dipende dall'implementazione. Alcuni esempi

di costanti in virgola mobile:

3.14 10. .001 1e100 3.14e-10 0e0

2.5 Operatori

I seguenti token sono operatori:

+ - * ** / // %

<< >> & | ^ ~

< > <= >= == != <>

Gli operatori di confronto <> e != sono forme alternative dello stesso

operatore. La forma preferita è !=, mentre <> è obsoleta.

2.6 Delimitatori

I seguenti token operano come delimitatori grammaticali:

( ) [ ] { }

, : . ` = ;

+= -= *= /= //= %=

&= |= ^= >>= <<= **=

Il punto occorre anche nelle costanti numeriche reali ed immginarie.

Una sequenza di tre punti ha un significato speciale come un'ellissi

in una fetta. La seconda metà della lista, gli operatori di

assegnamento e modifica, operano lessicalmente come delimitatori, ma

effettuano anche delle operazioni.

I seguenti caratteri ASCII stampabili hanno un significato speciale

come parte di altri token o sono altrimenti significativi per

l'analizzatore lessicale:

' " # \

I seguenti caratteri ASCII stampabili non vengono utilizzati in

Python. La loro presenza fuori da stringhe costanti manifeste e

commenti è un errore:

@ $ ?

3. Modello dei dati

3.1 Oggetti, valori e tipi

Gli oggetti sono delle astrazioni di Python per i dati. Tutti i dati

in Python vengono rappresentati da oggetti o da relazioni tra oggetti.

(In un certo senso, e conformemente al modello di Von Neumann di

``stored program computer'', anche il codice viene rappresentato come

un oggetto).

Ogni oggetto ha un'identità, un tipo ed un valore. L'identità di un

oggetto non cambia mai dopo che è stato creato; potete pensare a

questa come l'indirizzo di memoria dell'oggetto. L'operatore `is'

confronta l'identità di 2 oggetti;

la funzione id() restituisce un

intero che rappresenta l'identità dell'oggetto (attualmente

implementato come il suo indirizzo).

Il tipo di un oggetto è anch'esso

immutabile.^3.1 Il tipo di un oggetto determina le operazioni che

l'oggetto supporta (per esempio, ``è possibile determinarne la

lunghezza?'') e definisce anche i possibili valori per gli oggetti di

quel tipo.

La funzione type() restituisce il tipo dell'oggetto (che è

a sua volta un oggetto).

Il valore di alcuni oggetti può cambiare.

Gli oggetti il cui valore può cambiare vengono detti mutabili; gli oggetti

il cui valore non può cambiare vengono detti immutabili. (

Il valore di un oggetto contenitore immutabile che contiene un riferimento ad un

oggetto mutabile può cambiare quando cambia il valore di quest'ultimo;

comunque il contenitore viene ancora considerato immutabile, poiché la

collezione di oggetti che contiene non può essere cambiata. Perciò

immutabile non è strettamente equivalente ad un valore non

modificabile, la differenza è più sottile). La mutabilità di un

oggetto viene determinata dal suo tipo; per esempio numeri, stringhe e

tuple sono immutabili, mentre dizionari e liste sono mutabili.

Alcuni oggetti contengono riferimenti ad altri oggetti; questi vengono

chiamati contenitori. Sono esempi di contenitori tuple, liste e

dizionari. Questi riferimenti sono parte del valore del contenitore.

In molti casi, quando parliamo del valore del contenitore, implichiamo

il valore, non l'identità degli oggetti contenuti; comunque, quando

parliamo di mutabilità di un contenitore, viene implicata solo

l'identità dell'oggetto immediatamente contenuto. Perciò, se un

contenitore immutabile (come una tupla) contiene un riferimento ad un

oggetto mutabile, il suo valore può cambiare se cambia questo oggetto

mutabile.

I tipi coinvolgono quasi tutti gli aspetti del comportamento di un

oggetto. Anche l'importanza dell'identità degli oggetti ne viene

coinvolta in qualche modo: per i tipi immutabili, le operazioni che

computano nuovi valori possono in realtà restituire un riferimento ad

un oggetto esistente con lo stesso valore, mentre per gli oggetti

mutabili non è ammesso.

Per esempio, dopo "a = 1; b = 1", a e b

possono fare riferimento allo stesso oggetto con il valore uno, a

seconda dell'implementazione, ma dopo "c = []; d = []" è garantito che

c e d faranno riferimento a due liste differenti, uniche e vuote

(notare invece che "c = d = []" assegna lo stesso oggetto a c e d).

3.2 La gerarchia dei tipi standard

Di seguito una lista di tutti i tipi che vengono costruiti in Python.

I moduli di estensione (scritti in C, Java o altri linguaggi, in

funzione dell'implementazione) possono definire ulteriori tipi. Le

future versioni di Python potranno aggiungere tipi alla gerarchia dei

tipi (per esempio numeri razionali, array di interi memorizzati

efficientemente, etc.).

Alcuni dei tipi descritti contengono un paragrafo che elenca gli

`attributi speciali'.

Questi sono attributi che forniscono accesso all'implemenatzione e non sono intesi per l'uso generale. La loro

definizione potrà cambiare in futuro.

None

Questo tipo ha un singolo valore. C'è un solo oggetto con

questo valore. Questo oggetto è accessibile attraverso il nome

built-in None. Viene utilizzato per indicare l'assenza di un

valore in molte situazioni, per esempio, viene restituito dalle

funzioni che non restituiscono esplicitamente qualcosa. Il suo

valore di verità è ``Falso''.

NotImplemented

Questo tipo ha un singolo valore. C'è un solo oggetto con

questo valore. Questo oggetto è accessibile attraverso il nome

built-in NotImplemented. I metodi numerici ed i metodi di

confronto complessi possono restituire questo valore se non

implementano l'operazione per l'operando fornito. (L'interprete

proverà quindi a riflettere l'operazione, o altri metodi di

fallback, a seconda dell'operatore in questione.) Il suo valore

di verità è ``Vero''.

Ellipsis

Questo tipo ha un singolo valore. C'è un solo oggetto con

questo valore. Questo oggetto è accessibile con il nome

built-in Ellipsis. Viene utilizzato per indicare la presenza di

"..." nella sintassi di una sequenza. Il suo valore di verità è

``Vero''.

Numbers

Questi vengono creati da costanti numeriche e restuituiti come

risultato di operazioni aritmetiche o funzioni aritmetiche

built-in. Gli oggetti numerici sono immutabili; una volta

creati, il loro valore non verrà mai cambiato. I numeri Python

sono ovviamente strettamente correlati con i numeri matematici,

ma soggetti alle limitazioni numeriche della rappresentazione

su computer.

Python distingue tra interi, numeri in virgola mobile e numeri

complessi:

Integers

Questi rappresentano elementi dall'insieme matematico di

tutti i numeri:

Ci sono tre tipi di interi:

Interi Plain

Questi rappresentano numeri nell'intervallo da

-2147483648 a 2147483647. (L'intervallo può essere

maggiore su architetture con una dimensione più

grande, ma mai minore.) Quando il risultato di

un'operazione cade al di fuori di questo

intervallo, il risultato viene normalmente

restituito come un intero di tipo long (in alcuni

casi, viene invece sollevata l'eccezione

OverflowError). Per scopi volti ad operazioni di

scorrimento o per maschere, si assume che gli

interi abbiano una notazione binaria in complemento

a 2, utilizzando 32 bit o più e nascondendo alcuni

bit all'utente (cioé, tutti i 4294967296 differenti

modelli di bit corrispondono a differenti valori).

Interi Long

Questi rappresentano i numeri in un intervallo

illimitato, soggetti solamente alla memoria

(virtuale) disponibile. Per scopi volti ad

operazioni di scorrimento o per maschere, si assume

una rappresentazione binaria e i numeri negativi

vengono rappresentati in una variante della

notazione in complemento a due che dà l'illusione

di una stringa infinita di bit con segno che si

estende verso sinistra.

Booleani

Questi rappresentano i valori di verità ``Vero'' e

``Falso''. I due oggetti che rappresentano ``Vero''

e ``Falso'' sono gli unici oggetti booleani. Il

tipo Boolean è un sottotipo degli interi plain ed i

valori di Boolean si comportano come i valori 0 e 1

rispettivamente, in quasi tutti i contesti, ad

eccezione di quando vendono convertiti in stringa,

dove vendono restituite, rispettivamente, le

stringhe "False" e "True".

Numeri in virgola mobile

Questi rappresentano i numeri in virgola mobile in

precisione doppia (rappresentazione finita disponibile su

un computer). Siete lasciati alla misericordia

dell'architettura sottostante (e delle implementazioni C

e Java) per l'intervallo accettato e la gestione

dell'overflow. Python non supporta i numeri in virgola

mobile in precisione singola; il guadagno in utilizzo di

processore e memoria, che è in genere il motivo per

utilizzarli, viene sminuito dall'overhead di utilizzare

oggetti in Python, perciò non c'è ragione di complicare

il linguaggio con due tipi di numeri in virgola mobile.

Numeri complessi

Rappresentano numeri complessi come una coppia di numeri

in virgola mobile in precisione doppia. Valgono gli

stessi avvertimenti dati per i numeri in virgola mobile.

Le parti reali ed immaginarie di un numero complesso z

possono essere recuperate attraverso degli attributi in

sola lettura z.real e z.imag.

Sequenze

Rappresentano degli insiemi ordinati e finiti di elementi

indicizzati tramite numeri non negativi. La funzione built-in

len() restituisce il numero di elementi di una sequenza. Quando

la lunghezza di una sequenza è n, l'indice contiene i numeri 0,

1, ..., n-1. L'elemento i di una sequenza a viene selezionata

tramite a[i].

Le sequenza supportano anche l'affettamento: a[i:j] seleziona

tutti gli elementi con indice k tale che vari <= k < j. Quando

utilizzata come un'espressione, una fetta è una sequenza dello

stesso tipo. Questo implica che l'insieme degli indici viene

rinumerato in modo che inizi da 0.

Alcune sequenze supportano anche l'``affettazione estesa'' con

un terzo parametro ``passo'': a[i:j:k] seleziona tutti gli

elementi di a con un indice x dove x = i + n*k, n >= 0 e i <= x

< j.

Le sequenze si distinguono in base alla mutabilità:

Sequenze immutabili

Un oggetto di una sequenza di tipo immutabile non può

cambiare una volta che è stato creato. (Se l'oggetto

contiene un riferimento ad un'altro oggetto, quest'ultimo

può essere mutabile e può cambiare; comunque, la

collezione di oggetti direttamente referenziati da

un'oggetto immutabile non può cambiare.)

I seguenti tipi sono sequenze immutabili:

Stringhe

Gli elementi di una stringa sono caratteri. Non c'è

un tipo separato per i caratteri; un carattere

viene rappresentato da una stringa di un elemento.

I caratteri rappresentano (almeno) un byte di 8

bit. Le funzioni built-in chr() e ord() effettuano

le conversioni tra i caratteri e degli interi non

negativi che rappresentano il valore del byte. I

byte con i valori 0-127 rappresentano generalmente

i valori ASCII corrispondenti, ma l'interpretazione

dei valori viene lasciata al programma. Il tipo di

dato stringa viene anche utilizzato per

rappresentare array di byte, per esempio, per

gestire i dati letti da un file.

Unicode

Gli elementi di un oggetto Unicode sono unità di

codice Unicode. Un'unità di codice Unicode viene

rappresentata da n oggetto unicode di un elemento e

può contenere un valore a 16 o 32 bit che

rappresenta un ordinale Unicode (il massimo valore

per gli ordinali Unicode viene indicato in

sys.maxunicode e dipende da come è stato

configurato Python al momento della compilazione).

Negli oggetti Unicode possono essere presenti delle

coppie surrogate e verranno segnalate come due

elementi separati. Le funzioni built-in unichr() ed

ord() convertono tra le unità di codice ed interi

non negativi rappresentanti gli ordinali Unicode,

come definito nello Standard Unicode 3.0. Le

conversioni da e verso le altre codifiche sono

possibili attraverso i metodi di codifica encode

degli oggetti Unicode e la funzione built-in

unicode()..

Tuple

Gli elementi di una tupla sono oggetti Python

arbitrari. Le tuple di due o più elementi vengono

formattate in una lista di espressioni separate da

virgole.

Una tupla di un elemento (un 'singleton')

può essere formato aggiungendo una virgola ad

un'espressione (un'espressione da sola non crea una

tupla, poiché le parentesi devono essere

utilizzabili per raggruppare le espressioni). Una

tupla vuota può essere resa da una coppia vuota di

parentesi.

Sequenze mutabili

Le sequenze mutabili possono essere modificate dopo la

loro creazione. Le notazioni subscription e slice possono

essere utilizzate come obiettivi di un assegnamento o di

un'istruzione del (cancella).

C'è attualmente un solo tipo intrinseco di sequenze

mutabili:

Liste

Gli elementi di una lista sono oggetti Python

arbitrari. Le liste sono formate da una lista di

espressioni separate da virgola in una coppia di

parentesi quadre. (Notare che non c'è un caso

speciale per le liste di lunghezza 0 o 1).

Il modulo di estensione array fornisce un'esempio

aggiuntivo di sequenze mutabili.

Mappe

Rappresentano un insieme finito di oggetti indicizzati da un

insieme arbitrario di indici.

La notazione di subscription a[k]

seleziona l'elemento indicizzato k dalla mappa a; questo può

essere utilizzato nelle espressioni come obiettivo di un

assegnamento o di un'istruzione del (cancella). La funzione

built-in len() restituisce il numero di elementi in una mappa.

Dizionari

Rappresentano un insieme finito di oggetti indicizzati da

valori praticamente arbitrari. Gli unici tipi di valori

non accettabili come chiavi sono i valori contenenti

liste o dizionari o altri oggetti di tipo mutabile che

vengono confrontati per valore piuttosto che per

identità, la ragione di questo è che l'implementazione

efficiente dei dizionari richiede un valore di hash per

la chiave costante nel tempo. I tipi numerici utilizzati

come chiavi obbediscono alle normali regole per il

confronto numerico: se due numeri sono uguali (per

esempio 1 e 1.0) possono essere usati in modo

intercambiabile per indicizzare lo stesso elemento del

dizionario.

Tipi eseguibili

Sono i tipi a cui si può applicare l'operazione di chiamata a

funzione

Funzioni definite dall'utente

Un oggetto funzione definita dall'utente viene creato

dalla definizione di funzione

Deve essere chiamato con

una lista di argomenti che contiene lo stesso numero di

oggetti della lista formale di parametri ammessi per la

funzione.

Attributi speciali:

func_doc o __doc__ è la stringa di

documentazione (docstring) della funzione, o None se non

disponibile;

func_name o __name__ è il nome della funzione;

__module__ è il nome del modulo in cui la

funzione è stata definita o None se non disponibile;

func_defaults è una tupla che contiene i valori

predefiniti per gli argomenti che hanno un valore

predefinito oppure None se nessun argomento ha un valore

predefinito;

func_code è un oggetto di tipo codice che

rappresenta il codice compilato del corpo della funzione;

func_globals è (un riferimento a) il dizionario che

mantiene le variabili globali della funzione -- questo

definisce lo spazio dei nomi globale del modulo in cui la

funzione viene definita;

func_dict o __dict__ contiene lo spazio dei nomi che sostiene gli attributi arbitrari di

funzione;

func_closure è None oppure una tupla di celle

che contengono le associazioni per le variabili libere

della funzione.

Di queste, func_code, func_defaults, func_doc/__doc__ e

func_dict/__dict__ possono essere scrivibili; le altre

non possono mai cambiare.

Informazioni aggiuntive circa

la definizione della funzione, possono essere recuperate

dal suo oggetto di tipo codice; si veda la descrizione

dei tipi interni sotto.

Metodi definiti dall'utente

Un oggetto di tipo metodo definito dall'utente combina

una classe, un'istanza di classe (o None) ed un qualunque

oggetto chiamabile (normalmente una funzione definita

dall'utente).

Attributi speciali in sola lettura:

im_self è l'oggetto

che rappresenta l'istanza della classe;

im_func èl'oggetto che rappresenta la funzione;

im_class è la classe di

im_self per i metodi associati (bound) o la

classe a cui chiedere il metodo

per i metodi non associati (unbound); __doc__ è la documentazione del

metodo (lo stesso di im_func.__doc__); __name__ è il nome

del metodo (lo stesso di im_func.__name__); __module__ è

il nome del modulo in cui il metodo è stato definito o

None se non disponibile.

im_self referenzia la classe che definisce il metodo. 

I metodi definiti dall'utente possono essere creati

quando si recupera l'attributo di una classe (forse

tramite un'istanza di quella classe), se questo attributo

è una funzione definita dall'utente, un metodo definito

dall'utente non associato o un metodo di classe. Quando

l'attributo è un metodo definito dall'utente, un nuovo

oggetto di tipo metodo viene creato solo se la classe da

cui viene recuperato è la stessa o deriva dalla stessa

classe o dalla classe immagazzinata nel metodo originale;

altrimenti viene utilizzato il metodo originale.

Funzioni generatore

Una funzione od un metodo che usa l'istruzione yield

(vedere la sezione 6.8, ``L'istruzione yield'') viene

chiamata funzione generatore. Come una funzione, una

volta invocata, restituisce sempre un oggetto iteratore

che può essere usato per eseguire il corpo della

funzione:

attraverso il metodo iteratore next() la

funzione verrà eseguita finché continuerà a provvedere un

valore usando l'istruzione yield.

Quando la funzione

esegue un'istruzione return o raggiunge la fine, viene

sollevata un'eccezione StopIteration

e l'iteratore che

avrà raggiunto la fine della serie di valori verrà

restituito.

Funzioni built-in

Una funzione built-in è un wrapper per le funzioni C.

Esempi di funzioni built-in sono len() e math.sin() (math

è un modulo built-in standard). Il numero ed il tipo

degli argomenti vengono determinati dalla funzione C.

Attributi speciali di sola lettura: __

doc__ è la stringa

di documentazione della funzione, o None se non è

disponibile;

__name__ è il nome della funzione;

__self__ viene impostato a None

__module__ è il nome del modulo nel quale la

funzione è stata definita o None se non è disponibile.

Metodi built-in

Questo è il travestimento di una funzione built-in, in

questo caso contenente un oggetto passato alla funzione C

come un implicito argomento extra. Un esempio di un

metodo built-in è alist.append(), assumendo alist come un

oggetto lista. In questo caso, l'attributo speciale di

sola lettura __self__ viene impostato all'oggetto

rappresentato dalla lista, list.

Tipi di classi

Le classi tipo, o ``classi di nuovo stile'', sono

invocabili. Questi oggetti agiscono normalmente come

generatori di nuove istanze di se stesse, ma sono

possibili variazioni per le classi tipo che sovrascrivono

__new__(). Gli argomenti della chiamata vengono passati a

__new__() e, in casi tipici, a __init__() per

l'inizializzazione della nuova istanza.

Classi classiche

Gli oggetti classe vengono descritti di seguito. Quando

un oggetto classe viene chiamato, viene creata e

restituita una nuova istanza della classe (descritta

anch'essa di seguito). Questo implica una chiamata al

metodo __init__() della classe, se esiste. Qualsiasi

argomento viene passato al metodo __init__(). Se non

esiste un metodo __init__(), la classe deve essere

invocata senza argomenti.

Istanze di una classe

Le istanze di una classe vengono descritte di seguito. Le

istanza di una classe sono invocabili solo quando la

classe ha un metodo __call__(); x(argomenti) è una

scorciatoia per x.__call__(argomenti).

Moduli

I moduli vengono importati attraverso l'istruzione import

``L'istruzione import'').Un oggetto

modulo ha uno spazio dei nomi implementato come fosse un

dizionario (questo è il dizionario referenziato dall'attributo

func_globals delle funzioni definite nel modulo). I riferimenti

agli attributi vengono tradotti in controlli in questo

dizionario, per esempio, m.x è equivalente a m.__dict__["x"].

Un oggetto modulo non contiene il codice oggetto usato per

inizializzare il modulo (dato che è già stato inizializzato una

volta).

L'assegnamento di attributi aggiorna il dizionario dello spazio

dei nomi del modulo, per esempio, "m.x = 1" equivale a

"m.__dict__["x"] = 1".

Attributi speciali di sola lettura: __dict__ è il dizionario

dello spazio dei nomi del modulo.

Attributi predefiniti (modificabili):

__name__ è il nome del modulo;

__doc__ è la stringa di documentazione del modulo o

None se non è disponibile;

__file__ è il percorso del file da

cui è stato caricato il modulo, se è stato caricato da un file.

L'attributo __file__ non è presente per i moduli C che sono

linkati staticamente nell'interprete; per estensioni di moduli

caricati dinamicamente da librerie condivise, è il percorso del

file della libreria condivisa.

Classi

Gli oggetti classe vengono creati dalla definizione class

``Definizioni di classe''). Una classe

ha uno spazio dei nomi implementato attraverso un dizionario. I

riferimenti agli attributi della classe vengono tradotti in

controlli in questo dizionario, per esempio,

"C.x" viene convertito in "C.__dict__["x"]".

Quando l'attributo non viene

trovato, la sua ricerca continua nelle classi di base. La

ricerca è basata prima sulla profondità, da sinistra a destra e

nell'ordine delle occorrenze nella lista delle classi di base.

Quando un riferimento ad un attributo di classe (per una classe

C) deve produrre una funzione definita dall'utente o uno

slegamento di un metodo definito dall'utente la cui classe

associata è sia C che ad una delle sue classi di base, viene

trasformato in un metodo slegato definito dall'utente il cui

attributo im_class è C. Nel caso dovesse produrre un metodo di

classe, viene trasformato in un metodo legato definito

dall'utente i cui attributi im_class e im_self sono entrambi C.

Mentre nel caso dovesse produrre un metodo statico, viene

trasformato in un oggetto wrapped dal metodo statico. Vedere la

sezione 3.3.2 per altri modi in cui gli attributi ricevuti da

una classe possono differire da quelli attualmente contenuti

nel proprio __dict__.

L'assegnamento di attributi di una classe aggiornano il

dizionario della classe e mai il dizionario della classe di

base.

Un oggetto classe può essere chiamato (vedere sopra) per

produrre un'istanza di una classe (vedere di seguito).

Attributi speciali:

__name__ è il nome della classe;

__module__ è il nome del modulo in cui è definita la classe;

__dict__ è il dizionario contenente lo spazio dei nomi della classe;

__bases__ è una tupla (forse vuota o un singleton) contenente

le classi di base nell'ordine delle loro occorrenze nella lista

della classe di base;

__doc__ è la stringa di documentazione

della classe o None se non è definita.

Istanze di classe possono pretendere di essere numeri, sequenze

o mappe se hanno metodi con certi nomi speciali. Vedere la

sezione 3.3, ``Nomi di metodi speciali''.

Attributi speciali:

__dict__ è il dizionario degli attributi;

__class__ è l'istanza della classe.

File

Un oggetto file rappresenta un file aperto. Oggetti file

vengono creati dalla funzione built-in open() ed anche da

os.popen(), os.fdopen() e dal metodo makefile() di oggetti

socket (e forse da altre funzioni o metodi forniti da moduli di

estensione).

Gli oggetti sys.stdin, sys.stdout e sys.stderr

vengono inizializzati da oggetti file corrispondenti ai flussi

input, output ed error dell'interprete standard. Si veda la

Libreria Python di riferimento per la documentazione completa

di oggetti file.

Tipi interni

Alcuni tipi usati internamente dall'interprete vengono resi

disponibili all'utente.

completezza.

Codice oggetto

Il codice oggetto rappresenta il codice Python

eseguibile, byte-compilato, o bytecode. La differenza tra

codice oggetto ed oggetto funzione è che la funzione

contiene un esplicito riferimento alle funzioni globali

(il modulo in cui è stata definita), mentre un codice

oggetto non contiene del contesto; anche i valori degli

argomenti predefiniti vengono memorizzati nella funzione,

non nel codice oggetto (dato che i valori rappresentati

vengono calcolati al momento dell'esecuzione). A

differenza delle funzioni, il codice oggetto è immutabile

e non contiene riferimenti (diretti o indiretti) ad

oggetti mutabili.

Attributi speciali di sola lettura:

co_name fornisce il nome della funzione;

co_argcount indica il numero degli argomenti posizionali (inclusi gli argomenti con valori

predefiniti);

co_nlocals indica il numero delle variabili

locali usate per la funzione (inclusi gli argomenti);

co_varnames è una tupla contenente i nomi delle variabili

locali (partendo con i nomi degli argomenti);

co_cellvars

è una tupla contenente i nomi delle variabili locali che

vengono referenziate da funzioni annidate;

co_freevars è

una tupla contenente i nomi delle variabili libere;

co_code è una stringa che rappresenta la sequenza di

istruzioni bytecode;

co_consts è una tupla contenente le

costanti usate dal bytecode;

co_names è una tupla

contentente i nomi usati dal bytecode;

co_filename è il

nome del file da cui è stato compilato il codice;

co_firstlineno indica il numero della prima riga della

funzione;

co_lnotab è una stringa che codifica la

mappatura degli offset del bytecode in numeri di riga

(per dettagli vedere il codice sorgente dell'interprete);

co_stacksize è la dimenszione richiesta dello stack

(variabili locali incluse);

co_flags è un intero che

codifica un numero di flag per l'interprete.

Attributi speciali modificabili:

f_trace, se non è None, è una funzione invocabile all'avvio di ogni riga di

codice sorgente (usata dal debugger);

f_exc_type, f_exc_value, f_exc_traceback rappresentano le eccezioni

più recenti sollevate in questo frame;

f_lineno è il numero di riga corrente del frame -- se lo si scrive

all'interno di una funzione trace si salta alla data riga

Oggetti traceback

Gli oggetti traceback rappresentano lo stack trace di

un'eccezione. Un oggetto traceback viene creato quando

viene sollevata un'eccezione. Quando la ricerca di

un'eccezione tratta lo stack di esecuzione, viene

inserito un oggetto traceback davanti al corrente

traceback per ogni livello. Quando viene inserito un

gestore di eccezioni, la traccia dello stack viene resa

disponibile al programma. (Vedere la sezione 7.4,

del livello corrente; tb_lineno fornisce il numero di

Oggetti fetta

Gli oggetti fetta vengono usati per rappresentare delle

fette quando viene usata una sintassi di affettazione

estesa. Questa è una fetta che usa i due punti o fette

multiple o ellissi separate da virgole, per esempio,

a[i:j:step], a[i:j, k:l] o a[..., i:j]. Vengono anche

create dalla funzione built-in slice().

Attributi speciali in sola lettura:

start è il legame più basso;

stop è il legame più alto; step è il valore del

passo;

ciascuno di questi valori viene considerato None

se omesso. Questi attributi possono essere di qualsiasi

tipo.

Gli oggetti fetta supportano un metodo:

indices( self, length)

Questo metodo accetta come singolo argomento un

intero (length) e calcola l'informazione circa la

fetta estesa che l'oggetto fetta dovrebbe

descrivere. 

Metodi statici degli oggetti

I metodi statici forniscono un modo per annullare la

trasformazione di funzioni in metodi come descritto in

precedenza. Un metodo statico è un involucro (wrapper)

attorno ad altri oggetti, di solito metodi definiti

dall'utente. Quando un metodo statico viene richiesto da

una classe o dall'istanza di una classe, l'oggetto

attualmente restituito è un oggetto involucro (wrapper),

che non è soggetto ad altre trasformazioni. I metodi

statici non sono essi stessi invocabili, benché gli

oggetti siano essi stessi involucri (wrap). I metodi

statici vengono creati dal costruttore built-in

staticmethod().

Metodi di classe degli oggetti

Un metodo di classe, come un metodo statico, è un

involucro (wrapper) attorno ad un altro oggetto che

altera il modo nel quale questo oggetto viene richiamato

dalla classe e dalle instanze della classe. Come

richiamare un metodo di classe è stato descritto in

precedenza, in ``Metodi definiti dall'utente''. I metodi

di classe vengono creati dal costruttore built-in

classmethod().

3.3 Nomi di metodi speciali

Una classe può implementare certe operazioni che vengono invocate da

sintassi speciali (come operazioni aritmetiche o subscript e

affettamenti) definendo metodi con speciali nomenclature. Questo è

l'approccio di Python all'overload degli operatori, permettendo alle

classi di definire il proprio comportamento rispettando altresì gli

operatori del linguaggio. Per esempio, se una classe definisce un

metodo chiamato __getitem__() ed x è un'istanza di questa classe, x[i]

equivale a x.__getitem__(i). Eccetto dove menzionato, i tentativi di

eseguire un'operazione quando non sono stati definiti metodi

appropriati, sollevano un'eccezione.