像字典一样搜索namedtuple

9
为了节省内存和避免冗余的数据库存储(是的,可能会进行预先优化),我使用namedtuple而不是字典。
但是我需要搜索记录的集合,我的字典方法是:
import operator
def query(D,key,val, keynotfound=None):
    '''
    D:  a list of dictionaries  (but I want it to be namedtuples)
    key:  the key to query
    val:  the value to search for
    keynotfound:  value if key is not found

    Returns elements in D such that operator(D.get(key,None), val) is true
    '''
    op = operator.eq
    def try_op(f,x,y):
        try:
            return f(x,y)
        except Exception, exc:
            return False

    return (x for x in D if try_op(op, x.get(key,keynotfound),val))

无法在namedtuple上工作 如何子类化namedtuple以使其像字典一样可搜索? 并且,并非每个实例都包含与查询键/字段相同的键/字段,因此我需要跳过该行而不是抛出key/attr错误。


我希望这个查询函数能够适用于两种数据类型,因此我认为我会子类化namedtuple并添加一个“get”方法来调用getattr,以便接口保持不变......有什么问题吗? - Dewey
3个回答

16
我认为你可以使用getattr来查看字段是否存在,如果不存在则引发异常或返回默认值。
例如,基于namedtuple文档的说明:
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])

# An instance of the namedtuple
p = Point(1, 2)

In [1]: getattr(p, "x")
Out[1]: 1

In [2]: getattr(p, "z")
...
AttributeError: 'Point' object has no attribute 'z'

In [3]: getattr(f, "z", None)
Out[3]: None

1
最佳解决方案是调用vars(p),假设p是你的namedtuple实例。这将给出一个collections.OrderedDict,你可以像普通字典一样使用它。

2
从3.4版本开始不再适用,因为namedtuple不再实现__dict__。应该使用namedtuple的_asdict方法。 - TakingItCasual

1

试试这个:

return (x for x in D if try_op(op, getattr(x,key,keynotfound),val))

getattr 函数与字典元素的 get 方法类似,用于获取属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接