每当访问对象的属性时,如何制作对象日志消息?

时间:2018-12-23 06:42:28

标签: python dictionary

我正在使用的代码库的设计很大程度上依赖于属性访问。我想跟踪特定实例的属性访问。我在想这样的事情会起作用:

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 进行操作,但这似乎并非如此。

1 个答案:

答案 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'