2017-04-20 90 views
1

應用__slots__之前訪問__getattr__,我可以這樣做:如何同時使用__slots__

class C(object): 

    def __init__(self): 
     self.m_A = 1 

    def __getattr__(self, name): 
     if name in ("A"): 
      return self.__dict__["m_%s" % name] 
     raise AttributeError(name) 

a = C() 
a.A 

現在,我想用__slots__;但是,這將禁用__dict__導致我的代碼中斷。

所以,我的問題是:

  1. 是否有任何其他方式做到這一點(除property

  2. 如何使用__slots__ Python的時候我訪問一個對象的屬性?

+0

的[Python的可能的複製\ _ \ _槽\ _ \ _(製作和使用)](http://stackoverflow.com/questions/14666138/python-slots-making-and-using) – OJFord

+0

也考慮修改標題來總結*問題* - 目前看來是一個*陳述*表示'__slots__',並且延伸這個問題不值得任何人的時間。 – OJFord

+0

我已經看到它,但它不是我想要的。 –

回答

5

只是改變:

return self.__dict__["m_%s" % name] 

到:

return getattr(self, "m_%s" % name) 

前者是使用不適用的實施細則,後者明確地查找通過名稱的新屬性。

注:對於這個特定的情況下,我會避免__getattr__完全如涉及太多的開銷,而只是做:

@property 
def A(self): 
    return self.m_A 

這將具有相同的行爲,並通過__getattr__和運行速度更快(通用調度getattr調用比通過屬性描述符進行目標查找更昂貴)。如果你有一打這樣的槽,使只讀訪問器,您仍然可以通過使後級增加的訪問者使用這個模式相當便宜:

from operator import attrgetter 

class Foo(object): 
    __slots__ = 'm_XXX', 'm_YYY', etc. 

    ... rest of class body ... 

# Add readonly accessors sans m_ prefix for each slot with an m_ prefix: 
for membername in Foo.__slots__: 
    if membername.startswith('m_'): 
     setattr(Foo, membername.replace('m_', '', 1), property(attrgetter(membername))) 
+0

我有很多像'm_A'這樣的屬性,所以'property'不能滿足我的需求。 –

+0

@JohnHe:如果你正在使用'__slots__',你的屬性列表是有限的,並且如果它們都是簡單的只讀訪問器,那麼一堆兩行訪問函數(一個用於裝飾器,一個用於函數並返回)isn不合理,而且速度會更快。你實際上也可以概括這種特定的模式;我會將其編輯到我的答案中。 – ShadowRanger

+0

@JohnHe:增加了一個概括創建'property's的例子,用'__getattr__'代替了''__getattr__''的運行時間開銷,而且定義時間很少。 – ShadowRanger

-2

從描述的插槽如何在這裏工作快速閱讀:Usage of __slots__?

定義可以設置/將它們添加到__slots__變量獲取屬性名稱。如果你想在飛行中定義它們,似乎將__dict__添加到插槽中的項目列表是最好的選擇。