|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Apr 2008
Messaggi: 120
|
[PYTHON] decoratori per permessi agli attributi di una classe
Qualcuno sa come si possa attraverso i decoratori definire permessi di lettura (r), scrittura (w) ed entrambri (rw) agli attributi di una classe?
è un esercizio di università. Il main è questo: Codice:
traceMe = False def trace(*args): if traceMe: print('[' + ' '.join(map(str, args)) + ']') def private(*privates): # privates in enclosing scope def onDecorator(aClass): # aClass in enclosing scope class onInstance: # wrapped in instance attribute def __init__(self, *args, **kargs): self.wrapped = aClass(*args, **kargs) def __getattr__(self, attr): # My attrs don’t call getattr trace('get:', attr) # Others assumed in wrapped if attr in privates: raise TypeError('private attribute fetch: ' + attr) else: return getattr(self.wrapped, attr) def __setattr__(self, attr, value): # Outside accesses trace('set:', attr, value) # Others run normally if attr == 'wrapped': # Allow my attrs self.__dict__[attr] = value # Avoid looping elif attr in privates: raise TypeError('private attribute change: ' + attr) else: setattr(self.wrapped, attr, value) # Wrapped obj attrs return onInstance # Or use __dict__ return onDecorator from selectors import * @private('data', 'size', 'label') @rw(’data’) @r(’size’) @w(’label’) class D: def __init__(self, label, start): self.label = label self.data = start self.size = len(self.data) def double(self): for i in range(self.size): self.data[i] = self.data[i] * 2 def display(self): print(’{0} => {1}’.format(self.label, self.data)) if __name__ == "__main__": X = D(’X is’, [1, 2, 3]) X.display(); X.double(); X.display() try: print(X.size) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) try: print(X.data) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) print(X.getData()) X.setData([25]) print(X.getSize()) try: X.setSize(25) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) try: print(X.getLabel()) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) X.setLabel(’It has worked!!!’) X.display() La stampa è questa: X is X is => [1, 2, 3] X is => [2, 4, 6] TypeError: private attribute fetch: size TypeError: private attribute fetch: data [2, 4, 6] 1 Error: setter inexistent: setSize Error: getter inexistent: getLabel It has worked!!! => [25] Forse vanno usati i setattr e i getattr come in private? Ho provato così ma non funziona: Codice:
def r(*r): def onDecorator(aClass): class onInstance: def __init__(self, *args, **kargs): self.wrapped = aClass(*args, **kargs) def getdata(self, attr): #trace('get:', attr) if attr in rw: raise TypeError('getter inexistent: getsize: ' + attr) else: return getattr(self.wrapped, attr) return onInstance # Or use __dict__ return onDecorator Codice:
traceMe = False def trace(*args): if traceMe: print('[' + ' '.join(map(str, args)) + ']') def r(*r): # privates in enclosing scope def onDecorator(aClass): class onInstance: def __init__(self, *args, **kargs): self.wrapped = aClass(*args, **kargs) def __getattr__(self, attr): trace('get:', attr) if attr in pr: raise TypeError('private attribute fetch: ' + attr) else: return getattr(self.wrapped, attr) def __setattr__(self, attr, value): # Outside accesses trace('set:', attr, value) # Others run normally if attr == 'wrapped': # Allow my attrs self.__dict__[attr] = value # Avoid looping elif attr in privates: raise TypeError('private attribute change: ' + attr) else: setattr(self.wrapped, attr, value) return onInstance return onDecorator |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
L'idea dei decoratori è senz'altro corretta, come pure quella di intercettare i metodi speciali __getattr__ e __setattr__.
Comunque sistema un po' il codice iniziale, perché senza l'indentazione corretta in Python è illeggibile.
__________________
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 |
![]() |
![]() |
![]() |
#3 |
Member
Iscritto dal: Apr 2008
Messaggi: 120
|
si scusa è vero non me ne sono accorto. Ecco la seconda parte indentata
Codice:
@private('data', 'size', 'label') #@rw('data') @r('size') #@w('label') class D: def __init__(self, label, start): self.label = label self.data = start self.size = len(self.data) def double(self): for i in range(self.size): self.data[i] = self.data[i] * 2 def display(self): print('{0} => {1}'.format(self.label, self.data)) ''' X is X is => [1, 2, 3] X is => [2, 4, 6] TypeError: private attribute fetch: size TypeError: private attribute fetch: data [2, 4, 6] 1 Error: setter inexistent: setSize Error: getter inexistent: getLabel It has worked!!! => [25] ''' if __name__ == "__main__": X = D('X is', [1, 2, 3]) #X.display(); X.double(); X.display() try: print(X.size) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) try: print(X.data) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) print(X.getData()) X.setData([25]) print(X.getSize()) try: X.setSize(25) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) try: print(X.getLabel()) except Exception as e: print("{0}: {1}".format(type(e).__name__, e)) X.setLabel('It has worked!!!') X.display() |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Questo è un più complicato e mi richiede più tempo per l'analisi del codice e fare qualche prova.
Soltanto un paio di cose: Codice:
from selectors import * Poi cosa intendi esattamente per attributo "privato"? Uno che sia accessibile soltanto tramite un metodo definito all'interno della classe stessa? Giusto per essere chiari, supponendo che x sia definito come attributo privato: Codice:
class c: def __init__(self): self.x = 'OK' def Prova(self): print self.x i = c() i.Prova() # Stampa OK, perché x è accessibile dall'interno della classe i.x # Genera un errore, perché non ci si deve poter accedere dall'esterno
__________________
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 |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:40.