2015-12-01 30 views
1

我有這樣的:普通屬性實現GETATTR/SETATTR

class MySession: 

    def __init__(self, session): 
     session['my-data'] = {} # my data is here 
     self._session = session 

    def __getattr__(self, name): 
     return self._session['my-data'][name] 

    def __setattr__(self, name, value): 
     my_data = self._session['my-data'] 
     my_data[name] = value 
     self._session['my-data'] = my_data 


obj = MySession({}) 
obj.x = 3 

基本上我想封裝與對象訪問會話(子)字典屬性的訪問。但我不能這樣做,因爲這將導致無限遞歸,我猜是因爲這樣做:

self._session = session 

電話SETATTR,進而調用GETATTR,進而調用GETATTR等

我怎麼能預 - 在實現getattr/setattr的類中初始化一些(普通)屬性?

+0

這會導致同樣的無限遞歸:self.session再次GETATTR – dangonfast

回答

2

__getattr__方法只要求不存在的屬性在正常的屬性字典中。然而無條件地被稱爲(它的鏡像實際上是__getattribute__而不是__getattr__)。如果您可以在__init__中正確設置_session屬性,則無需擔心其他方法中的任何問題。

添加屬性,而不會在任何遞歸,使用super(MySession, self).__setattr__給你打電話從object繼承方法的版本(你應該總是從object繼承在Python 2,讓你的類的新樣式類,在Python 3,這是默認)。您也可以直接撥打object.__setattr__,但如果您最終使用多重繼承,則使用super會更好。

class MySession(object): 
    def __init__(self, session): 
     session['my-data'] = {} 
     super(MySession, self).__setattr__("_session", session) # avoid our __setattr__ 

    def __getattr__(self, name): 
     return self._session['my-data'][name] # this doesn't recurse if _session exists 

    def __setattr__(self, name, value): 
     my_data = self._session['my-data'] 
     my_data[name] = value 
     self._session['my-data'] = my_data 
+0

太好了,謝謝。關於我的setattr實現:我知道這很尷尬,但這與會話在django中的工作方式有關:設置子鍵不會更新會話。這是一個常見的Django陷阱。 https://docs.djangoproject.com/en/1.8/topics/http/sessions/ – dangonfast

+0

'TypeError:super()至少需要1個參數(0給定)'。我正在使用python 2.7 – dangonfast

+0

啊,我假定你是在Python 3中,因爲缺乏'object'作爲你的課程的基礎。在Python 2中,你肯定希望(或者'super'不管你怎麼稱呼它都不會工作)。您還需要爲'super'調用提供參數,因爲Python 2的版本不能像Python 3那樣自動推導出類。我已經更新了Python 2的工作答案,並且將'__setattr__'實現放回了您需要的方式。 – Blckknght

1

你可以初始化第一和改變制定者干將以後:

def __init__(self, session): 
    session['my-data'] = {} 
    self._session = session 
    self.__setattr__ = self._setattr 
    self.__getattr__ = self._getattr 

假設self._setattrself._getattr實現當然:)的

+0

遺憾的是它不工作要求。 _getattr未使用。這確實很奇怪。 – dangonfast