Python - 将文件导入NamedTuple

6 投票
3 回答
8697 浏览
提问于 2025-04-16 16:39

最近我有个关于数据类型的问题。
从那以后,我一直在尝试使用命名元组(效果好坏不一)。

我现在遇到的问题是:
- 如何从文件中导入行到新的元组中,
- 如何将用空格、制表符(或者其他分隔符)分开的值导入到元组的指定部分?

比如:

Monday  8:00    10:00   ETR_28135   lh1n1522    Computer science    1     
Tuesday 12:00   14:00   ETR_28134   lh1n1544    Geography EA    1  

第一行应该放到元组的第一个位置,也就是元组[0]。第一个数据:元组[0].day;第二个:元组[0].start;依此类推。
当新的一行开始时(也就是两个制表符\t),就开始一个新的元组,比如元组[1]。

我用这个来分隔数据:

with open(Filename) as f:
    for line in f:
        rawData = line.strip().split('\t')  

而其余的逻辑还没有完成(填充元组的部分)。

(我知道,这个问题和之前的问题都很基础。不过,希望这些能帮助到其他人。如果你觉得这不是一个真正的问题,或者太简单了,可以投票关闭。谢谢你的理解。)

3 个回答

3

这里有一个简单的方法来处理这些事情。首先,声明一个行项目的类:

fields = "dow", "open_time", "close _time", "code", "foo", "subject", "bar"
Item = namedtuple('Item', " ".join(fields)) 

接下来的部分是在你的循环里面。

# this is what your raw data looks like after the split:
#raw_data = ['Monday', '8:00', '10:00', 'ETR_28135', 'lh1n1522', 'Computer science', '1']
data_tuple = Item(**dict(zip(fields, raw_data)))

现在慢慢来解释:

  • zip(fields, raw_data) 会创建一个成对的列表,比如 [("dow", "Monday"), ("open_time", "8:00"),..],就是把字段和原始数据配对在一起。
  • 然后 dict() 会把这个成对的列表变成一个字典,像这样 {"dow": "Monday", "open_time": "8:00", ..}
  • 接着 ** 会把这个字典当作一堆关键字参数传给 Item 的构造函数,相当于 Item(dow="Monday", open_time="8:00",..)

所以你的项目就是命名元组,所有的值都是字符串。

补充:

如果字段的顺序不会改变,你可以更简单地做到这一点:

data_tuple = Item(*raw_data)

这利用了文件中字段的顺序和 Item 定义中参数的顺序是匹配的这个事实。

3

如果你想使用命名元组(NamedTuple),可以参考一下Python文档中稍微修改过的例子:

MyRecord = namedtuple('MyRecord', 'Weekday, start, end, code1, code2, title, whatever')

import csv
for rec in map(MyRecord._make, csv.reader(open("mycsv.csv", "rb"), delimiter='\t')):
    print rec.weekday
    print rec.title
    # etc...
12

这种数据库文件被称为“逗号分隔值”,虽然实际上它们并不是用逗号分开的。Python有一个很方便的库叫做csv,可以让你轻松读取这样的文件。

下面是一个稍微修改过的文档中的例子

csv.register_dialect('mycsv', delimiter='\t', quoting=csv.QUOTE_NONE)
with open(filename, 'rb') as f:
    reader = csv.reader(f, 'mycsv')

通常你一次处理一行数据。如果你需要把整个文件放在一个元组中,可以这样做:

t = tuple(reader)

编辑

如果你想通过字段名来访问数据,可以使用csv.DictReader,不过我不太清楚具体怎么用,也没法在这里测试。

编辑 2

关于命名元组的内容,我有点跟不上了。这里有一个很好的例子,展示了命名元组如何与csv模块一起使用:

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

import csv
for line in csv.reader(open("employees.csv", "rb")):
    emp = EmployeeRecord._make(line)
    print emp.name, emp.title

撰写回答