如何在使用__slots__时访问__getattr__

时间:2017-04-20 02:02:32

标签: python

在应用__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__时如何访问对象属性?

2 个答案:

答案 0 :(得分:7)

只需改变:

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)))

答案 1 :(得分:-2)

快速阅读插槽如何工作的说明:Usage of __slots__?

通过将它们添加到__slots__变量来定义可以设置/获取的属性名称。如果你想动态定义它们,似乎将__dict__添加到插槽中的项目列表是可行的。