|
|||||||
|
|
|
![]() |
|
|
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: 18:51.



















