PDA

View Full Version : [Python] Metodi bound/unbound


Unrue
08-01-2010, 12:17
Ciao,
rieccomi con un dubbio di Python sui metodi bound/unbound:

Supponiamo di avere il seguente codice:


Class Test(Object):
def metodo_uno(self):
print "Chiamato metodo_uno"

def metodo_due():
print "Chiamato metodo_due"

a_test = Test()
a_test.metodo_uno()
a_test.metodo_due()



Ottengo il seguente errore:


>>> a_test = Test()
Chiamato metodo_uno
>>> a_test.metodo_due()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: metodo_due() takes no arguments (1 given)




Ora, il secondo metodo è dunque unbound, per il fatto che non ci sia il self come argomento. Ma quindi mettere self non è opzionale, ma fondamentale in quanto cambia completamente il comportamento. E' giusto?

Come si richiama il secondo metodo?:confused: E a cosa mi serve un metodo unbound? E' come un metodo statico?

cdimauro
08-01-2010, 13:35
No, il secondo metodo rimane sempre un metodo bound, a prescindere che tu abbia specificato o meno il primo argomento, perché è stato dichiarato all'interno di una classe.

Quindi, anche se lo ometti, quando provi a richiamarlo il compilatore ha comunque generato una chiamata a metodo_due passandogli come parametro l'istanza.

Per ottenere un metodo "statico" devi ricorrere all'apposito decoratore:

Class Test(Object):
def metodo_uno(self):
print "Chiamato metodo_uno"

@staticmethod
def metodo_due():
print "Chiamato metodo_due"

a_test = Test()
a_test.metodo_uno()
a_test.metodo_due()


C'è anche un decoratore (@classmethod) per i metodi di classe, che richiedono sempre un parametro, ma questo è la classe e non l'istanza dell'oggetto.

Unrue
08-01-2010, 14:07
No, il secondo metodo rimane sempre un metodo bound, a prescindere che tu abbia specificato o meno il primo argomento, perché è stato dichiarato all'interno di una classe.

Quindi, anche se lo ometti, quando provi a richiamarlo il compilatore ha comunque generato una chiamata a metodo_due passandogli come parametro l'istanza.



Ciao,
quindi la differenza tra metodo bound e unbound è che quello bound è dichiarato all'interno della classe, quello unbound all'esterno?

Ma allora quando devo mettere come argomento self e quando no?:confused: Cioè, continuo a non capire perché il primo metodo lo accetta ed il secondo no.

cdimauro
08-01-2010, 14:38
Ciao,
quindi la differenza tra metodo bound e unbound è che quello bound è dichiarato all'interno della classe, quello unbound all'esterno?
Attenzione: c'è differenza fra funzione e metodo, e fra metodo bound e metodo unbuond.

La differenza fra funzione e metodo sta nel fatto che il secondo viene dichiarato all'interno di una classe, e in questo caso pretende sempre come primo parametro un'istanza della stessa classe (a meno di usare i due decoratori di cui ti parlavo).

Un metodo poi può essere bound o unbound, a seconda se è legato a una precisa istanza oppure no. Quindi
Class Test(Object):
def metodo_uno(self):
print "Chiamato metodo_uno"

def metodo_due():
print "Chiamato metodo_due"

a_test = Test()
b_test = Test()

bound = a_test.metodo_uno
unbound = Test.metodo_due

bound()
unbuond(a_test)
unbuond(b_test)
Ma allora quando devo mettere come argomento self e quando no?:confused: Cioè, continuo a non capire perché il primo metodo lo accetta ed il secondo no.
Self lo devi mettere SEMPRE quando dichiari una funzione in una classe (quindi hai dichiarato un metodo).

Sempre dentro una classe, lo puoi omettere se utilizzi @staticmethod (in questo modo il metodo diventa un metodo statico, cioé una funzione).

Unrue
08-01-2010, 14:53
Mm,
il tuo esempio dà errore:


class Test():
def metodo_uno(self):
print "Called method_one"

def metodo_due():
print "Called method_two"

a_test = Test()
b_test = Test()

bound = a_test.metodo_uno
unbound = Test.metodo_due

bound()
unbound(a_test)
unbound(b_test)



Called method_one
Traceback (most recent call last):
File "bound.py", line 17, in <module>
unbound(a_test)
TypeError: metodo_due() takes no arguments (1 given)


Cioè, in pratica, quale è la differenza tra metodo unbound e metodo "statico"?


Self lo devi mettere SEMPRE quando dichiari una funzione in una classe (quindi hai dichiarato un metodo).

Sempre dentro una classe, lo puoi omettere se utilizzi @staticmethod (in questo modo il metodo diventa un metodo statico, cioé una funzione).


Quindi scrivere un metodo senza decoratore @staticmethod e senza self come argomento è un errore giusto?

cdimauro
08-01-2010, 15:00
Mm,
il tuo esempio dà errore:


class Test():
def metodo_uno(self):
print "Called method_one"

def metodo_due():
print "Called method_two"

a_test = Test()
b_test = Test()

bound = a_test.metodo_uno
unbound = Test.metodo_due

bound()
unbound(a_test)
unbound(b_test)



Called method_one
Traceback (most recent call last):
File "bound.py", line 17, in <module>
unbound(a_test)
TypeError: metodo_due() takes no arguments (1 given)

Sbadatamente ho ricopiato il tuo codice col metodo senza il parametro self. Aggiungilo e funzionerà.
Cioè, in pratica, quale è la differenza tra metodo unbound e metodo "statico"?
Il primo pretende un'istanza come primo argomento, nel momento dell'invocazione.

Il secondo può non accettarla, perché è un funzione come un'altra.
Quindi scrivere un metodo senza decoratore @staticmethod e senza self come argomento è un errore giusto?
Sì, lo è, perché non puoi richiamarlo.

Unrue
08-01-2010, 15:02
Ok capito!
Grazie come sempre, ciao ;)

Unrue
08-01-2010, 15:24
Il primo pretende un'istanza come primo argomento, nel momento dell'invocazione.

Il secondo può non accettarla, perché è un funzione come un'altra.



Noo, aspetta! Non avevo letto la tua ultima modifica...

Dunque, se un metodo unbound non è legato ad una particolare istanza, perché vuole un'istanza come primo argomento?

Infine, questo è un esempio di metodo statico:


class prova():
@staticmethod
def pippo():
pass


Un metodo unbound invece come si scrive? :fagiano:

cdimauro
08-01-2010, 19:51
Noo, aspetta! Non avevo letto la tua ultima modifica...

Dunque, se un metodo unbound non è legato ad una particolare istanza, perché vuole un'istanza come primo argomento?
Perché rimane comunque un metodo, e i metodi lavorano esclusivamente su / con delle istanze.

Un metodo bound è un metodo in cui l'oggetto è già legato a una particolare istanza, per cui non c'è bisogno di (e NON si deve) specificare nessuna istanza: al più si passano eventuali parametri, ed è già in grado di lavorare.

Un metodo unbound vedilo come una "promessa di matrimonio", dove un partner aspetta l'altro per poter "convolare a nozze". Tale metodo (uno dei partner) è legato a una precisa classe, ma aspetta la sua "amata" istanza (l'altro partner) per poter effettuare il lavoro vero e proprio.
Rispetto al metodo bound, però, è un po' più "libertino", perché quello bound è legato alla sua istanza "finché morte (cioè il garbage collector) non li separa", mentre quello unbound si può utilizzare con qualunque istanza della stessa classe che gli viene passata.
Infine, questo è un esempio di metodo statico:


class prova():
@staticmethod
def pippo():
pass


Un metodo unbound invece come si scrive? :fagiano:
Così:
class prova():
def pippo():
pass

unbound = prova.pippo

istanza1 = prova()
istanza2 = prova()

unbound(istanza1)
unbound(istanza2)
In buona sostanza, "unbound" è semplicemente il riferimento al metodo pippo della classe prova.

P.S. Scusami per prima, ma avevo fretta, e ho commesso un errore da dilettante. :muro:

Unrue
09-01-2010, 10:01
Un metodo unbound vedilo come una "promessa di matrimonio", dove un partner aspetta l'altro per poter "convolare a nozze". Tale metodo (uno dei partner) è legato a una precisa classe, ma aspetta la sua "amata" istanza (l'altro partner) per poter effettuare il lavoro vero e proprio.
Rispetto al metodo bound, però, è un po' più "libertino", perché quello bound è legato alla sua istanza "finché morte (cioè il garbage collector) non li separa", mentre quello unbound si può utilizzare con qualunque istanza della stessa classe che gli viene passata.


Credo di aver capito :D :D


P.S. Scusami per prima, ma avevo fretta, e ho commesso un errore da dilettante. :muro:

Di nulla :p . Grazie infinite, ciao!