Python 中是否有允许拦截对对象的访问的机制?

Is there a mechanism in Python, which would allow to intercept access to an object?

我想控制变量被访问。我试图在 pyjack 模块的帮助下实现它,但是方法 pyjack.connect(my_str, proxyfn=my_proxyfn) 抛出异常 ...type '<type 'str'>' not supported.

这是我想要的示例:

>>> def on_access(obj):
...    print 'object with id=%d has been requested' % id(obj)
...
>>> s = 'some string'
>>>
>>> foo(s, handler=on_access)
>>>
>>> print s
object with id=4559856664 has been requested
some string
>>>
>>> s + '.'
object with id=4559856664 has been requested
some string.

更新:对象保留其类型很重要。

继续示例:

>>> import json
>>>
>>> json.dumps(s)
object with id=4559856664 has been requested
'"some string"'

如果不创建某种包装器 class 来委托对底层 "tracked" 对象的调用,就无法做到这一点。

对一个对象的每一个操作最终都是通过使用它的命令来控制的。 print,例如调用__str__s + '.'先调用__add__,下标调用__getitem__。您需要在这些函数中定义 "on access" 行为

介绍您示例中的功能的快速基本说明可能如下所示:

class Wrap(object):

    access_str = "object with id={} has been accessed"

    def __init__(self, obj):
        self._obj = obj

    def __add__(self, v):
        print(self.access_str.format(self._obj))
        # If you want the result to be tracked 
        # return Wrap(self._obj + v)
        return self._obj + v


    def __repr__(self):
        print(self.access_str.format(self._obj))
        return repr(self._obj)

    def __str__(self):
        print(self.access_str.format(self._obj))
        return str(self._obj)

这显然缺少所需的其余方法,但如果你沿着这条路走下去,那是你应该做的事情。

现在您可以像使用任何字符串一样使用它:

>>> s = Wrap("Hello World")
>>> print(s)
object with id=140023929394880 has been accessed
Hello World
>>> s + '.'
object with id=140023929394880 has been accessed
'Hello World.'

这显然可以更改,例如在 __init__ 中,您可以强制要求 name 参数,然后通过使用 globals() 在全局范围内绑定该参数.

此外,您可以创建一个元class,它会根据类型自动为您生成类似的 dunder 方法。

要点是,没有内置方法可以做到这一点,您需要自己以一些乏味的方式来完成。