|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
[Python] Classi, oggetti e self
Sto facendo un programma per gestire un'ipotetica biblioteca.
Ho un dubbio sulla parola chiave self: Uno sguardo a questo stralcio di codice: Codice:
class floor():
__closet=[]
__floorNumber=0
def __init__(self, closetNumber, n):
self.__floorNumber=n
self.__closet.append(closetNumber)
def addBook(self,bookObj,closetNumber,shelfNumber):
for i in range(len(self.__closet)):
if self.__closet[i].getClosetNumber()== closetNumber:
self.__closet[closetNumber].addBook(bookObj,shelfNumber)
EDIT: Una domanda ulteriore sull'import: ho letto in giro che l'import non funziona bene su sistemi Mac OS e Windows nel caso in cui si importi un modulo che ha un'importazione al suo interno, nello specifico: Codice:
from modulo import * È vero?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
Ultima modifica di kwb : 23-10-2012 alle 17:59. |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Apr 2010
Città: Leuven
Messaggi: 667
|
Quote:
__closet=[] e __floorNumber=0 come l'hai create tu non sono variabili di istanza ma di classe (come se in Java tu ci avessi messo davanti static). Per renderle variabili di istanza cancella la dichiarazione fuori dall'__init__. self. va apposto a tutte le variabili di istanza e a tutti i metodi che richiami nella classe ed è il puntatore all'istanza specifica. Non ho mai avuto problemi con from modulo import *, sia su linux che su windows, sei sicuro che non sia un bug di qualche versione precedente alla 2.7.3?
__________________
L'elettronica digitale non esiste, è solo elettrotecnica con interruttori piccoli!
|
|
|
|
|
|
|
#3 | ||||
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Quote:
Quote:
Una cosa che mi aspettavo di poter fare era la seguente: nel main importo il modulo floor ( from floor import * ) e se dentro floor ho già importato altri moduli, mi aspettavo di poterli usare anche dal main, ma non è così... Quote:
Codice:
private int n; Da quel che mi hai detto, ho capito che le variabili le dichiaro private solo dentro il costruttore ( anche se, è vero, non esiste una vera e propria dichiarazione delle variabili in python ) Quote:
Non funziona come il this. di java?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
||||
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Jul 2009
Messaggi: 72
|
Fai un pò di confusione, il this in Java veniva usato per richiamare un attributo/variabile (chiamala come vuoi) d'istanza, stessa cosa qui vale per il self. Servono esattamente alla stessa cosa.
La differenza è che in Java esistono i modificatori d'accesso, private ecc, cosa che in Python non c'è. Porre un _ d'avanti ad una variabile serve a far vedere agli altri, per convenzione, che quell'attributo è privato e quindi non dovrebbero accedervi direttamente (senza metodo get/set per capirci) e se lo fanno è a loro rischio e pericolo. Come ti hanno scritto sotto quello che dovresti fare è mettere i tuoi attributi d'istanza nel Costruttore, ponendo un _ prima di quelli che vuoi indicare come privati. Fuori invece metti le variabili di classe, costanti, che infatti anche in Java si inizializzano fuori dal costruttore. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Esattamente, il _ davanti è per lo più una convenzione: "è roba mia, interna, per favore non toccarla". Ma nessuno t'impedisce di metterci le mani, perché non esiste nella maniera più assoluta il concetto di privato, protetto, pubblico.
Ma attenzione quando si importa tutto da un modulo con la sintassi from Modulo import *. In questo caso Python non importa tutti gli identificatori del modulo, ma soltanto quelli che NON iniziano con _. In pratica chi ha realizzato il modulo può decidere cosa far importare automaticamente e cosa no; un meccanismo più fine è rappresentato dall'uso della variabile __all__ . Ovviamente non c'è alcun problema coi moduli rispetto al s.o. su cui gira Python. Riguardo a self & this, anche qui ci sono differenze con gli altri linguaggi. All'interno di una funzione definita in una classe (che diventa un metodo a tutti gli effetti, se non viene "decorata" opportunamente per farla diventare metodo di classe o funzione statica; ma di questo non ne parliamo per ora), qualunque assegnazione produce una variabile locale alla funzione. Se vogliamo creare, modificare, o semplicemente accedere a una variabile d'istanza, bisogna sempre utilizzare self.Variabile. Non è come negli altri linguaggi a oggetti, dove il self/this è implicitamente sempre presente; qui è obbligatorio, perché fa fede il motto di Python (explicit is better than implicit). E' noioso scrivere sempre self.? Può darsi, ma il codice è più leggibile. Ciò detto, se il problema è il morbo dello scrivano, si può usare un qualunque altro identificatore al posto di self: Codice:
class c:
def m(s):
s.VariabileDIstanza = 'Hello!'
__________________
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 |
|
|
|
|
|
#6 | ||||
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Quote:
Quindi la domanda è: un programmatore che scrive in Python, come le deve gestire le variabili che dichiara di una classe? Quote:
Quote:
Quote:
Se così fosse andremmo moooolto meglio
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
||||
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
1) dimenticare le idiosincrasie di altri linguaggi che già conosci; 2) rispettare le convenzioni e gli idiomi del nuovo linguaggio; 3) cercarne di capire le ragioni (col tempo & esperienza). Ho trovato questo atteggiamento molto utile.
__________________
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) Ultima modifica di banryu79 : 24-10-2012 alle 10:27. |
|
|
|
|
|
|
#8 | ||||||
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Quote:
Quote:
- nell'__init__ se serve che siano sempre inizializzate, magari con valori di default; - all'interno di altri metodi. Non siamo forzati a impostare le variabili d'istanza per forza nel costruttore, insomma. Lo facciamo quando lo riteniamo più opportuno. In altri casi è possibile definire delle property, Delphi/C# like per intenderci, e quindi controllare l'accesso di una variabile d'istanza tramite getter e/o setter e/o deleter. Quote:
Quote:
Codice:
Modulo._NonSonoInvisibile = True Codice:
from Modulo import _NonSonoInvisibile _NonSonoInvisibile = True Quote:
Siamo una setta di integralisti votati alla leggibilità del sorgente. ![]() 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: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Ho provato un po' a giocare con queste cose. Ma non ho ben afferrato come sono riuscito ( e se ci sono riuscito ) a fare una lista di oggetti ( 2 ) che contenesse un'altra lista di oggetti.
Ad esempio, il main: Codice:
from floor import *
from book import *
#Initialize the array
piano=[]
for i in range(2): #Use 2 floors
tempFloor=floor(0,i)
piano.append(tempFloor)
libroProva = book("Isaac Asimov","Cronache della Galassia")
#piano[0].addBook(book,1,1)
Su ogni piano della biblioteca ci devono essere un tot di armadi ( il cui numero è ancora da definire ), e poi per ogni armadio ci dovranno essere scaffali ecc... ( ma ancora non ci sono arrivato ). Quello che ho fatto è stato creare una lista piano. Tramite il for creo degli oggetti piano temporanei ( tempFloor ) che inserisco dentro la lista piano. Ora la classe floor: Codice:
class floor():
def __init__(self, closetNumber, n):
self._closet=[]
self._closet.append(closetNumber)
self._floorNumber=n
def addBook(self,bookObj,closetNumber,shelfNumber):
for i in range(len(self._closet)):
if self._closet[i].getClosetNumber()== closetNumber:
return self._closet[closetNumber].addBook(bookObj,shelfNumber)
return False
Tuttavia, mi aspettavo che scrivendo: Codice:
def __init__(self, closetNumber, n):
self._closet.append(closetNumber)
self._floorNumber=n
![]() Premesso che _closet è una lista di numeri ( poi lo trasformerò in oggetto, tramite la sua classe ), sono riuscito a creare la seguente struttura ( che dura fino alla fine dell'esecuzione del programma )? Codice:
piano[0]: closet[0] piano[1]: closet[0]
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
Ultima modifica di kwb : 24-10-2012 alle 13:08. |
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Apr 2010
Città: Leuven
Messaggi: 667
|
Se ci scrivi il testo dell'esercizio per come lo hai concepito proviamo a farlo e poi ci scambiamo i sorgenti completi.
ti va?
__________________
L'elettronica digitale non esiste, è solo elettrotecnica con interruttori piccoli!
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
La biblioteca è composta da:
- 2 piani - Per ogni piano vi sono, diciamo, 5 armadi - Per ogni armadio vi sono 5 scaffali - Per ogni ripiano ci sono 10 libri Dal main si chiama il metodo addBook che aggiunge l'oggetto book alla libreria, nella posizione indicata dai parametri ( specificando il piano ): Codice:
piano[0].addBook(oggetto_Book,NumeroArmadio,NumeroMensola) floor, closet e shelf. Vi è una classe aggiuntiva, book che contiene, oltre al titlo e l'autore ( inizializzati tramite costruttore alla creazione dell'oggetto libro ) anche i metodi set/get per impostare il piano/armadio/scaffale a cui si trova e l'anno di pubblicazione del libro.
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Altro consiglio (non richiesto, lo so) spassionato:
Scrivi il sorgente (i nomi delle variabili e dei tipi custom) in una sola lingua, o inglese o italiano o altro (la regola sarebbe usare la ingua franca dell'informatica: l'inglese). Altrimenti
__________________
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) |
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Quote:
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Questa non l'ho capita..
__________________
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) |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Nel senso che poi magari mi confondo e invece di scrivere il nome della variabili, scrivo il nome della classe ( che magari si chiamano simili ).
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Tipo: i nomi delle classi iniziano in maiuscolo, i campi delle istanze in minuscolo. Floor è la classe, floor il campo. Closet è la classe, closet il campo, ecc... Comunque nessuno ti vieta di fare qual cavolo che vuoi eh, il mio era solo un consiglio
__________________
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) |
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Ho seguito il tuo suggerimento e ho fatto così.
Ora però, alle prese con la creazione della biblioteca vuota ( senza libri ), mi da un errore, dentro il file Closet.py Codice:
self._shelf[i].append(dummyS) IndexError: list index out of range Main.py: Codice:
from Floor import *
from Book import *
#Initialize the array
floor=[]
for i in range(2): #Use 2 floors
tempFloor=Floor(i)
floor.append(tempFloor)
Codice:
from Closet import *
class Floor():
floorNumber =0
def __init__(self, n):
self._closet=[]
for i in range(5): #Create 5 closets
dummyC=Closet(i)
self._closet[i].append(dummyC)
self.floorNumber=n
Codice:
from Shelf import *
class Closet():
closetNumber=0
def __init__(self, closetNumber):
self.closetNumber=closetNumber
self._shelf=[]
for i in range(5): #Create 5 shelves
dummyS=Shelf(i)
self._shelf[i].append(dummyS)
Codice:
class Shelf():
shelfNumber=0
book=[]
def __init__(self, shelfNumber):
self.shelfNumber=shelfNumber
Inoltre, è giusto come ho gestito le variabili?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Ci sono diversi errori. Il primo è che hai dichiarato floorNumber, closetNumber, shelfNumber, e (soprattutto!) book come variabili di classe, quando è chiaro che dovrebbero essere d'istanza, per l'uso che ne fai. Quindi ti basta eliminare l'assegnazione a zero (e lista vuota per l'ultimo) che nei fai all'interno della definizione della classe.
Quello che ti crea problemi, comunque, è il fatto che accedi a un elemento della lista quando ancora non gliel'hai inserito con append. Infatti per popolare la lista al posto di questo: Codice:
self._closet[i].append(dummyC) Codice:
self._closet.append(dummyC) Infatti tu hai creato una lista vuota con self._closet = [] , ma... devi ancora popolarla. E lo fai col metodo append, ma devi applicarlo a self._closet, perché è questa lista, mentre self._closet[i] non è una lista (potrebbe anche esserlo, eh!) ma un suo elementi, che nello specifico è un'istanza di Closet. Un'ottimizzazione che potresti fare è quella di eliminare l'uso delle variabili temporanee. Un esempio: Codice:
for i in range(2): #Use 2 floors
floor.append(Floor(i))
Codice:
floor = [Floor(i) for i in range(2)] #Use 2 floors
__________________
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 Ultima modifica di cdimauro : 25-10-2012 alle 05:22. |
|
|
|
|
|
#19 | |||
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Allora, non riesco ancora ad afferrare la differenza tra variabile di classe e d'istanza.
A livello di allocazione di memoria ed accesso alla variabile ( perchè credo che la differenza sia in quello ), cosa cambia? Non sono riuscito a trovare qualcosa che lo spiegasse chiaramente, nemmeno il tutorial sul sito di python lo spiega... Da quello che ho capito io la variabile di istanza esiste ( e lo spazio in memoria per essa viene allocato ) quando creo l'oggetto ( ovvero con un Floor(i) ad esempio ) e dura fino alla deallocazione in memoria dell'oggetto. Ma la variabile di classe? Quote:
Quote:
Quote:
Mi pare di capire che essenzialmente ciò che vuoi far fare in seguito ad un condizione lo metti prima e dopo metti la/e condizione/i. Poi la teoria è sempre diversa dalla pratica
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|||
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Ho aggiustato un po' e ora almeno stampa qualcosa.
Tuttavia, come faccio a creare lo spazio di memoria per l'oggetto book ( creare una lista lunga 10 book, dentro shelf ) senza però dover assegnare i valori ( perchè lo farò tramite il metodo addBook )?
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 18:35.






















