View Full Version : [Python] - Definizione di classi
88MIKI88
11-11-2008, 12:10
Sto leggendo il capitolo sulle classi e mi è sorto un dubbio...il libro per definire una classe procede nel seguente modo
class punto:
pass
e poi successivamente
p1 = punto()
p1.x=4.0
......
Con pass nn succede niente... invece l'istanzazione a l'inserimento degli attributi avviene solo in un secondo momento.
Non si può quindi fare una cosa del tipo:
class punto:
p1 = punto()
p1.x=4.0
...........
Plesase cdimauro / esperto in python datemi delle delucidazioni in merito....secondo me questo capitolo non è tanto chiaro xò boh
cdimauro
11-11-2008, 12:58
Sto leggendo il capitolo sulle classi e mi è sorto un dubbio...il libro per definire una classe procede nel seguente modo
class punto:
pass
e poi successivamente
p1 = punto()
p1.x=4.0
......
Con pass nn succede niente... invece l'istanzazione a l'inserimento degli attributi avviene solo in un secondo momento.
Non si può quindi fare una cosa del tipo:
class punto:
p1 = punto()
p1.x=4.0
...........
Plesase cdimauro / esperto in python datemi delle delucidazioni in merito....secondo me questo capitolo non è tanto chiaro xò boh
Con Python gli attributi a una classe o anche a una singola instanza li puoi aggiungere e togliere come e quando vuoi.
Se vuoi settare delle variabili di classe, puoi fare così:
class punto:
x = 4.0
y = 5.0
Il tuo esempio precedente non è corretto, perché la classe punto non è ancora stata definita.
Se vuoi aggiungere invece degli attributi di istanza, fai così:
class punto:
def __init__(self):
self.x = 4.0
p1 = punto()
print p1.x
Questi due esempi simulano quello che avviene con altri linguaggi orientati agli oggetti che hanno una tipizzazione statica e, quindi, richiedono di specificare sempre nella definizione della classe gli attribuiti di classe o d'istanza.
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.
mad_hhatter
11-11-2008, 13:55
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
cdimauro
11-11-2008, 19:37
In Python non puoi istanziare immediatamente la classe mentre è in corso la sua definizione, come nell'esempio precedente:
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
Puoi invece creare tutte le istanze che vuoi di se stessa all'interno dei suoi metodi:
class punto:
def MySelf(self):
return punto
>>> p = punto()
>>> p.MySelf()
<class __main__.punto at 0x027E3CF0>
>>> punto
<class __main__.punto at 0x027E3CF0>
Il comportamento come vedi è simile a quello degli altri linguaggi.
mad_hhatter
12-11-2008, 08:57
ah ok, mi pareva una limitazione eccessiva, infatti... ma perché all'interno di un metodo è concessa mentre è vietata a livello di membri?
88MIKI88
12-11-2008, 17:36
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.
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
Secondo voi può andare??
banryu79
13-11-2008, 07:37
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.
cdimauro
13-11-2008, 08:02
ah ok, mi pareva una limitazione eccessiva, infatti... ma perché all'interno di un metodo è concessa mentre è vietata a livello di membri?
Perché Python differisce dagli altri linguaggi di programmazione "statici" perché quando incontra una definizione di classe, in realtà non la definisce, ma la costruisce, cioé ne esegue il codice che incontra man mano.
Tornando all'esempio di prima:
class punto:
x = 4.0
y = 5.0
In questo caso abbiamo punto che ha due variabili di classe, x e y. Cosa fa Python quando incontra questo pezzo di sorgente? Ne... esegue il codice.
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.
class punto:
def __init__(self):
self.x = 4.0
In questo caso però è più semplice. Quando viene eseguita la def __init__ viene creato sempre un nuovo oggetto di tipo funzione a cui viene associato il nome "__init__" (il binding con lo scope attuale verrà effettuato alla fine, al solito).
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:
class punto:
pass
punto.p1 = punto()
E' molto diverso da ciò che avviene con gli altri linguaggi "statici" (d'altra parte Python non a caso è... dinamico :p), per cui non dovesse essere chiaro chiedi pure. :)
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.
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
Secondo voi può andare??
Sì, ma non basta (vedi banryu). Ma poi devi proprio stampare i valori dentro Muovirettangolo?
mad_hhatter
13-11-2008, 09:53
ti ringrazio cdimauro, sei stato chiarissimo
88MIKI88
13-11-2008, 12:11
Sì, ma non basta (vedi banryu). Ma poi devi proprio stampare i valori dentro Muovirettangolo?
La stampa l'ho messa io tanto x vedere se il programma funzionava...mmm ok forse ho capito come procedere diciamo che dopo aver cambiato le coordinate di A faccio partire una funzione che mi calcoli in automatico in base ai parametri che passerò il punto B (quello in alto a dx) giusto??
banryu79
13-11-2008, 12:55
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).
La stampa l'ho messa io tanto x vedere se il programma funzionava
Certo, solo non è molto logico farla fare dentro un metodo il cui scopo è "Muovirettangolo". Diciamo che sarebbe meglio dall'esterno chiamare "MuoviRettangolo" su un oggetto Rettangolo e subito dopo chiamare, per esempio, "Stamparettangolo".
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".
mmm ok forse ho capito come procedere diciamo che dopo aver cambiato le coordinate di A faccio partire una funzione che mi calcoli in automatico in base ai parametri che passerò il punto B (quello in alto a dx) giusto??
Esatto.
cdimauro
13-11-2008, 13:21
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:
@logmethods(Log)
class Test:
def Somma(self, x, y):
return x + y
def Prodotto(self, x, y):
return x + y
per loggare automaticamente tutte le chiamate a Somma e Prodotto (e volendo anche il loro risultato; a seconda di com'è implementato logmethods).
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. :)
banryu79
13-11-2008, 13:33
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à.
cdimauro
13-11-2008, 19:48
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 :D).
banryu79
14-11-2008, 08:51
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 :D).
Ti prendo in parola perchè in questo momento non posso andare a rivedermi l'implementazione delle metaclassi in SmallTalk, ho rogne più rognose in ufficio da sbrigare :(
Però mi interesserebbe un piccolo confrontro per capire le diverse filosofie :fagiano:
~FullSyst3m~
14-11-2008, 10:07
Non ho capito un azz :muro:
~FullSyst3m~
14-11-2008, 10:10
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.
Un metodo a parte solo per stampare un valore?
banryu79
14-11-2008, 10:13
Un metodo a parte solo per stampare un valore?
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.
~FullSyst3m~
14-11-2008, 10:44
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.
Non è più comodo inserire un print quando serve?
~FullSyst3m~
15-11-2008, 10:01
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
Io l'ho risolto cosi, ma vorrei capire cosa voleva dire banryu
~FullSyst3m~
15-11-2008, 10:10
class punto:
def __init__(self):
self.x = 4.0
p1 = punto()
print p1.x
class punto:
def MySelf(self):
return punto
>>> p = punto()
>>> p.MySelf()
<class __main__.punto at 0x027E3CF0>
>>> punto
<class __main__.punto at 0x027E3CF0>
Perchè nel primo codice chiami l'attributo soltanto e nell'alto invece appendi all'oggetto la funzione senza parametri se l'avevi definita con il parametro 'self'?
~FullSyst3m~
15-11-2008, 11:14
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.
Intendi qualcosa del genere?
class Rettangolo:
pass
R = Rettangolo()
R.AltoSx = 00.0
R.AltoSy = 00.0
R.Bx = 1.0
R.By = 2.0
def Muovi(Rettangolo, dx, dy, Altezza, Larghezza):
SpostaSx = R.AltoSx + dx
SpostaSy = R.AltoSy + dy
SpostaBx = R.Bx + Altezza
SpostaBy = R.By + Larghezza
return SpostaSx, SpostaSy, SpostaBx, SpostaBy
def Stampa (dati):
print dati
Stampa (Muovi (R, 30, 40, 50, 60))
banryu79
15-11-2008, 12:02
Intendi qualcosa del genere?
class Rettangolo:
pass
R = Rettangolo()
R.AltoSx = 00.0
R.AltoSy = 00.0
R.Bx = 1.0
R.By = 2.0
def Muovi(Rettangolo, dx, dy, Altezza, Larghezza):
SpostaSx = R.AltoSx + dx
SpostaSy = R.AltoSy + dy
SpostaBx = R.Bx + Altezza
SpostaBy = R.By + Larghezza
return SpostaSx, SpostaSy, SpostaBx, SpostaBy
def Stampa (dati):
print dati
Stampa (Muovi (R, 30, 40, 50, 60))
Non conosco Python, in Java avrei fatto pressapoco così:
public class MyRectangle
{
private Point2D upLeft = new Point2D(0.0, 0.0);
private double length = 0.0;
private double height = 0.0;
public MyRectangle(double l, double h)
{
length = l;
height = h;
}
public MyRectangle(Point2D position, double l, double h)
{
this(l, h);
upLeft = position;
}
public void muovi(double deltaX, double deltaY)
{
upLeft.muovi(deltaX, deltaY);
}
public Point2D upLeft()
{
return new Point2D(upLeft.x(), upLeft.y());
// oppure, a seconda dei gusti:
// return upLeft.clone();
// questo con lo scopo di non permettere modifiche
// esterne ai punti che definiscono il Rettangolo.
// Se invece si volesse tornare proprio il riferimento al punto
// per permettere modifiche allora basterrebbe tornare il
// riferimento stesso, così:
// return upLeft;
}
public Point2D downRight()
{
return new Point2D(upLeft.x() + deltaX, upLeft.y() + deltaY);
}
public Point2D upright()
{
return new Point2D(upLeft.x() + deltaX, upLeft.y());
}
public Point2D downLeft()
{
return new Point2D(upLeft.x(), upLeft.y() + deltaY);
}
public Point2D[] points()
{
Point2D[] points = new Point2D[4];
points[0] = upLeft();
points[1] = upRight();
points[2] = downRight();
points[3] = downLeft();
return points;
}
@Override
public void toString()
{
return new String("upLeft=" + upLeft.toString() + ", length=" + length + ", height=" + height);
}
}
la classe Punto2D:
public class Point2D
{
private double x;
private double y;
public Punto2D(double x, double y)
{
this.x = x;
this.y = y;
}
public void muovi(double deltaX, double deltaY)
{
x += deltaX;
y += deltaY;
}
@Override
public void toString()
{
return new String("@X" + x + ",Y" + y);
}
}
~FullSyst3m~
15-11-2008, 12:17
Non conosco Python, in Java avrei fatto pressapoco così:
public class MyRectangle
{
private Point2D upLeft = new Point2D(0.0, 0.0);
private double length = 0.0;
private double height = 0.0;
public MyRectangle(double l, double h)
{
length = l;
height = h;
}
public MyRectangle(Point2D position, double l, double h)
{
this(l, h);
upLeft = position;
}
public void muovi(double deltaX, double deltaY)
{
upLeft.muovi(deltaX, deltaY);
}
public Point2D upLeft()
{
return new Point2D(upLeft.x(), upLeft.y());
// oppure, a seconda dei gusti:
// return upLeft.clone();
// questo con lo scopo di non permettere modifiche
// esterne ai punti che definiscono il Rettangolo.
// Se invece si volesse tornare proprio il riferimento al punto
// per permettere modifiche allora basterrebbe tornare il
// riferimento stesso, così:
// return upLeft;
}
public Point2D downRight()
{
return new Point2D(upLeft.x() + deltaX, upLeft.y() + deltaY);
}
public Point2D upright()
{
return new Point2D(upLeft.x() + deltaX, upLeft.y());
}
public Point2D downLeft()
{
return new Point2D(upLeft.x(), upLeft.y() + deltaY);
}
public Point2D[] points()
{
Point2D[] points = new Point2D[4];
points[0] = upLeft();
points[1] = upRight();
points[2] = downRight();
points[3] = downLeft();
return points;
}
@Override
public void toString()
{
return new String("upLeft=" + upLeft.toString() + ", length=" + length + ", height=" + height);
}
}
la classe Punto2D:
public class Point2D
{
private double x;
private double y;
public Punto2D(double x, double y)
{
this.x = x;
this.y = y;
}
public void muovi(double deltaX, double deltaY)
{
x += deltaX;
y += deltaY;
}
@Override
public void toString()
{
return new String("@X" + x + ",Y" + y);
}
}
Ho la pasta nel piatto quindi ho solo visto che sono un sacco di righe di codice. Non credo proprio che l'esercizio voleva tutto questo. Anche se non conosci Python guarda il codice che ho scritto, mi sono basato su quello che hai detto a 88MIKI88
cdimauro
17-11-2008, 08:32
Ti prendo in parola perchè in questo momento non posso andare a rivedermi l'implementazione delle metaclassi in SmallTalk, ho rogne più rognose in ufficio da sbrigare :(
Però mi interesserebbe un piccolo confrontro per capire le diverse filosofie :fagiano:
Al momento ti passo questo: http://mail.python.org/pipermail/python-dev/2001-May/014508.html che è un messaggio della mailing list degli sviluppatori Python in cui Guido ha riportato un messaggio che gli è arrivato da chi ha creato le metaclassi in SmallTalk e che fa un confronto con Python.
banryu79
17-11-2008, 10:36
Al momento ti passo questo: http://mail.python.org/pipermail/python-dev/2001-May/014508.html che è un messaggio della mailing list degli sviluppatori Python in cui Guido ha riportato un messaggio che gli è arrivato da chi ha creato le metaclassi in SmallTalk e che fa un confronto con Python.
Grazie mille.
Ho la pasta nel piatto quindi ho solo visto che sono un sacco di righe di codice. Non credo proprio che l'esercizio voleva tutto questo.
Sì sono d'accordo su questo.
Ma volevo solo fornire un esempio che illustrasse perchè non occorre tenersi memorizzati i due punti che definiscono il rettangolo (infatti a cosa servirebbe? Se vuoi sapere anche gli altri due punti lasciati fuori, senza contare quanto è alto e quanto è largo il rettangolo, ti tocca comunque implementare metodi che ti calcolino tali valori) e che invece è più comodo definire un rettangolo tramite un unico punto e i due valori di larghezza e altezza.
In questo modo per traslare il rettangolo basta applicare la traslazione ad un solo punto: larghezza e altezza non cambiano.
Se vuoi modificare le dimensioni del rettangolo basta modificare altezza o larghezza, il singolo punto non cambia.
Certo poi se vuoi sapere le coordinate degli altri punti devi fare dei calcoli, ed è per illustrare questo che ho aggiunto i metodi per calcolare i punti del rettangolo [che tra la'ltro non sono propriamente soddisfacenti per varie ragioni], non per suggerirla come implementazione corretta all'utente che ha aperto il thread: certo avrei dovuto specificare meglio le mie ragioni, ma postavo da casa di miadre nel mio vecchio pc e a parte problemi di connessione (ogni tanto cade) avevo pure fretta...
~FullSyst3m~
17-11-2008, 12:35
Grazie mille.
Sì sono d'accordo su questo.
Ma volevo solo fornire un esempio che illustrasse perchè non occorre tenersi memorizzati i due punti che definiscono il rettangolo (infatti a cosa servirebbe? Se vuoi sapere anche gli altri due punti lasciati fuori, senza contare quanto è alto e quanto è largo il rettangolo, ti tocca comunque implementare metodi che ti calcolino tali valori) e che invece è più comodo definire un rettangolo tramite un unico punto e i due valori di larghezza e altezza.
In questo modo per traslare il rettangolo basta applicare la traslazione ad un solo punto: larghezza e altezza non cambiano.
Se vuoi modificare le dimensioni del rettangolo basta modificare altezza o larghezza, il singolo punto non cambia.
Certo poi se vuoi sapere le coordinate degli altri punti devi fare dei calcoli, ed è per illustrare questo che ho aggiunto i metodi per calcolare i punti del rettangolo [che tra la'ltro non sono propriamente soddisfacenti per varie ragioni], non per suggerirla come implementazione corretta all'utente che ha aperto il thread: certo avrei dovuto specificare meglio le mie ragioni, ma postavo da casa di miadre nel mio vecchio pc e a parte problemi di connessione (ogni tanto cade) avevo pure fretta...
No figurati, non ho detto che era per suggerirla come implementazione corretta per l'utente, anzi è stato un motivo di insegnamento il codice che hai postato. Io sinceramente ancora non ho capito bene cosa vuoi dire e non mi ci soffermo più di tanto visto che gli esercizi li ho fatti e il capitolo l'ho capito, cosi vado avanti. Però anche se non conosci Python dai un'occhiata al sorgente che è di facile comprensione, ho cercato di fare quello che hai detto tu (anche se sicuramente ho capito male) ;)
banryu79
17-11-2008, 13:04
...
Però anche se non conosci Python dai un'occhiata al sorgente che è di facile comprensione, ho cercato di fare quello che hai detto tu (anche se sicuramente ho capito male) ;)
Questo?
class Rettangolo:
pass
R = Rettangolo()
R.AltoSx = 00.0
R.AltoSy = 00.0
R.Bx = 1.0
R.By = 2.0
def Muovi(Rettangolo, dx, dy, Altezza, Larghezza):
SpostaSx = R.AltoSx + dx
SpostaSy = R.AltoSy + dy
SpostaBx = R.Bx + Altezza
SpostaBy = R.By + Larghezza
return SpostaSx, SpostaSy, SpostaBx, SpostaBy
def Stampa (dati):
print dati
Stampa (Muovi (R, 30, 40, 50, 60))
Quello che intendevo io era di definire come membri di Rettangolo tre attributi:
- punto iniziale (per esempio quello in alto a sinistra)
- altezza
- larghezza
Vedo nel tuo codice che hai definito un metodo Muovi a cui passi come argomenti anche la larghezza e l'altezza, e non era quello che stavo suggerendo.
Rifletti un attimo: se Muovi un Rettangolo cos'è che cambia nel Rettangolo?
Di certo non le sue dimensioni (larghezza e altezza), che anzi, non prendiamo neanche in considerazione.
Cambia invece la sua posizione. Come la esprimo la posizione di un Rettangolo? Ad esempio tramite le coordinate di uno dei suoi spigoli, che scegliamo arbitrariamente (diciamo quello in basso a snx, ipotizzando di trovarci in un sistema cartesiano orientato con l'asse delle X che cresce positivamente verso destra e l'asse delle Y che cresce positivamente verso l'alto, rispetto l'origine[X0,Y0]. Io nel mio esempio avevo scelto quello in alto a sinistra perchè mi stavo basando su un altro sitema di riferimento).
Quindi abbiamo detto che un Rettangolo può essere descritto dalla sua posizione e dalle sue dimensioni.
Potremmo dunque definirlo tramite tre attributi:
1) un Punto [posizione]
2) un valore per la Larghezza [dimensione]
3) un valore per l'Altezza [dimensione]
Questo partendo dal presupposto di voler definire una classe Rettangolo, e di dotarla di un metodo per "muoverlo".
Forse ho capito l'equivoco (mio): mi sono accorto adesso del fatto che l'esercizio non richiede di definire un metodo Muovi dentro la classe Rettangolo, ma chiede di definire un metodo Muovi che prende un Rettangolo tra gli argomenti e lo "muove". Errore mio, io fin'ora partivo dall'altro presupposto, chiedo scusa.
~FullSyst3m~
17-11-2008, 14:40
Questo?
class Rettangolo:
pass
R = Rettangolo()
R.AltoSx = 00.0
R.AltoSy = 00.0
R.Bx = 1.0
R.By = 2.0
def Muovi(Rettangolo, dx, dy, Altezza, Larghezza):
SpostaSx = R.AltoSx + dx
SpostaSy = R.AltoSy + dy
SpostaBx = R.Bx + Altezza
SpostaBy = R.By + Larghezza
return SpostaSx, SpostaSy, SpostaBx, SpostaBy
def Stampa (dati):
print dati
Stampa (Muovi (R, 30, 40, 50, 60))
Quello che intendevo io era di definire come membri di Rettangolo tre attributi:
- punto iniziale (per esempio quello in alto a sinistra)
- altezza
- larghezza
Vedo nel tuo codice che hai definito un metodo Muovi a cui passi come argomenti anche la larghezza e l'altezza, e non era quello che stavo suggerendo.
Rifletti un attimo: se Muovi un Rettangolo cos'è che cambia nel Rettangolo?
Di certo non le sue dimensioni (larghezza e altezza), che anzi, non prendiamo neanche in considerazione.
Cambia invece la sua posizione. Come la esprimo la posizione di un Rettangolo? Ad esempio tramite le coordinate di uno dei suoi spigoli, che scegliamo arbitrariamente (diciamo quello in basso a snx, ipotizzando di trovarci in un sistema cartesiano orientato con l'asse delle X che cresce positivamente verso destra e l'asse delle Y che cresce positivamente verso l'alto, rispetto l'origine[X0,Y0]. Io nel mio esempio avevo scelto quello in alto a sinistra perchè mi stavo basando su un altro sitema di riferimento).
Quindi abbiamo detto che un Rettangolo può essere descritto dalla sua posizione e dalle sue dimensioni.
Potremmo dunque definirlo tramite tre attributi:
1) un Punto [posizione]
2) un valore per la Larghezza [dimensione]
3) un valore per l'Altezza [dimensione]
Questo partendo dal presupposto di voler definire una classe Rettangolo, e di dotarla di un metodo per "muoverlo".
Forse ho capito l'equivoco (mio): mi sono accorto adesso del fatto che l'esercizio non richiede di definire un metodo Muovi dentro la classe Rettangolo, ma chiede di definire un metodo Muovi che prende un Rettangolo tra gli argomenti e lo "muove". Errore mio, io fin'ora partivo dall'altro presupposto, chiedo scusa.
Esatto, l'esercizio vuole una funzione (o metodo) che prende un oggetto Rettangolo ;)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.