Please ignore secret bonuses. Secret tests do NOT award bonus. Max hw grade is 30+2 bonus efficiency

Do you need help?

Dubbio lezione di martedì 17/11

twgever (17470 points)
8 29 105
in Programmare in Python by (17.5k points)

@classmethod

def load(cls, filename):

        img=images.load(filename)

        w=len(img[0])

        h=len(img)

        nuova=cls(w,h)

        nuova.img=[[Colore(*pixel) for pixel in line ] for line in img]

        return nuova

Innanzitutto, mi scusi se non ho allegato un'immagine e bensì ho dovuto riscrivere, ma è perché non sono riuscito ad allegarlaangry

Ora, il problema è che non capisco tutti i passaggi di questa funzione, elenco i passaggi.

-se il prof. non avesse aggiunto il decoratore classmethod, l'esecuzione avrebbe dato un errore, perchè una classe non è autorizzata "creare" altre istanze? (posso chiamare le istanze oggetti, o commetto un'eresia se lo faccio?)

-perchè usiamo questo metodo? non basta usare direttamente img? perchè risalviamo tutto il necessario in una nuova istanza e non usiamo direttamente img? Semmai fosse perchè modificherei il file originale, non basterebbe fare deepcopy allora?

-nella riga "nuova=cls(w,h)" che cosa succede di preciso? che cosa esegue di preciso questa istruzione?

-perchè nuova.img? significa che quello che fa il ciclo viene memorizzato nella lista img, che appartiene a nuova?

392 views
closed

2 Answers

Best answer
andrea.sterbini (207920 points)
750 1267 2373
by (208k points)
selected by
stiamo costruendo una nuova immagine che contiene liste di liste di Colore invece che di triple RGB

Quando carichiamo l'immagine da file dobbiamo quindi convertire le liste di liste di triple in liste di liste di Colore.

Il metodo è definito come classmethod perchè è come se volessimo avere a disposizione un nuovo tipo do costruttore che produce una immagine leggendola da file invece che creandola con dimensioni e sfondo fissato

In altri linguaggi è possibile avere costruttori multipli ma in Python no, per cui definendo un classmethod ottengo la stessa funzionalità

Al metodo viene passata la classe a cui appartiene come primo argomento, quindi
   nuova = cls(w,h)
costruisce un nuovo oggetto Immagine di dimensioni w,h e sfondo nero
poi l'istruzione
    nuova.img  = ...
serve a memorizzare nell'attributo img del nuovo oggetto la lista di liste di Colore
AdSum (16290 points)
9 20 134
by (16.3k points)
Allora sono un bel pò di domande, vedo quello che posso fare:

@classmethod è un decoratore che serve a trasformare un metodo da metodo di istanza a metodo di classe. Se hai familiriatà con altri linguaggi non è altro che renderlo statico.

Non so cosa intendi con "usare direttamente img" ma comunque usiamo questo metodo per avere un modo per caricare un file e creare l'oggetto da esso in automatico. Mettere questa funzione nel costruttore della classe stessa renderebbe impossibile la creazione manuale (senza file) e quindi lo renderebbe veramente poco pratico.

nuova=cls(w,h) non fa altro che creare un oggetto (nuova) di tipo cls (in questo caso Image se non sbaglio). La funzione cls() non è altro che il costruttore della classe stessa, quindi __init__()

nuova.img serve ad indicare che img appartiene a nuova, mi spiego:

l'oggetto Image ha al suo interno una variabile, ovvero img. Per richiamare le variabili di un oggetto si scrive nomeOggetto.variabile.  .  E' lo stesso ragionamento dei metodi.
twgever (17470 points)
8 29 105
by (17.5k points)
quindi @classmethod mi permette di usare quello che tipicamente chiamo self, con le istanze, come la classe stessa che sto usando. mentre con un metodo d'istanza scrivendo self chiamo l'oggetto, in un metodo di classe scrivendo self (o cls, perchè tanto non cambia ed è solo consuetudine, giusto?) chiamo la classe stessa, quindi in questo caso immagine, o non ricordo come l'abbiamo chiamata.

E quindi scrivere nuova=cls(w,h) è come scrivere nuova=immagine(w,h), se immagine è il nome della classe, giusto?

Per il resto, il professore ha spiegato che facciamo questo per trasformare una lista di liste che contiene Colore, piuttosto che triple RGB. Ricordi per caso quali erano gli attributi di Colore?
AdSum (16290 points)
9 20 134
by (16.3k points)
Si, un metodo di classe sarebbe Classe.metodo() mentre quello di istanza è Istanza.metodo().  self e cls è consuetudine, ti consiglio di mettere quello più adatto, ma comunque non genera errori ma solo confusione al limite.

Ni. Solo a volte è la stessa cosa. Se tu richiami il metodo all'interno di immagine si, ma se lo chiami in una sottoclassse di immagine, tipo che ne so ImmagineBIancoENero, tu con cls() crei automaticamente ImmagineBiancoENero, mentre con immagine() crei sempre solo ed esclusivamente Immagine, anche per le sottoclassi.

L'ultima domanda non l'ho capita, con "facciamo questo" cosa intendi esattamente?
twgever (17470 points)
8 29 105
by (17.5k points)
sìsì, naturalmente intendevo in questo metodo.

con "facciamo questo" intendevo questo procedimento, proprio il metodo load.
AdSum (16290 points)
9 20 134
by (16.3k points)
Tre variabili contenenti le tre gradazioni. Ovvero R,G,B
twgever (17470 points)
8 29 105
by (17.5k points)
inoltre, posso dire che con i metodi di classe lavoro sulle istanze e sugli attributi, mentre con i metodi di istanza lavoro con un'istanza che già esiste, e ne modifico solo gli attributi ? Parafrasando a grandissime linee.
AdSum (16290 points)
9 20 134
by (16.3k points)
Allora c'è un po di confusione. Ti faccio un esempio con le automobili. Immagina la classe come un modello di Ferrari.  Tu dal modello(classe) puoi generare un'automobile(istanza). Se per esempio vuoi che ne so, contare quante Ferrari di quel tipo sono state prodotte, tu non a cercarlo sulla macchina (istanza) ma negli schedari riguardati il modello (classe) che probabilmente contengono un registro(variabile) che tiene conto delle vendite (quindi un metodo di classe). Se invece vuoi modificare una specifica macchina (istanza) non andrai a modificare il modello (classe) bensi' direttamente il veicolo stesso (quindi un metodo di istanza!).
twgever (17470 points)
8 29 105
by (17.5k points)
va bene, chiarissimo, anche se preferisco le lamborghini. Buona giornata!