I write a function (Python 3.x) for use it as a class decorator than make attributes private or public. First of all I wrote my 'private' function:
def private(attrlist):
def wrapper(obj):
class fPrivate:
def __init__(self,*args,**kwargs):
self.__wrapped = obj(*args,**kwargs)
def __getattr__(self,args):
if attrlist(args):
raise TypeError('Get on a provate attr')
else:
return getattr(self.__wrapped,args)
def __setattr__(self,args,val):
if args == '_fPrivate.__wrapped':
self.__dict__[args] = val
elif attrlist(args):
raise TypeError('Set on private')
else:
setattr(self.__wrapped,args,val)
return fPrivate
return wrapper
then I use two different methods to declare Private and Pubblic method, like this:
def setPriv(*lists):
return private(attrlist=(lambda args: args in lists))
def setPub(*lists):
return private(attrlist=(lambda args: args not in lists))
at this point I test my work:
@setPriv('name')
class t1:
def __init__(self,name,age):
self.name = name
self.age = age
But when I create my first instance
a = t1('Bob',40)
I got this error:
> File "C:\Code\utils\private.py", line 11, in __getattr__
getattr(self.__wrapped,args)
File "C:\Code\utils\private.py", line 11, in __getattr__
getattr(self.__wrapped,args)
File "C:\Code\utils\private.py", line 11, in __getattr__
getattr(self.__wrapped,args)
File "C:\Code\utils\private.py", line 11, in __getattr__
getattr(self.__wrapped,args)
File "C:\Code\utils\private.py", line 8, in __getattr__
if attrlist(args):
File "C:\Code\utils\private.py", line 25, in <lambda>
return private(attrlist=(lambda args: args in lists))
RecursionError: maximum recursion depth exceeded in comparison
Thanks in advance
After the name of an attribute has been mangled, the rules for naming in Python are still obeyed, so attribute __wrapped
will read _fPrivate__wrapped
not _fPrivate.__wrapped
; without dot(s).
If you check your traceback, you'll see the error is raised in the __init__
when you first try to set self.__wrapped
, which is turn calls __getattribute__
and then __getattr__
, and since __getattr__
again contains an attribute access viz. self.__wrapped
, it goes on and on.
Removing that dot ensures, _fPrivate__wrapped
makes it to the instance dictionary and setting the attribute calls __getattribute__
which returns the attribute cleanly and has no need to search deeper.
a = t1('Bob',40)
a.age = 7
print(a.age)
# 7
a.name = 'me'
Traceback (most recent call last):
File "python", line 38, in <module>
File "python", line 15, in __setattr__
TypeError: Set on private