Python中是否有一种机制可以拦截对象的访问?

时间:2016-11-25 21:43:34

标签: python python-internals

我想控制变量被访问。我尝试在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.

Upd:对象保留其类型非常重要。

继续举例:

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

1 个答案:

答案 0 :(得分:0)

如果没有创建某种类型的包装类来代替对底层&#34;跟踪&#34;的调用,则无法做到这一点。对象

最终通过使用其dunders来控制对象上的每个操作。例如,print拨打__str__s + '.'先拨打__add__,拨打电话__getitem__。您需要定义您的访问权限&#34;这些函数中的行为

在示例中显示功能的快速基本说明可能如下所示:

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()将其绑定到全局范围。

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

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