在应用__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__
导致我的代码中断。
所以,我的问题是:
还有其他办法吗?(property
除外)
使用__slots__
时如何访问对象属性?
答案 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__添加到插槽中的项目列表是可行的。