2017-03-17 60 views
2

我編寫一個函數(Python 3.x),將它用作類裝飾器,而不是使屬性成爲私有的或公共的。在這一點上我測試了我的工作我的類裝飾器中的_getattr_上的Python遞歸

def setPriv(*lists): 
    return private(attrlist=(lambda args: args in lists)) 
def setPub(*lists): 
    return private(attrlist=(lambda args: args not in lists)) 

:所有的 首先,我寫我的「私人」功能:

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 

然後我用兩種不同的方法來聲明私有和Pubblic方法,如下所示:

@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 

感謝

+1

'getattr'導致'__getattr__'被調用。 – Vallentin

+0

@Vallentin不一定。首先調用__getattribute__'。 –

回答

1

屬性的名字一直錯位,在Python的命名規則仍然服從後,所以屬性__wrapped會讀_fPrivate__wrapped不是_fPrivate.__wrapped;沒有點(S)。

如果你檢查你的回溯,你會看到錯誤在__init__提出當你第一次嘗試設置self.__wrapped,這反過來又調用__getattribute__然後__getattr__,並自__getattr__又包含一個屬性訪問即self.__wrapped,它繼續下去。

刪除那個點確保_fPrivate__wrapped使它成爲實例字典並設置屬性調用__getattribute__它乾淨地返回屬性並且不需要更深入的搜索。

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