我正在使用的代码库的设计很大程度上依赖于属性访问。我想跟踪特定实例的属性访问。我在想这样的事情会起作用:
class MyDict(dict):
def get(self, key, default=None):
print('get: %r' % key)
return dict.get(self, key, default)
def update(self, *args, **kwargs):
print('update: %r %r' % (args, kwargs))
dict.update(self, *args, **kwargs)
def __getitem__(self, key):
print('getitem: %r' % key)
return dict.__getitem__(self, key)
def __setitem__(self, key, value):
print('setitem: %r %r' % (key, value))
dict.__setitem__(self, key, value)
class Bar:
def __init__(self):
self.__dict__ = MyDict()
b = Bar()
b.baz = 'boz' # 1. should print setitem but doesn't
setattr(b, 'foo', 'fum') # 2. same as above
getattr(b, 'foo') # 3. should print getitem but doesn't
b.foo # 4. same as above
b.__dict__['fix'] = 'fox' # 5. successfully prints setitem message
b.__dict__['fix'] # 6. successfully prints getitem message
print(b.__dict__) # Shows {'baz': 'boz', 'foo': 'fum', 'fix': 'fox'}, as expected
有人可以解释为什么上面的1、2、3和4不能按预期工作吗?为什么5和6起作用?
我认为属性访问(通过b.foo,getattr和setattr)通过getitem和setitem对基础 dict 进行操作,但这似乎并非如此。
答案 0 :(得分:0)
感谢@Sraw。我意识到我不需要重写 dict ,而需要重写setattr和getattr。这有效:
class Bar:
def __setattr__(self, name, value):
print('setattr: %r %r' % (name, value))
super().__setattr__(name, value)
b = Bar()
b.baz = 'boz'
setattr(b, 'foo', 'fum')
输出符合预期:
setattr: 'baz' 'boz'
setattr: 'foo' 'fum'