Python 在我的 class 装饰器中对 _getattr_ 的递归
Python recursion on _getattr_ in my class decorator
我编写了一个函数 (Python 3.x) 将其用作 class 装饰器,而不是将属性设为私有或 public。
首先我写了我的 'private' 函数:
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
然后我使用两种不同的方法来声明 Private 和 Pubblic 方法,如下所示:
def setPriv(*lists):
return private(attrlist=(lambda args: args in lists))
def setPub(*lists):
return private(attrlist=(lambda args: args not in lists))
此时我测试我的工作:
@setPriv('name')
class t1:
def __init__(self,name,age):
self.name = name
self.age = age
但是当我创建第一个实例时
a = t1('Bob',40)
我收到这个错误:
> 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
提前致谢
在属性名称被破坏后,仍然遵守Python中的命名规则,因此属性__wrapped
将读作_fPrivate__wrapped
不是 _fPrivate.__wrapped
;没有点。
如果你检查你的回溯,你会看到当你第一次尝试设置 self.__wrapped
时 __init__
中出现了错误,这是依次调用 __getattribute__
然后 __getattr__
,并且由于 __getattr__
再次包含属性访问即。 self.__wrapped
,它一直在继续。
删除该点可确保 _fPrivate__wrapped
使其进入实例字典并设置属性调用 __getattribute__
,returns 属性干净利落,无需更深入地搜索。
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
我编写了一个函数 (Python 3.x) 将其用作 class 装饰器,而不是将属性设为私有或 public。 首先我写了我的 'private' 函数:
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
然后我使用两种不同的方法来声明 Private 和 Pubblic 方法,如下所示:
def setPriv(*lists):
return private(attrlist=(lambda args: args in lists))
def setPub(*lists):
return private(attrlist=(lambda args: args not in lists))
此时我测试我的工作:
@setPriv('name')
class t1:
def __init__(self,name,age):
self.name = name
self.age = age
但是当我创建第一个实例时
a = t1('Bob',40)
我收到这个错误:
> 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
提前致谢
在属性名称被破坏后,仍然遵守Python中的命名规则,因此属性__wrapped
将读作_fPrivate__wrapped
不是 _fPrivate.__wrapped
;没有点。
如果你检查你的回溯,你会看到当你第一次尝试设置 self.__wrapped
时 __init__
中出现了错误,这是依次调用 __getattribute__
然后 __getattr__
,并且由于 __getattr__
再次包含属性访问即。 self.__wrapped
,它一直在继续。
删除该点可确保 _fPrivate__wrapped
使其进入实例字典并设置属性调用 __getattribute__
,returns 属性干净利落,无需更深入地搜索。
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