简而言之:检查 python 中的一个巨大列表是否已更改的快速方法是什么? hashlib
需要一个缓冲区,并且构建该列表的字符串表示是不可行的。
总而言之:我有一大堆代表数据的字典。我对这些数据进行了大量分析,但所有分析都需要一些元数据方面,即。主题集(列表中的每个字典都有一个主题键,有时我只需要一个包含数据集中存在数据的所有主题的列表。)。所以我想实现以下内容:
class Data:
def __init__(self, ...):
self.data = [{...}, {...}, ...] # long ass list of dicts
self.subjects = set()
self.hash = 0
def get_subjects(self):
# recalculate set of subjects only if necessary
if self.has_changed():
set(datum['subject'] for datum in self.data)
return self.subjects
def has_changed(self):
# calculate hash of self.data
hash = self.data.get_hash() # HOW TO DO THIS?
changed = self.hash == hash
self.hash = hash # reset last remembered hash
return changed
问题是如何实现has_changed
方法,或者更具体地说,get_hash
(每个对象已经有一个__hash__
方法,但是通过默认它只返回对象的 id
,当我们将一个元素附加到列表时它不会改变)。
最佳答案
一种更复杂的方法是使用代理数据元素而不是原生列表和字典,后者可以标记对其属性的任何更改。为了使其更加灵活,您甚至可以编写回调以在发生任何更改时使用。
因此,假设您只需要处理数据结构上的列表和字典 - 我们可以使用继承自 dict 的类,并在访问对象上的任何数据更改方法时使用回调来处理列表。方法的完整列表在http://docs.python.org/reference/datamodel.html
# -*- coding: utf-8 -*-
# String for doctests and example:
"""
>>> a = NotifierList()
>>> flag.has_changed
False
>>> a.append(NotifierDict())
>>> flag.has_changed
True
>>> flag.clear()
>>> flag.has_changed
False
>>> a[0]["status"]="new"
>>> flag.has_changed
True
>>>
"""
changer_methods = set("__setitem__ __setslice__ __delitem__ update append extend add insert pop popitem remove setdefault __iadd__".split())
def callback_getter(obj):
def callback(name):
obj.has_changed = True
return callback
def proxy_decorator(func, callback):
def wrapper(*args, **kw):
callback(func.__name__)
return func(*args, **kw)
wrapper.__name__ = func.__name__
return wrapper
def proxy_class_factory(cls, obj):
new_dct = cls.__dict__.copy()
for key, value in new_dct.items():
if key in changer_methods:
new_dct[key] = proxy_decorator(value, callback_getter(obj))
return type("proxy_"+ cls.__name__, (cls,), new_dct)
class Flag(object):
def __init__(self):
self.clear()
def clear(self):
self.has_changed = False
flag = Flag()
NotifierList = proxy_class_factory(list, flag)
NotifierDict = proxy_class_factory(dict, flag)
2017年更新
一个人生活和学习:本地列表可以通过调用绕过魔术方法的本地方法来更改。傻瓜证明系统是相同的方法,但继承自 collections.abc.MutableSequence
相反,将 native 列表保留为代理对象的内部属性。
关于python - 检查python中的大列表是否已更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9871169/