我已将dict
分类为:
class ObjectiveDict(dict):
def __getattr__(self, name):
if name in self:
return self[name]
else:
raise AttributeError("No such attribute: " + name)
def __setattr__(self, name, value):
"""
IMPORTANT NOTICE: when "name" is an iterator of an iterable, will not work, must use [] syntax
"""
self[name] = value
def __delattr__(self, name):
if name in self:
del self[name]
else:
raise AttributeError("No such attribute: " + name)
现在我有类似的东西:
objd = ObjectiveDict({'a':1, 'b':2, 'c':3})
objd.d = 4
这很有效,输出:
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
但是,如果我有一个我要附加到objd
的键列表,让我们假设使用默认值,它使用我用于迭代器的名称来创建一个键来迭代列表,即:
keys = ['key1', 'key2', 'key3']
for k in keys:
objd.k = None
输出:
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'k': None}
我知道我可以使用objd[k] = None
或使用setattr
方法解决这个问题,但我想理解为什么当我使用点符号时我的__setattr__
方法ObjectiveDict
1}}将迭代器作为字符串?有没有办法修补我的代码,所以它使用点符号?
答案 0 :(得分:5)
因为Python是连贯的。
在第一种情况下,您对objd.d = 4
感到满意,已翻译为objd['d'] = 4
。但它可能是:
d = 'e'
objd.d = 4
你仍然会有{'a': 1, 'b': 2, 'c': 3, 'd': 4}
(希望不 {'a': 1, 'b': 2, 'c': 3, 'e': 4}
)。
所以当你写下第二种情况时:
keys = ['key1', 'key2', 'key3']
for k in keys:
objd.k = None
您只需重复objd.k = None
,即三次翻译为objd['k'] = None
。
点符号无法使用名称的值,您只能使用名称本身。
您可以使用以下方式使其正常工作:
def __setattr__(self, name, value):
self[eval(name)] = value
但我真的很劝你不要那样做!在第一种情况下,你会得到:
d = 'e'
objd.d = 4
objd
=>输出:{'a': 1, 'b': 2, 'c': 3, 'e': 4}
!