每当访问对象属性时,如何使对象日志消息



我正在开发一个代码库,其设计严重依赖于属性访问。 我想跟踪特定实例的属性访问。 我在想这样的事情会起作用:

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 对底层字典进行操作,但事实似乎并非如此。

谢谢@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'

最新更新