2013-07-09 26 views
1

有沒有一種方法來攔截屬性調用鏈?在Python中訪問一個完整的屬性調用鏈

我的意思是這樣的:

myobj.attr1.attr2.{...}.attrN 

我可以採用某種MyObj中內攔截整個產業鏈?

我想到的是一個函數,可以一次訪問完整鏈'attr1.{...}.attrN',例如作爲一個字符串。有沒有辦法確定這一點?

到目前爲止,我有一個相當哈克解決方案,其中getatrr創建新物體,其GETATTR還創建新物體並且由此整個屬性鏈(在全名以下)記錄爲一個字符串。但我不喜歡這個解決方案,因爲這有幾個缺點,特別是在酸洗和錯誤處理方面。

class NameCollector(object): 
    ''' A helper class that resolves natural naming 
    ''' 
    def __init__(self,myobj,name='',parent_name=''): 

     self._myobj=myobj 

     if name == '': 
      self._fullname = '' 
     elif parent_name == '': 
      self._fullname = name 
     else: 
      self._fullname = parent_name + '.' + name 

    def __getattr__(self,name): 

     new_collector = NameCollector(self._myobj,name,self._fullname, self._regexp) 
     if name in self._myobj._leaves: 
      return self._myobj._do_stuff_with_chained_attribute_names(new_collector) 

     return new_collector 

歡呼和感謝, 羅伯特

+0

將屬性視爲* name *的屬性而不是該名稱引用的對象的屬性的用例是什麼? – chepner

回答

0

一個解決辦法是建立在第一次訪問a.b一個新的對象,然後每一個後續訪問,只需更新對象的內部結構(例如,一個值列表),並添加一個__str____repr__方法。

class NameCollector(object): 
    def __init__(self, parent, attr): 
     self.parent = parent 
     self.structure = [attr] 
    def __getattr__(self, attr): 
     if attr in self.__dict__: return attr 
     self.structure.append(attr) 
     return self 
    def __str__(self): 
     retval = "" 
     for item in self.structure: 
      retval += str(getattr(self.parent, item)) + "." 
     return retval[:-1] # Remove the last '.' 
class Foo(object): 
    def __getattr__(self, attr): return NameCollector(self, attr) 
+0

'AttributeError:'NoneType'對象沒有屬性'other''你必須在'__getattr__'中返回'self',否則它不能處理多於2個屬性的鏈(使用'other.other.other'嘗試) – Bakuriu

+0

if attr in self .__ dict__:return attr 可能沒有必要,因爲只有在myobj中沒有匹配時才調用__getattr__ .__ dict__ 但是,您的答案不能解決我的問題。如果我調用myobj.attr1。{...}。attr2,我將返回一個NameCollector對象,它可以打印屬性字符串。我需要的是,myobj立即可以訪問完整的鏈條,並且可以做出適當的反應。所以myobj.attr1。{...}。attrN應該直接由myobj處理並返回一些存儲在attrN中的數據(但是中間階段可能拼錯了,或者用戶想要快捷鍵)。 – SmCaterpillar

相關問題