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