PDA

View Full Version : [PYTHON] aggiungere metodi dinamicamente


snowx
25-02-2012, 14:10
Sto cercando di aggiungere dei metodi dinamicamente ad una classe attraverso i decoratori, senza sapere a priori il nome del metodo, ho provato a fare cosi ma ci sono dei problemi:


def decor(*var):
def onDecorator(aClass):
class onInstance:

def __init__(self,*args,**kargs):
getter='G'+var[0]
aClass.getter = self.flaz
self.wrapped = aClass(*args,**kargs)

def __getattr__(self,attr):
return getattr(self.wrapped,attr)

def flaz(self):
return self.data

return onInstance
return onDecorator

@decor('data')
class D:
def __init__(self, data):
self.data = data
self.dimension = len(self.data)


se provo:

X=D([5,3])
print(X.Gdata())
mi dice che AttributeError: 'D' object has no attribute 'Gdata'

invece se faccio

X=D([5,3])
print(X.getter())
sembra funzionare, il problema è che io vorrei avere il comportamento che ho chiamando X.getter() quando chiamo X.Gdata e più in generale un X.Gxxx, come posso fare?

cdimauro
25-02-2012, 14:38
Non ho ancora usato i decoratori di classe per cui potrei anche sbagliare, ma prova a cambiare questo:
aClass.getter = self.flaz
con questo:
setattr(aClass, getter, self.flaz)

snowx
25-02-2012, 16:14
Non ho ancora usato i decoratori di classe per cui potrei anche sbagliare, ma prova a cambiare questo:
aClass.getter = self.flaz
con questo:
setattr(aClass, getter, self.flaz)

è perfetto :D

ma ora mi chiedo, come mai?

cdimauro
25-02-2012, 16:57
DOPPIO. :(

cdimauro
25-02-2012, 16:58
Perché con:
aClass.getter = self.flaz
hai aggiunto l'attributo getter (esattamente con questo nome) alla classe (quindi è un attributo di classe) aClass, e gli fornito come valore il metodo bounded flaz.

Per cui tutte le istanze di aClass erediteranno quest'attributo, che funzionerà come un metodo perché... contiene un metodo. :p

Mentre con:
setattr(aClass, getter, self.flaz)
aggiunto sempre ad aClass un attributo, il cui nome è contenuto nella variabile getter, che contiene la stringa che hai costruito prima. Quindi contenendo getter 'Gdata', verrà creato l'attributo di classe che si chiama Gdata, appunto, il cui valore è il solito metodo bounded flaz.

Magie della dinamicità di Python. :D