|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Dec 2007
Città: .......
Messaggi: 188
|
[Python] - Definizione di classi
Sto leggendo il capitolo sulle classi e mi è sorto un dubbio...il libro per definire una classe procede nel seguente modo
Codice:
class punto: pass Codice:
p1 = punto() p1.x=4.0 ...... Non si può quindi fare una cosa del tipo: Codice:
class punto: p1 = punto() p1.x=4.0 ...........
__________________
------------------------------------------------------------------------------------------------------------ Intel Core 2 Duo 2.66Ghz - 3gb Ram - Hard Disk 250gb - Scheda Video: GeForce 8500 Gt da 512mb - Windows Xp Pro SP3 IPHONE 3GS 16GB BLACK MACBOOK PRO 15,4" 2.40GHz - 4GB RAM 320GB HD ------------------------------------------------------------------------------------------------------------ |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Quote:
Se vuoi settare delle variabili di classe, puoi fare così: Codice:
class punto: x = 4.0 y = 5.0 Se vuoi aggiungere invece degli attributi di istanza, fai così: Codice:
class punto:
def __init__(self):
self.x = 4.0
p1 = punto()
print p1.x
Ma ne puoi fare a meno, se non sono necessari. Io per una questione di leggibilità generalmente li specifico sempre come nei due esempi che ho riportato.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
siccome in Java è possibile una definizione ricorsiva di una classe (cioè è possibile definire una classe avente come membro un'istanza di sè stessa), quale caratteristica del linguaggio permette a Java questo comportamento e lo vieta in python?
grazie per l'aiuto |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
In Python non puoi istanziare immediatamente la classe mentre è in corso la sua definizione, come nell'esempio precedente:
Codice:
class punto: p1 = punto() p1.x=4.0 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in punto NameError: name 'punto' is not defined Codice:
class punto:
def MySelf(self):
return punto
>>> p = punto()
>>> p.MySelf()
<class __main__.punto at 0x027E3CF0>
>>> punto
<class __main__.punto at 0x027E3CF0>
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
ah ok, mi pareva una limitazione eccessiva, infatti... ma perché all'interno di un metodo è concessa mentre è vietata a livello di membri?
|
|
|
|
|
|
#6 |
|
Member
Iscritto dal: Dec 2007
Città: .......
Messaggi: 188
|
Esercizio:
scrivi una funzione chiamata MuoviRettangolo che prende come parametri un Rettangolo e due valori dx e dy. La funzione deve spostare le coordinate del punto in alto a sinistra sommando alla posizione x il valore dx e alla posizione y il valore dy. Codice:
class Rettangolo: pass #a,b,c,d sarebbero i nomi dei punti che compongono il rettangolo R=Rettangolo() R.ax=1.0 R.ay=2.0 R.bx=3.0 R.by=4.0 ....... ....... def Muovirettangolo(Rettangolo,dx,dy): R.ax=R.ax+dx R.ay=R.ay+dy print R.ax, R.ay
__________________
------------------------------------------------------------------------------------------------------------ Intel Core 2 Duo 2.66Ghz - 3gb Ram - Hard Disk 250gb - Scheda Video: GeForce 8500 Gt da 512mb - Windows Xp Pro SP3 IPHONE 3GS 16GB BLACK MACBOOK PRO 15,4" 2.40GHz - 4GB RAM 320GB HD ------------------------------------------------------------------------------------------------------------ |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
1] visto che sposti le coordinate del punto in alto a sinistra (ax, ay) di una certa quantità (dx, dy) devi poi aggiornare anche le coordinate del secondo punto (bx, by).
Secondo me potresti definire rettangolo tramite il punto in alto a sinistra (ax, ay) e due valori (larghezza, altezza), invece di specificare il secondo punto (bx, by). In questo modo poi aggiungerei un metodo che sulla base dei valori dei membri così definiti di rettangolo calcoli il suo secondo punto. 2] per stampare il valore dei due punti del rettangolo farei un metodo a parte che fa solo quello.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#8 | ||
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Quote:
Tornando all'esempio di prima: Codice:
class punto: x = 4.0 y = 5.0 Quindi sa che deve creare un oggetto (perché la classe punto è a tutti gli effetti un oggetto; in Python qualunque cosa è un oggetto) che dovrà chiamare punto e dovrà inserirlo nel namespace dello scope attuale (nel caso in questione si tratta del global scope del modulo in cui ha incontrato questa istruzione) e comincia a eseguirne il codice. All'inizio crea un nuovo oggetto di tipo classe (o type, che è uguale; non c'è differenza fra tipi e classi in Python, perché entrambi permettono di creare nuove istanze di "se stessi"), lo chiama internamente "punto" (il binding con lo scope attuale si verifica soltanto alla fine dell'istruzione class) e imposta come scope quello della classe (quindi tutti i binding che ci saranno da adesso alla fine dell'istruzione riguarderanno il name space dell'oggetto "punto"). Poi continua e incontra l'istruzione x = 4.0. La esegue. Questa crea un oggetto float con valore 4.0 e crea anche una variabile di nome "x" nello scope attuale (che è quello dell'oggetto "punto"), assegnadoglielo. Idem per y = 5.0. Alla chiusura dell'istruzione class abbiamo che l'oggetto "punto" ha nel suo namespace due variabili ("x" e "y") coi rispettivi valori. Infine viene rimosso lo scope dell'istruzione class, tornando a quello precedente, al quale viene effettuato il binding a "punto". Per funzioni e metodi la situazione è la stessa: l'istruzione def non definisce una funzione o un metodo, ma si passa ad eseguire l'istruzione def. Codice:
class punto:
def __init__(self):
self.x = 4.0
Vengono poi annotati il numero e il tipo di parametri (se sono con valore di default oppure no), e infine viene semplicemente creato il bytecode delle istruzioni presenti dentro l'istruzione def. Quindi NON viene eseguito il codice di self.x = 4.0, soltanto generato il suo bytecode e memorizzato all'interno di "__init__". Alla fine viene effettuato il binding di "__init__" allo scope attuale, cioé quello di "punto". In buona sostanza, definire classi e funzioni in Python equivale a tutti gli effetti a eseguire del codice (a seconda del tipo di istruzione) e a creare sempre degli oggetti. In questo modo si spiega perché una variabile di classe NON può memorizzare istanze di sé stessa: perché in quel preciso momento nello scope non esiste nessuna variabile "punto" da poter istanziare, perché il binding, appunto, avviene alla fine. Un metodo può, invece, effettuare quest'operazione, perché nel momento in cui viene eseguito l'oggetto "punto" è stato già completamente definito, per cui è presente nello scope e, quindi, lo si può "chiamare" (ebbene sì: la creazione di un'istanza equivale, in Python, a una chiamata a funzione che restituisce un nuovo oggetto, ovviamente del tipo della classe). In alternativa si può potrebbe completare la creazione dell'oggetto "punto" e inizializzare poi le sue variabili di classe: Codice:
class punto: pass punto.p1 = punto() Quote:
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
||
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
ti ringrazio cdimauro, sei stato chiarissimo
|
|
|
|
|
|
#10 | |
|
Member
Iscritto dal: Dec 2007
Città: .......
Messaggi: 188
|
Quote:
__________________
------------------------------------------------------------------------------------------------------------ Intel Core 2 Duo 2.66Ghz - 3gb Ram - Hard Disk 250gb - Scheda Video: GeForce 8500 Gt da 512mb - Windows Xp Pro SP3 IPHONE 3GS 16GB BLACK MACBOOK PRO 15,4" 2.40GHz - 4GB RAM 320GB HD ------------------------------------------------------------------------------------------------------------ |
|
|
|
|
|
|
#11 | ||
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Grazie cdimauro per la chiara spiegazione, ho imparato qualcosa di nuovo (avevo immaginato si trattasse appunto del fatto che Python è un linguaggio dinamico, ma non conoscevo i dettagli del meccanismo, molto interessante).
Quote:
Ancora meglio, mi sembra un pleonasma includere nel nome dei metodi di Rettangolo il nome della classe, io cioè li chiamerei semplicemente "Muovi" e "Stampa". Quote:
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
||
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Grazie. Comunque non ho voluto allungare troppo il discorso, ma il comportamento di Python nella creazione di classi e funzioni è utilissimo quando poi si cominciano a usare le metaclassi (per le classi soltanto) e i decoratori (per entrambe).
Tanto per rendere l'idea del perché sia utile questo comportamento, supponiamo di voler loggare le chiamate a tutti i metodi di una classe. E' sufficiente creare una metaclasse, oppure un class decorator (disponibile a partire da Python 2.6) che verrà "applicata" all'istanza appena creata (quindi è terminata l'istruzione class, ma non è ancora stato effettuato il binding del suo nome nello scope) che "rovista" fra tutti i metodi della classe li sostituisce uno per uno con degli opportuni wrapper. Supponendo che Log sia una funzione che prende in input un elenco variabile di argomenti e li scriva su un file, e che logmethods sia un class decorator che esegue il lavoro di cui sopra, basta questo: Codice:
@logmethods(Log)
class Test:
def Somma(self, x, y):
return x + y
def Prodotto(self, x, y):
return x + y
Comunque si tratta di argomenti avanzati e anche un po' complicati, ma davvero molto utili una volta che sono entrati a far parte del proprio bagaglio culturale.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Ora non sono sicuro perchè non ho approfondito fino a questo punto, ma anche in SmallTalk si possono ottenere dei risultati simili in potenza a quello da te descritto, con la scusa che tutto è un oggetto, anche le classi stesse (ci sono le metaclassi).
Questo per dire che non è una novità ma fa certamente piacere sapere che in un linguaggio dinamico e recente (e suppongo anche più "di produzione" che SmallTalk) hanno incluso questa potenzialità.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Come giustamente hai riportato, il concetto di metaclasse non è affatto nuovo e infatti lo ritroviamo in SmallTalk.
Python però lo implementa in maniera diversa e con uno stile particolarmente semplice e funzionale (in tutti i sensi
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Però mi interesserebbe un piccolo confrontro per capire le diverse filosofie
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Mar 2007
Messaggi: 4683
|
Non ho capito un azz
__________________
Firma eliminata e avatar cambiato. Troppa gente giudica il monaco dall'abito. |
|
|
|
|
|
#17 | |
|
Senior Member
Iscritto dal: Mar 2007
Messaggi: 4683
|
Quote:
__________________
Firma eliminata e avatar cambiato. Troppa gente giudica il monaco dall'abito. |
|
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Certo, anzi, forse sarebbe meglio un metodo che faccia l'equivalente del toString() in Java.
Poi sarà il chiamante esterno a decidere se e dove stampare.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Mar 2007
Messaggi: 4683
|
Non è più comodo inserire un print quando serve?
__________________
Firma eliminata e avatar cambiato. Troppa gente giudica il monaco dall'abito. |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Mar 2007
Messaggi: 4683
|
Codice:
class Rettangolo:
pass
R = Rettangolo()
R.AltoSx = 00.0
R.AltoSy = 00.0
def MuoviRettangolo(Rettangolo, dx, dy):
SpostaSx = R.AltoSx + dx
SpostaSy = R.AltoSy + dy
return SpostaSx, SpostaSy
__________________
Firma eliminata e avatar cambiato. Troppa gente giudica il monaco dall'abito. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 21:33.




















