summaryrefslogtreecommitdiffhomepage
path: root/it-it
diff options
context:
space:
mode:
Diffstat (limited to 'it-it')
-rw-r--r--it-it/c++-it.html.markdown283
-rw-r--r--it-it/python-it.html.markdown199
2 files changed, 435 insertions, 47 deletions
diff --git a/it-it/c++-it.html.markdown b/it-it/c++-it.html.markdown
index 92ebc165..4af30176 100644
--- a/it-it/c++-it.html.markdown
+++ b/it-it/c++-it.html.markdown
@@ -8,6 +8,7 @@ contributors:
- ["Connor Waters", "http://github.com/connorwaters"]
translators:
- ["Robert Margelli", "http://github.com/sinkswim/"]
+ - ["Tommaso Pifferi", "http://github.com/neslinesli93/"]
lang: it-it
---
@@ -151,7 +152,7 @@ namespace Primo {
namespace Secondo {
void foo()
{
- printf("Questa è Secondo::foo\n")
+ printf("Questa è Secondo::foo\n");
}
}
@@ -805,6 +806,94 @@ void faiQualcosaConUnFile(const std::string& nomefile)
// sono tutti automaticamente distrutti con i loro contenuti quando escono dalla visibilità.
// - I mutex usano lock_guard e unique_lock
+// I contenitori che utilizzano chiavi non-primitive (classi personalizzate)
+// richiedono la funzione di confronto nell'oggetto stesso, o tramite un puntatore a funzione.
+// Le chiavi primitive hanno funzioni di confronto già definite, ma puoi sovrascriverle.
+class Foo {
+public:
+ int j;
+ Foo(int a) : j(a) {}
+};
+struct funzioneDiConfronto {
+ bool operator()(const Foo& a, const Foo& b) const {
+ return a.j < b.j;
+ }
+};
+// Questo non è permesso, anche se qualche compilatore potrebbe non dare problemi
+//std::map<Foo, int> fooMap;
+std::map<Foo, int, funzioneDiConfronto> fooMap;
+fooMap[Foo(1)] = 1;
+fooMap.find(Foo(1)); -- vero
+
+///////////////////////////////////////
+// Espressioni Lambda (C++11 e superiori)
+///////////////////////////////////////
+
+// Le espressioni lambda (più semplicemente "lambda") sono utilizzate
+// per definire una funzione anonima nel punto in cui viene invocata, o
+// dove viene passata come argomento ad una funzione
+
+// Ad esempio, consideriamo l'ordinamento di un vettore costituito da una
+// coppia di interi, utilizzando il secondo elemento per confrontare
+vector<pair<int, int> > tester;
+tester.push_back(make_pair(3, 6));
+tester.push_back(make_pair(1, 9));
+tester.push_back(make_pair(5, 0));
+
+// Passiamo una lambda come terzo argomento alla funzione di ordinamento
+// `sort` è contenuta nell'header <algorithm>
+sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
+ return lhs.second < rhs.second;
+});
+
+// Nota bene la sintassi utilizzata nelle lambda:
+// [] serve per "catturare" le variabili.
+// La "Lista di Cattura" definisce tutte le variabili esterne che devono essere disponibili
+// all'interno della funzione, e in che modo.
+// La lista può contenere:
+// 1. un valore: [x]
+// 2. un riferimento: [&x]
+// 3. qualunque variabile nello scope corrente, per riferimento [&]
+// 4. qualunque variabile nello scope corrente, per valore [=]
+// Esempio:
+
+vector<int> id_cani;
+// numero_cani = 3;
+for(int i = 0; i < 3; i++) {
+ id_cani.push_back(i);
+}
+
+int pesi[3] = {30, 50, 10};
+
+// Mettiamo che vuoi ordinare id_cani in base al peso dei cani
+// Alla fine, id_cani sarà: [2, 0, 1]
+
+// Le lambda vengono in aiuto
+
+sort(id_cani.begin(), id_cani.end(), [&pesi](const int &lhs, const int &rhs) {
+ return pesi[lhs] < pesi[rhs];
+});
+// Nota come abbiamo catturato "pesi" per riferimento nell'esempio.
+// Altre informazioni sulle lambda in C++: http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
+
+///////////////////////////////
+// Ciclo For semplificato(C++11 e superiori)
+///////////////////////////////
+
+// Puoi usare un ciclo for per iterare su un tipo di dato contenitore
+int arr[] = {1, 10, 3};
+
+for(int elem: arr) {
+ cout << elem << endl;
+}
+
+// Puoi usare "auto" senza preoccuparti del tipo degli elementi nel contenitore
+// Ad esempio:
+
+for(auto elem: arr) {
+ // Fai qualcosa con `elem`
+}
+
///////////////////////
// Roba divertente
//////////////////////
@@ -855,20 +944,188 @@ Foo f1;
f1 = f2;
-// Come deallocare realmente le risorse all'interno di un vettore:
-class Foo { ... };
-vector<Foo> v;
-for (int i = 0; i < 10; ++i)
- v.push_back(Foo());
+///////////////////////////////////////
+// Tuple (C++11 e superiori)
+///////////////////////////////////////
+
+#include<tuple>
+
+// Concettualmente le tuple sono simili alle strutture del C, ma invece di avere
+// i membri rappresentati con dei nomi, l'accesso agli elementi avviene tramite
+// il loro ordine all'interno della tupla.
+
+// Cominciamo costruendo una tupla.
+// Inserire i valori in una tupla
+auto prima = make_tuple(10, 'A');
+const int maxN = 1e9;
+const int maxL = 15;
+auto seconda = make_tuple(maxN, maxL);
+
+// Vediamo gli elementi contenuti nella tupla "prima"
+cout << get<0>(prima) << " " << get<1>(prima) << "\n"; // stampa : 10 A
+
+// Vediamo gli elementi contenuti nella tupla "seconda"
+cout << get<0>(seconda) << " " << get<1>(seconda) << "\n"; // stampa: 1000000000 15
+
+// Estrarre i valori dalla tupla, salvandoli nelle variabili
+int primo_intero;
+char primo_char;
+tie(primo_intero, primo_char) = prima;
+cout << primo_intero << " " << primo_char << "\n"; // stampa : 10 A
+
+// E' possibile creare tuple anche in questo modo
+tuple<int, char, double> terza(11, 'A', 3.14141);
+
+// tuple_size ritorna il numero di elementi in una tupla (come constexpr)
+cout << tuple_size<decltype(terza)>::value << "\n"; // stampa: 3
+
+// tuple_cat concatena gli elementi di tutte le tuple, nell'esatto ordine
+// in cui sono posizionati all'interno delle tuple stesse
+auto tupla_concatenata = tuple_cat(prima, seconda, terza);
+// tupla_concatenata diventa = (10, 'A', 1e9, 15, 11, 'A' ,3.14141)
+
+cout << get<0>(tupla_concatenata) << "\n"; // stampa: 10
+cout << get<3>(tupla_concatenata) << "\n"; // stampa: 15
+cout << get<5>(tupla_concatenata) << "\n"; // stampa: 'A'
+
+
+/////////////////////
+// Contenitori
+/////////////////////
+
+// I Contenitori della "Standard Template Library", ovvero la libreria standard
+// dei template contenuti nel C++, sono template predefiniti.
+// I Contenitori si occupano di come allocare lo spazio per gli elementi contenuti,
+// e forniscono funzioni per accedervi e manipolarli
+
+// Vediamo alcuni tipi di contenitori:
+
+// Vector (array dinamici/vettori)
+// Permettono di definire un vettore, o una lista di oggetti, a runtime
+#include<vector>
+vector<Tipo_Dato> nome_vettore; // usato per inizializzare un vettore
+cin >> val;
+nome_vettore.push_back(val); // inserisce il valore di "val" nel vettore
+
+// Per iterare in un vettore, abbiamo due possibilità:
+// Ciclo normale
+for(int i=0; i<nome_vettore.size(); i++)
+// Cicla dall'indice zero fino all'ultimo
+
+// Iteratore
+vector<Tipo_Dato>::iterator it; // inizializza l'iteratore per il vettore
+for(it=nome_vettore.begin(); it!=nome_vettore.end();++it)
+// Nota che adesso non cicla più sugli indici, ma direttamente sugli elementi!
+
+// Per accedere agli elementi del vettore
+// Operatore []
+var = nome_vettore[indice]; // Assegna a "var" il valore del vettore all'indice dato
+
+
+// Set (insiemi)
+// Gli insiemi sono contenitori che memorizzano elementi secondo uno specifico ordine.
+// Gli insiemi vengono per lo più utilizzati per memorizzare valori unici, secondo
+// un ordine, senza scrivere ulteriore codice.
+
+#include<set>
+set<int> insieme; // Inizializza un insieme di interi
+insieme.insert(30); // Inserisce il valore 30 nell'insieme
+insieme.insert(10); // Inserisce il valore 10 nell'insieme
+insieme.insert(20); // Inserisce il valore 20 nell'insieme
+insieme.insert(30); // Inserisce il valore 30 nell'insieme
+// Gli elementi dell'insieme sono:
+// 10 20 30
+
+// Per cancellare un elemento
+insieme.erase(20); // Cancella l'elemento con valore 20
+// L'insieme contiene adesso: 10 30
+
+// Per iterare su un insieme, usiamo gli iteratori
+set<int>::iterator it;
+for(it=insieme.begin();it<insieme.end();it++) {
+ cout << *it << endl;
+}
+// Stampa:
+// 10
+// 30
+
+// Per svuotare il contenitore usiamo il metodo "clear"
+insieme.clear();
+cout << insieme.size();
+// Stampa: 0
+
+// Nota: per permettere elementi duplicati, possiamo usare "multiset"
+
+// Map (mappa/tabella di hash)
+// Le mappe servono per memorizzare un elemento, detto chiave, a cui viene
+// associato un valore, il tutto secondo uno specifico ordine.
+
+#include<map>
+map<char, int> mia_mappa; // Inizializza una mappa che usa i char come chiave, e gli interi come valore
+
+mia_mappa.insert(pair<char,int>('A',1));
+// Inserisce il valore 1 per la chiave A
+mia_mappa.insert(pair<char,int>('Z',26));
+// Inserisce il valore 26 per la chiave Z
+
+// Per iterare
+map<char,int>::iterator it;
+for (it=mia_mappa.begin(); it!=mia_mappa.end(); ++it)
+ std::cout << it->first << "->" << it->second << '\n';
+// Stampa:
+// A->1
+// Z->26
+
+// Per trovare il valore corrispondente ad una data chiave
+it = mia_mappa.find('Z');
+cout << it->second;
+// Stampa: 26
+
+
+///////////////////////////////////
+// Operatori logici e bitwise(bit-a-bit)
+//////////////////////////////////
+
+// La maggior parte di questi operatori in C++ sono gli stessi degli altri linguaggi
+
+// Operatori logici
+
+// Il C++ usa la "Short-circuit evaluation" per le espressioni booleane. Cosa significa?
+// In pratica, in una condizione con due argomenti, il secondo viene considerato solo se
+// il primo non basta a determinate il valore finale dell'espresione.
+
+true && false // Effettua il **and logico** e ritorna falso
+true || false // Effettua il **or logico** e ritorna vero
+! true // Effettua il **not logico** e ritorna falso
+
+// Invece di usare i simboli, si possono usare le keyword equivalenti
+true and false // Effettua il **and logico** e ritorna falso
+true or false // Effettua il **or logico** e ritorna vero
+not true // Effettua il **not logico** e ritorna falso
+
+// Operatori bitwise(bit-a-bit)
+
+// **<<** Operatore di Shift a Sinistra
+// << sposta i bit a sinistra
+4 << 1 // Sposta a sinistra di 1 i bit di 4, ottenendo 8
+// x << n in pratica realizza x * 2^n
+
+
+// **>>** Operatore di Shift a Destra
+// >> sposta i bit a destra
+4 >> 1 // Sposta a destra di 1 i bit di 4, ottenendo 2
+// x >> n in pratica realizza x / 2^n
-// La riga seguente riduce la dimensione di v a 0, ma il distruttore non
-// viene chiamato e dunque le risorse non sono deallocate!
-v.empty();
-v.push_back(Foo()); // Il nuovo valore viene copiato nel primo Foo che abbiamo inserito
+~4 // Effettua il NOT bit-a-bit
+4 | 3 // Effettua il OR bit-a-bit
+4 & 3 // Effettua il AND bit-a-bit
+4 ^ 3 // Effettua il XOR bit-a-bit
-// Distrugge realmente tutti i valori dentro v. Vedi la sezione riguardante gli
-// oggetti temporanei per capire come mai funziona così.
-v.swap(vector<Foo>());
+// Le keyword equivalenti sono
+compl 4 // Effettua il NOT bit-a-bit
+4 bitor 3 // Effettua il OR bit-a-bit
+4 bitand 3 // Effettua il AND bit-a-bit
+4 xor 3 // Effettua il XOR bit-a-bit
```
Letture consigliate:
diff --git a/it-it/python-it.html.markdown b/it-it/python-it.html.markdown
index 3a4099e7..71f6dc1c 100644
--- a/it-it/python-it.html.markdown
+++ b/it-it/python-it.html.markdown
@@ -4,9 +4,11 @@ contributors:
- ["Louie Dinh", "http://ldinh.ca"]
- ["Amin Bandali", "http://aminbandali.com"]
- ["Andre Polykanine", "https://github.com/Oire"]
+ - ["evuez", "http://github.com/evuez"]
filename: learnpython.py
translators:
- ["Ale46", "http://github.com/Ale46/"]
+ - ["Tommaso Pifferi", "http://github.com/neslinesli93/"]
lang: it-it
---
Python è stato creato da Guido Van Rossum agli inizi degli anni 90. Oggi è uno dei più popolari
@@ -15,8 +17,15 @@ pseudocodice eseguibile.
Feedback sono altamente apprezzati! Potete contattarmi su [@louiedinh](http://twitter.com/louiedinh) oppure [at] [google's email service]
-Nota: Questo articolo è valido solamente per Python 2.7, ma dovrebbe andar bene anche per
-Python 2.x. Per Python 3.x, dai un'occhiata a [Python 3 tutorial](http://learnxinyminutes.com/docs/python3/).
+Nota: questo articolo è riferito a Python 2.7 in modo specifico, ma dovrebbe andar
+bene anche per Python 2.x. Python 2.7 sta raggiungendo il "fine vita", ovvero non sarà
+più supportato nel 2020. Quindi è consigliato imparare Python utilizzando Python 3.
+Per maggiori informazioni su Python 3.x, dai un'occhiata al [tutorial di Python 3](http://learnxinyminutes.com/docs/python3/).
+
+E' possibile anche scrivere codice compatibile sia con Python 2.7 che con Python 3.x,
+utilizzando [il modulo `__future__`](https://docs.python.org/2/library/__future__.html) di Python.
+Il modulo `__future__` permette di scrivere codice in Python 3, che può essere eseguito
+utilizzando Python 2: cosa aspetti a vedere il tutorial di Python 3?
```python
@@ -54,6 +63,12 @@ Python 2.x. Per Python 3.x, dai un'occhiata a [Python 3 tutorial](http://learnxi
-5 // 3 # => -2
-5.0 // 3.0 # => -2.0
+# E' possibile importare il modulo "division" (vedi la sezione 6 di questa guida, Moduli)
+# per effettuare la divisione normale usando solo '/'.
+from __future__ import division
+11/4 # => 2.75 ...divisione normale
+11//4 # => 2 ...divisione troncata
+
# Operazione Modulo
7 % 3 # => 1
@@ -112,11 +127,19 @@ not False # => True
# Una stringa può essere considerata come una lista di caratteri
"Questa è una stringa"[0] # => 'Q'
-# % può essere usato per formattare le stringhe, in questo modo:
-"%s possono essere %s" % ("le stringhe", "interpolate")
+# Per sapere la lunghezza di una stringa
+len("Questa è una stringa") # => 20
+
+# Formattazione delle stringhe con %
+# Anche se l'operatore % per le stringe sarà deprecato con Python 3.1, e verrà rimosso
+# successivamente, può comunque essere utile sapere come funziona
+x = 'mela'
+y = 'limone'
+z = "La cesta contiene una %s e un %s" % (x,y)
# Un nuovo modo per fomattare le stringhe è il metodo format.
# Questo metodo è quello consigliato
+"{} è un {}".format("Questo", "test")
"{0} possono essere {1}".format("le stringhe", "formattate")
# Puoi usare delle parole chiave se non vuoi contare
"{nome} vuole mangiare {cibo}".format(nome="Bob", cibo="lasagna")
@@ -132,9 +155,17 @@ None is None # => True
# L'operatore 'is' testa l'identità di un oggetto. Questo non è
# molto utile quando non hai a che fare con valori primitivi, ma lo è
# quando hai a che fare con oggetti.
-
-# None, 0, e stringhe/liste vuote sono tutte considerate a False.
-# Tutti gli altri valori sono True
+
+# Qualunque oggetto può essere usato nei test booleani
+# I seguenti valori sono considerati falsi:
+# - None
+# - Lo zero, come qualunque tipo numerico (quindi 0, 0L, 0.0, 0.j)
+# - Sequenze vuote (come '', (), [])
+# - Contenitori vuoti (tipo {}, set())
+# - Istanze di classi definite dall'utente, che soddisfano certi criteri
+# vedi: https://docs.python.org/2/reference/datamodel.html#object.__nonzero__
+#
+# Tutti gli altri valori sono considerati veri: la funzione bool() usata su di loro, ritorna True.
bool(0) # => False
bool("") # => False
@@ -144,7 +175,13 @@ bool("") # => False
####################################################
# Python ha una funzione di stampa
-print "Sono Python. Piacere di conoscerti!"
+print "Sono Python. Piacere di conoscerti!" # => Sono Python. Piacere di conoscerti!
+
+# Un modo semplice per ricevere dati in input dalla riga di comando
+variabile_stringa_input = raw_input("Inserisci del testo: ") # Ritorna i dati letti come stringa
+variabile_input = input("Inserisci del testo: ") # Interpreta i dati letti come codice python
+# Attenzione: bisogna stare attenti quando si usa input()
+# Nota: In python 3, input() è deprecato, e raw_input() si chiama input()
# Non c'è bisogno di dichiarare una variabile per assegnarle un valore
una_variabile = 5 # Convenzionalmente si usa caratteri_minuscoli_con_underscores
@@ -155,6 +192,7 @@ una_variabile # => 5
un_altra_variabile # Genera un errore di nome
# if può essere usato come un'espressione
+# E' l'equivalente dell'operatore ternario in C
"yahoo!" if 3 > 2 else 2 # => "yahoo!"
# Liste immagazzinano sequenze
@@ -207,6 +245,17 @@ li + altra_li # => [1, 2, 3, 4, 5, 6]
# Concatena liste con "extend()"
li.extend(altra_li) # Ora li è [1, 2, 3, 4, 5, 6]
+# Rimuove la prima occorrenza di un elemento
+li.remove(2) # Ora li è [1, 3, 4, 5, 6]
+li.remove(2) # Emette un ValueError, poichè 2 non è contenuto nella lista
+
+# Inserisce un elemento all'indice specificato
+li.insert(1, 2) # li è di nuovo [1, 2, 3, 4, 5, 6]
+
+# Ritorna l'indice della prima occorrenza dell'elemento fornito
+li.index(2) # => 1
+li.index(7) # Emette un ValueError, poichè 7 non è contenuto nella lista
+
# Controlla l'esistenza di un valore in una lista con "in"
1 in li # => True
@@ -227,8 +276,9 @@ tup[:2] # => (1, 2)
# Puoi scompattare le tuple (o liste) in variabili
a, b, c = (1, 2, 3) # a è ora 1, b è ora 2 and c è ora 3
+d, e, f = 4, 5, 6 # puoi anche omettere le parentesi
# Le tuple sono create di default se non usi le parentesi
-d, e, f = 4, 5, 6
+g = 4, 5, 6 # => (4, 5, 6)
# Guarda come è facile scambiare due valori
e, d = d, e # d è ora 5 ed e è ora 4
@@ -250,6 +300,9 @@ filled_dict.keys() # => ["tre", "due", "uno"]
filled_dict.values() # => [3, 2, 1]
# Nota - Come sopra riguardo l'ordinamento delle chiavi.
+# Ottieni tutte le coppie chiave-valore, sotto forma di lista di tuple, utilizzando "items()"
+filled_dicts.items() # => [("uno", 1), ("due", 2), ("tre", 3)]
+
# Controlla l'esistenza delle chiavi in un dizionario con "in"
"uno" in filled_dict # => True
1 in filled_dict # => False
@@ -298,6 +351,15 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6}
# Fai differenze su set con -
{1, 2, 3, 4} - {2, 3, 5} # => {1, 4}
+# Effettua la differenza simmetrica con ^
+{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5}
+
+# Controlla se il set a sinistra contiene quello a destra
+{1, 2} >= {1, 2, 3} # => False
+
+# Controlla se il set a sinistra è un sottoinsieme di quello a destra
+{1, 2} <= {1, 2, 3} # => True
+
# Controlla l'esistenza in un set con in
2 in filled_set # => True
10 in filled_set # => False
@@ -405,7 +467,7 @@ aggiungi(y=6, x=5) # Le parole chiave come argomenti possono arrivare in ogni
# Puoi definire funzioni che accettano un numero variabile di argomenti posizionali
-# che verranno interpretati come tuple se non usi il *
+# che verranno interpretati come tuple usando il *
def varargs(*args):
return args
@@ -413,7 +475,7 @@ varargs(1, 2, 3) # => (1, 2, 3)
# Puoi definire funzioni che accettano un numero variabile di parole chiave
-# come argomento, che saranno interpretati come un dizionario se non usi **
+# come argomento, che saranno interpretati come un dizionario usando **
def keyword_args(**kwargs):
return kwargs
@@ -449,19 +511,19 @@ def pass_all_the_args(*args, **kwargs):
# Funzioni Scope
x = 5
-def setX(num):
+def set_x(num):
# La variabile locale x non è uguale alla variabile globale x
x = num # => 43
print x # => 43
-def setGlobalX(num):
+def set_global_x(num):
global x
print x # => 5
x = num # la variabile globable x è ora 6
print x # => 6
-setX(43)
-setGlobalX(6)
+set_x(43)
+set_global_x(6)
# Python ha funzioni di prima classe
def create_adder(x):
@@ -474,15 +536,22 @@ add_10(3) # => 13
# Ci sono anche funzioni anonime
(lambda x: x > 2)(3) # => True
+(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5
# Esse sono incluse in funzioni di alto livello
map(add_10, [1, 2, 3]) # => [11, 12, 13]
+map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3]
+
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7]
# Possiamo usare la comprensione delle liste per mappe e filtri
[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7]
+# Puoi fare anche la comprensione di set e dizionari
+{x for x in 'abcddeef' if x in 'abc'} # => {'d', 'e', 'f'}
+{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
+
####################################################
## 5. Classi
@@ -502,6 +571,9 @@ class Human(object):
# Assegna l'argomento all'attributo name dell'istanza
self.name = name
+ # Inizializza una proprietà
+ self.age = 0
+
# Un metodo dell'istanza. Tutti i metodi prendo "self" come primo argomento
def say(self, msg):
return "{0}: {1}".format(self.name, msg)
@@ -517,6 +589,21 @@ class Human(object):
def grunt():
return "*grunt*"
+ # Una proprietà è come un metodo getter.
+ # Trasforma il metodo age() in un attributo in sola lettura, che ha lo stesso nome
+ @property
+ def age(self):
+ return self._age
+
+ # Questo metodo permette di modificare la proprietà
+ @age.setter
+ def age(self, age):
+ self._age = age
+
+ # Questo metodo permette di cancellare la proprietà
+ @age.deleter
+ def age(self):
+ del self._age
# Instanziare una classe
i = Human(name="Ian")
@@ -536,6 +623,16 @@ j.get_species() # => "H. neanderthalensis"
# Chiamare il metodo condiviso
Human.grunt() # => "*grunt*"
+# Aggiorna la proprietà
+i.age = 42
+
+# Ritorna il valore della proprietà
+i.age # => 42
+
+# Cancella la proprietà
+del i.age
+i.age # => Emette un AttributeError
+
####################################################
## 6. Moduli
@@ -570,34 +667,67 @@ math.sqrt == m.sqrt == sqrt # => True
import math
dir(math)
+# Se nella cartella corrente hai uno script chiamato math.py,
+# Python caricherà quello invece del modulo math.
+# Questo succede perchè la cartella corrente ha priorità
+# sulle librerie standard di Python
+
####################################################
## 7. Avanzate
####################################################
-# I generatori ti aiutano a fare codice pigro
+# Generatori
+# Un generatore appunto "genera" valori solo quando vengono richiesti,
+# invece di memorizzarli tutti subito fin dall'inizio
+
+# Il metodo seguente (che NON è un generatore) raddoppia tutti i valori e li memorizza
+# dentro `double_arr`. Se gli oggetti iterabili sono grandi, il vettore risultato
+# potrebbe diventare enorme!
def double_numbers(iterable):
+ double_arr = []
+ for i in iterable:
+ double_arr.append(i + i)
+
+# Eseguendo il seguente codice, noi andiamo a raddoppiare prima tutti i valori, e poi
+# li ritorniamo tutti e andiamo a controllare la condizione
+for value in double_numbers(range(1000000)): # `test_senza_generatore`
+ print value
+ if value > 5:
+ break
+
+# Invece, potremmo usare un generatore per "generare" il valore raddoppiato non
+# appena viene richiesto
+def double_numbers_generator(iterable):
for i in iterable:
yield i + i
-# Un generatore crea valori al volo.
-# Invece di generare e ritornare tutti i valori in una volta ne crea uno in ciascuna
-# iterazione. Ciò significa che i valori più grandi di 15 non saranno considerati in
-# double_numbers.
-# Nota xrange è un generatore che fa la stessa cosa di range.
-# Creare una lista 1-900000000 occuperebbe molto tempo e spazio.
-# xrange crea un oggetto generatore xrange invece di creare l'intera lista
-# come fa range.
-# Usiamo un underscore finale nel nome delle variabile quando vogliamo usare un nome
-# che normalmente colliderebbe con una parola chiave di python
-xrange_ = xrange(1, 900000000)
-
-# raddoppierà tutti i numeri fino a che result >=30 non sarà trovato
-for i in double_numbers(xrange_):
- print i
- if i >= 30:
+# Utilizzando lo stesso test di prima, stavolta però con un generatore, ci permette
+# di iterare sui valori e raddoppiarli uno alla volta, non appena vengono richiesti dalla
+# logica del programma. Per questo, non appena troviamo un valore > 5, usciamo dal ciclo senza
+# bisogno di raddoppiare la maggior parte dei valori del range (MOLTO PIU VELOCE!)
+for value in double_numbers_generator(xrange(1000000)): # `test_generatore`
+ print value
+ if value > 5:
break
+# Nota: hai notato l'uso di `range` in `test_senza_generatore` e `xrange` in `test_generatore`?
+# Proprio come `double_numbers_generator` è la versione col generatore di `double_numbers`
+# Abbiamo `xrange` come versione col generatore di `range`
+# `range` ritorna un array di 1000000 elementi
+# `xrange` invece genera 1000000 valori quando lo richiediamo/iteriamo su di essi
+
+# Allo stesso modo della comprensione delle liste, puoi creare la comprensione
+# dei generatori.
+values = (-x for x in [1,2,3,4,5])
+for x in values:
+ print(x) # stampa -1 -2 -3 -4 -5
+
+# Puoi anche fare il cast diretto di una comprensione di generatori ad una lista.
+values = (-x for x in [1,2,3,4,5])
+gen_to_list = list(values)
+print(gen_to_list) # => [-1, -2, -3, -4, -5]
+
# Decoratori
# in questo esempio beg include say
@@ -605,7 +735,6 @@ for i in double_numbers(xrange_):
# ritornato
from functools import wraps
-
def beg(target_function):
@wraps(target_function)
def wrapper(*args, **kwargs):
@@ -634,11 +763,13 @@ print say(say_please=True) # Puoi comprarmi una birra? Per favore! Sono povero
* [Automate the Boring Stuff with Python](https://automatetheboringstuff.com)
* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
* [Dive Into Python](http://www.diveintopython.net/)
-* [The Official Docs](http://docs.python.org/2.6/)
+* [The Official Docs](http://docs.python.org/2/)
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
* [Python Module of the Week](http://pymotw.com/2/)
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
+* [LearnPython](http://www.learnpython.org/)
+* [Fullstack Python](https://www.fullstackpython.com/)
### Libri cartacei