从 namedtuple 记录结构中检索数据失败

Retrieving data from namedtuple record structure fails

我需要创建一个查找 table 来存储表格数据并根据多个字段值检索记录。

我找到了一个示例 post # 15418386,它几乎可以满足我的需要,但是无论传递的参数如何,它总是 returns 相同的记录。 我在这个 post 的底部列出了代码,在 casr 中 link 不起作用。

我已经通过使用 IDE 中的调试器(我使用的是 PyCharm)验证了文件被正确读取并且数据 table 也被正确填充。 =14=]

代码中包含的测试数据为:

name,age,weight,height
Bob Barker,25,175,6ft 2in
Ted Kingston,28,163,5ft 10in
Mary Manson,27,140,5ft 6in
Sue Sommers,27,132,5ft 8in
Alice Toklas,24,124,5ft 6in

函数总是returns最后一条记录,我相信问题出在这几行代码中。但是我不明白它是如何工作的。

matches = [self.records[index]
            for index in self.lookup_tables[field].get(value, []) ]
return matches if matches else None

我想了解代码应该如何工作,以便我可以编辑它以便能够搜索多个参数。

原码:

from collections import defaultdict, namedtuple
import csv
class DataBase(object):
    def __init__(self, csv_filename, recordname):
        # read data from csv format file int list of named tuples
        with open(csv_filename, 'rb') as inputfile:
            csv_reader = csv.reader(inputfile, delimiter=',')
            self.fields = csv_reader.next() # read header row
            self.Record = namedtuple(recordname, self.fields)
            self.records = [self.Record(*row) for row in csv_reader]
            self.valid_fieldnames = set(self.fields)
        # create an empty table of lookup tables for each field name that maps
        # each unique field value to a list of record-list indices of the ones
        # that contain it.
        self.lookup_tables = defaultdict(lambda: defaultdict(list))

    def retrieve(self, **kwargs):
        """Fetch a list of records with a field name with the value supplied
           as a keyword arg ( or return None if there aren't any)."""

        if len(kwargs) != 1:
            raise ValueError(
            'Exactly one fieldname/keyword argument required for function '
            '(%s specified)' % ', '.join([repr(k) for k in kwargs.keys()])
            )

        field, value = kwargs.items()[0]        # get only keyword arg and value
        if field not in self.valid_fieldnames:
            raise ValueError('keyword arg "%s" isn\'t a valid field name' % field)
        if field not in self.lookup_tables:     # must create field look up table
            for index, record in enumerate(self.records):
                value = getattr(record, field)
                self.lookup_tables[field][value].append(index)

        matches = [self.records[index]
                   for index in self.lookup_tables[field].get(value, []) ]
        return matches if matches else None


if __name__ == '__main__':
    empdb = DataBase('employee.csv', 'Person')
    print "retrieve(name='Ted Kingston'):", empdb.retrieve(name='Ted Kingston')
    print "retrieve(age='27'):", empdb.retrieve(age='27')
    print "retrieve(weight='150'):", empdb.retrieve(weight='150')

变量 value 在以下 if .. for .. 块中被覆盖:

field, value = kwargs.items()[0]   # <--- `value` defined

...

if field not in self.lookup_tables:
    for index, record in enumerate(self.records):
        value = getattr(record, field)  # <--- `value` overwritten
        self.lookup_tables[field][value].append(index)

所以,value指的是最后一条记录的值。您需要使用其他名称以防止此类覆盖。

if field not in self.lookup_tables:
    for index, record in enumerate(self.records):
        v = getattr(record, field)
        self.lookup_tables[field][v].append(index)