Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3:钩子列表&;口述变化_Python_Python 3.x_Hook - Fatal编程技术网

Python 3:钩子列表&;口述变化

Python 3:钩子列表&;口述变化,python,python-3.x,hook,Python,Python 3.x,Hook,我的应用程序依靠list和dict数据结构来维护当前状态。现在我需要跟踪元素在列表中的添加/删除或dict数据更改。我在谷歌上搜索发现有collections.abc.Sequence(用于列表)和collections.abc.MutableMapping(用于dict),但它们非常有限,结果不能代替list/dict(append,clear,…)。我一直在考虑一些代理类,它将转发调用,并在转发某个方法之前/之后提供要调用的挂钩,但在中找不到任何类似的 所以我的问题是:如何钩住给定结构的变异

我的应用程序依靠
list
dict
数据结构来维护当前状态。现在我需要跟踪元素在列表中的添加/删除或dict数据更改。我在谷歌上搜索发现有
collections.abc.Sequence
(用于列表)和
collections.abc.MutableMapping
(用于dict),但它们非常有限,结果不能代替list/dict(
append
clear
,…)。我一直在考虑一些代理类,它将转发调用,并在转发某个方法之前/之后提供要调用的挂钩,但在中找不到任何类似的


所以我的问题是:如何钩住给定结构的变异子?有什么我不知道的吗?

子类化dict可能:

class DictWatch(dict):
    def __init__(self, *args, **kwargs):
        self.callback = kwargs.pop('callback')
        dict.__init__(self, args)

    def __setitem__(self, key, val):
        # YOUR HOOK HERE
        self.callback(key, val)
        dict.__setitem__(self, key, val)

    # and other overrided dict methods if you need them
演示:


尽管正式支持子类内置类,但我还是建议您考虑使用代理类。

问题是调用重写的方法时没有很好的文档记录。例如,如果重写
\uuuu setitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,则当您使用
。您还必须覆盖
扩展
。很容易忘记覆盖一些模糊的方法,修改将在不调用回调的情况下悄无声息地进行(而如果使用代理,它将抛出一个
AttributeError
,指示您忘记定义某个方法)

还有更多。某些通过参数接收字典的内置方法在CPython中根本不会调用任何重写的方法,如下所示:

逃学

hooky.List
示例:

#!/usr/bin/env python

from hooky import List


class MyList(List):
    def _before_add(self, key, item):
        print('before add, key: {}, item: {}'.format(key, repr(item)))

    def _after_add(self, key, item):
        print(' after add, key: {}, item: {}'.format(key, repr(item)))

    def _before_del(self, key):
        print('before_del, key: ', key)

    def _after_del(self, key):
        print(' after_del, key: ', key)


l = MyList(['a', 'b'])

l.append(1)

l.extend(['f', 'g', 2])

l.pop()

l[2:3] = ['c', 'd', 'e']

print(l)

l.clear()

print(l)
打印:

before add, key: 0, item: 'a'
 after add, key: 0, item: 'a'
before add, key: 1, item: 'b'
 after add, key: 1, item: 'b'
before add, key: 2, item: 1
 after add, key: 2, item: 1
before add, key: 3, item: 'f'
 after add, key: 3, item: 'f'
before add, key: 4, item: 'g'
 after add, key: 4, item: 'g'
before add, key: 5, item: 2
 after add, key: 5, item: 2
before_del, key:  -1
 after_del, key:  -1
before_del, key:  2
 after_del, key:  2
before add, key: 2, item: 'c'
 after add, key: 2, item: 'c'
before add, key: 3, item: 'd'
 after add, key: 3, item: 'd'
before add, key: 4, item: 'e'
 after add, key: 4, item: 'e'
['a', 'b', 'c', 'd', 'e', 'f', 'g']
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
[]

我想到的唯一方法是自己实现list/dict的子类,然后重写
append
clear
等。我看到一些讨论指出继承内置类型是个坏主意。还是错了?@Daniel:从内置类型继承绝对没有错!那太傻了。
#!/usr/bin/env python

from hooky import List


class MyList(List):
    def _before_add(self, key, item):
        print('before add, key: {}, item: {}'.format(key, repr(item)))

    def _after_add(self, key, item):
        print(' after add, key: {}, item: {}'.format(key, repr(item)))

    def _before_del(self, key):
        print('before_del, key: ', key)

    def _after_del(self, key):
        print(' after_del, key: ', key)


l = MyList(['a', 'b'])

l.append(1)

l.extend(['f', 'g', 2])

l.pop()

l[2:3] = ['c', 'd', 'e']

print(l)

l.clear()

print(l)
before add, key: 0, item: 'a'
 after add, key: 0, item: 'a'
before add, key: 1, item: 'b'
 after add, key: 1, item: 'b'
before add, key: 2, item: 1
 after add, key: 2, item: 1
before add, key: 3, item: 'f'
 after add, key: 3, item: 'f'
before add, key: 4, item: 'g'
 after add, key: 4, item: 'g'
before add, key: 5, item: 2
 after add, key: 5, item: 2
before_del, key:  -1
 after_del, key:  -1
before_del, key:  2
 after_del, key:  2
before add, key: 2, item: 'c'
 after add, key: 2, item: 'c'
before add, key: 3, item: 'd'
 after add, key: 3, item: 'd'
before add, key: 4, item: 'e'
 after add, key: 4, item: 'e'
['a', 'b', 'c', 'd', 'e', 'f', 'g']
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
before_del, key:  -1
 after_del, key:  -1
[]