计算从 python 字典中解包的次数
Count reads from python dictionary with unpacking
我有兴趣计算对字典值的访问次数。我不确定如何在柜台中包括字典拆包。有什么建议吗?
from collections import defaultdict
class LDict(dict):
def __init__(self, *args, **kwargs):
'''
This is a read-counting dictionary
'''
super().__init__(*args, **kwargs)
self._lookup = defaultdict(lambda : 0)
def __getitem__(self, key):
retval = super().__getitem__(key)
self._lookup[key] += 1
return retval
def __setitem__(self, key, value):
super().__setitem__(key, value)
self._lookup[key] = self._lookup.default_factory()
def __delitem__(self, key):
super().__delitem__(self, key)
_ = self._lookup[key]
del self._lookup[key]
def list_unused(self):
return [key for key in self if self._lookup[key] == 0]
l = LDict(a='apple', b='bugger')
print({**l, **l})
print(l.list_unused())
_ = l['a']
print(l.list_unused())
您需要覆盖更多方法。访问 不是 通过 __getitem__()
集中:其他方法如 copy()
、items()
等无需通过 __getitem()__
即可访问密钥。我假设 **
运算符使用 items()
,但您将需要处理所有方法以跟踪每次访问。在许多情况下,您将不得不做出判断。例如,__repr__()
算作访问吗?返回的字符串包含格式化的每个键和值,所以我认为它确实如此。
我建议重写这些方法中的所有,因为您还必须对作业进行簿记。
def __repr__(self):
def __len__(self):
def __iter__(self):
def clear(self):
def copy(self):
def has_key(self, k):
def update(self, *args, **kwargs):
def keys(self):
def values(self):
def items(self):
编辑:显然这里有一个与您的实施直接相关的重要警告。如果 LDict
扩展 dict
,则在字典解包 { **l, **l}
期间调用这些方法中的 none。
显然您可以遵循建议 here,并在不扩展 dict
的情况下实施 LDict。这对我有用:
from collections import MutableMapping
class LDict(MutableMapping):
def __init__(self, *args, **kwargs):
'''
This is a read-counting dictionary
'''
self._lookup = defaultdict(lambda : 0)
self.data = {}
if kwargs:
self.data.update(kwargs)
def __getitem__(self, key):
retval = self.data[key]
self._lookup[key] += 1
return retval
def __setitem__(self, key, value):
self.data[key] = value
self._lookup[key] = self._lookup.default_factory()
def __delitem__(self, key):
del self.data[key]
_ = self._lookup[key]
del self._lookup[key]
def items(self):
print('items is being called!')
yield from self.data.items()
def __iter__(self):
print('__iter__ is being called!')
yield from self.data
def __len__(self):
return len(self.data)
def list_unused(self):
return [key for key in self if self._lookup[key] == 0]
l = LDict(a='apple', b='bugger')
print({**l, **l})
print(l.list_unused())
_ = l['a']
print(l.list_unused())
产生输出:
__iter__ is being called!
__iter__ is being called!
{'b': 'bugger', 'a': 'apple'}
__iter__ is being called!
[]
__iter__ is being called!
[]
(我只实现了最低限度以使示例工作,如果您希望计数正确,我仍然建议实现我列出的方法集!)
所以我猜你的问题的答案是你必须
- 实施
__iter__(self)
方法
- 不要继承自
dict()
。
我有兴趣计算对字典值的访问次数。我不确定如何在柜台中包括字典拆包。有什么建议吗?
from collections import defaultdict
class LDict(dict):
def __init__(self, *args, **kwargs):
'''
This is a read-counting dictionary
'''
super().__init__(*args, **kwargs)
self._lookup = defaultdict(lambda : 0)
def __getitem__(self, key):
retval = super().__getitem__(key)
self._lookup[key] += 1
return retval
def __setitem__(self, key, value):
super().__setitem__(key, value)
self._lookup[key] = self._lookup.default_factory()
def __delitem__(self, key):
super().__delitem__(self, key)
_ = self._lookup[key]
del self._lookup[key]
def list_unused(self):
return [key for key in self if self._lookup[key] == 0]
l = LDict(a='apple', b='bugger')
print({**l, **l})
print(l.list_unused())
_ = l['a']
print(l.list_unused())
您需要覆盖更多方法。访问 不是 通过 __getitem__()
集中:其他方法如 copy()
、items()
等无需通过 __getitem()__
即可访问密钥。我假设 **
运算符使用 items()
,但您将需要处理所有方法以跟踪每次访问。在许多情况下,您将不得不做出判断。例如,__repr__()
算作访问吗?返回的字符串包含格式化的每个键和值,所以我认为它确实如此。
我建议重写这些方法中的所有,因为您还必须对作业进行簿记。
def __repr__(self):
def __len__(self):
def __iter__(self):
def clear(self):
def copy(self):
def has_key(self, k):
def update(self, *args, **kwargs):
def keys(self):
def values(self):
def items(self):
编辑:显然这里有一个与您的实施直接相关的重要警告。如果 LDict
扩展 dict
,则在字典解包 { **l, **l}
期间调用这些方法中的 none。
显然您可以遵循建议 here,并在不扩展 dict
的情况下实施 LDict。这对我有用:
from collections import MutableMapping
class LDict(MutableMapping):
def __init__(self, *args, **kwargs):
'''
This is a read-counting dictionary
'''
self._lookup = defaultdict(lambda : 0)
self.data = {}
if kwargs:
self.data.update(kwargs)
def __getitem__(self, key):
retval = self.data[key]
self._lookup[key] += 1
return retval
def __setitem__(self, key, value):
self.data[key] = value
self._lookup[key] = self._lookup.default_factory()
def __delitem__(self, key):
del self.data[key]
_ = self._lookup[key]
del self._lookup[key]
def items(self):
print('items is being called!')
yield from self.data.items()
def __iter__(self):
print('__iter__ is being called!')
yield from self.data
def __len__(self):
return len(self.data)
def list_unused(self):
return [key for key in self if self._lookup[key] == 0]
l = LDict(a='apple', b='bugger')
print({**l, **l})
print(l.list_unused())
_ = l['a']
print(l.list_unused())
产生输出:
__iter__ is being called!
__iter__ is being called!
{'b': 'bugger', 'a': 'apple'}
__iter__ is being called!
[]
__iter__ is being called!
[]
(我只实现了最低限度以使示例工作,如果您希望计数正确,我仍然建议实现我列出的方法集!)
所以我猜你的问题的答案是你必须
- 实施
__iter__(self)
方法 - 不要继承自
dict()
。