使用循环创建namedtuple的实例作为数据库记录

时间:2018-08-01 14:20:39

标签: python numpy namedtuple

我想知道是否可以在循环中实例化namedtuple。我遇到的问题是我有单个文件(> 500),每个文件都应该是namedtuple的一个实例,并且我想使用文件名来访问记录。 例如说我有一个具有三个属性的namedtuple

from collections import namedtuple
import pandas as pd
record_ids=["record1","record2"]
reads=namedtuple("reads", "id length text")
for record in record_ids:
    records=pd.read_table(record+".txt",dtype=None, header='infer')
    text=records.iloc[0:100]
    entry=[record,len(text),text)
    varname=reads._make(entry)

其中record_ids是保存在列表中的文件名。 我希望将varname作为文件名。因此,如果我的文件是record1.txt,则可以在任何地方访问record1.length。 我的问题是: 1)这是明智的做法吗?我需要对较大的数据集执行数学运算,这不是为了保持记录。 2)这可能吗?还是有更多的pythonic替代方法?

非常感谢您的任何建议!

1 个答案:

答案 0 :(得分:0)

分配给varname可能会给您带来麻烦,尤其是因为它不会进行迭代,并且您最终将得到一个可引用的元组,而不是希望查看的大量元组。

您可能需要考虑将每个reads()类实例化为对象集合。

对于对象列表,该对象不需要名称,因此您不需要变量,仅收集列表类型就足够了。如果您知道记录ID,则以后遍历记录的代价是无法引用一个。用变量命名每个变量将成倍恶化。

防止出现变量膨胀并能够通过记录ID引用每个读取对象的解决方案是字典。这似乎与您的代码现在试图通过随后读取以读取记录id的方式尝试显示元组的身份一致,在您的情况下,该记录id尚未唯一,因为您所附加的只是“ .txt”,并且您的ID值似乎在列表中。该列表似乎似乎可以从列表理解中受益。

在任何情况下,对于对记录的命名引用,字典都将标有变量。您的记录ID可以选择在该类中,以防万一您出于某种原因将记录移至列表并与字典键分离的情况... 将记录id用作字典键,以下内容大致近似于数据模型的最终结果: dict_varname = {'record_id_unique':}

您可以使用namedtuple ._replace()方法重用您的原型namedtuple'reads'。原型永远不必进入列表,只需将其作为功能蓝图就可以访问。在您的示例中,它已经被标记为变量“ reads”。您可以给变量命名不同的名称,但是可以这样工作。类名在namedtuple声明的括号内用引号引起来。

from collections import namedtuple as nt
reads = nt('reads', ('id', 'length', 'text'))

即使在创建实例时,该原型的某些项目也可以重复使用。

my_record_list = []
for _ in range(len(list_of_records)):
    my_record_list.append(reads._replace(reads, id='record'+_, length=len(the_text), text=the_text))

._ replace将保留您不会覆盖的值,使您最初分配给原型的值具有灵活的默认值(该类的声明/实例读为“ reads”)。

my_record_dict = {}
data = ['so_long', 'lots_of_data']
    for recordid in recordid_list:
        for data in recordid_datalist:
            my_record_dict[recordid] = reads('reads', length=len(data[0]), text=data[1])

要读取数据,可以遍历键以提取对象(值)并从中读取所需的字段。您还可以更轻松地选择一条记录,而不必搜索所有记录以查找要查找的值的元组索引。字典键是不可变的,与遍历列表对象的索引相比,可以更快地找到这些哈希值。

如果到目前为止,您都遵循默认值,那么其余部分将“修复”上述问题,即依靠对._replace值的读取并在循环中创建新实例,而无需重复所有值。如上所示,您可以执行以下操作,但是._replace和语法可以轻松实现,即要求所有值。有关新实例中“读取”如何成为值,请参见上文。棘手的吧?

reads._replace(reads (id='123', length=999999, text='why?'))

更好地创建一个实例,该实例将保留您的默认值,并由此创建新实例:

proto = reads('123', 999999, 'why not') # your default values on which to build
print(proto)

在标签下进行制作的最终示例。当您要使用循环中的替换值附加新实例时,请删除标签:

k = proto._replace(id=34)
print(k)

我希望这会有所帮助。