不使用第三方模块,如何将CSV数据映射到Python类对象?
问题描述
用户对Python中类/对象与CSV的结合使用存在困惑,现有一个包含26行数据(1行表头,25行数据)的CSV文件,示例数据如下:
id,food,food_print,cal1,cal2,expi1999,expi2000,expi2001 1,bun,bun_bun,45.3434,199.32323,23.3333,45.4444,33.33333 2,burger,burger_bun,45.342343,200.34243,34.3333,0,9 3,pickle,pickle_seed,67.345454,34.3434,34,56,33 4,chicken,chicken_egg,44.34343,43.343343,43,434,34343
已编写部分Python代码,但不知道如何将CSV行数据写入类对象以便后续调用:
class City(object): def __init__(self, food = 'n/a', foodprint = 'n/a', cal1 = -999, cal2 = -999, expi1999 = -999, expi2000 = -999, expi2001 = -999): self.food = food self.foodprint = foodprint self.cal1 = cal1 self.cal2 = cal2 self.expi1999 = expi1999 self.expi2000 = expi2000 self.expi2001 = expi2001 meals = [] foodfile = open('Food.csv', 'rt') headers = foodfile.readline().strip().split(',') headers = headers.split(',') for line in foodfile: foodfields = foodfile.readline().strip().split(',')
解决方案
先修正原代码的两处错误
- headers重复split问题:
headers = foodfile.readline().strip().split(',')已经把表头拆成了列表,后续headers.split(',')会报错(列表没有split方法),直接删掉这行重复代码。 - 循环跳行问题:
for line in foodfile已经在逐行读取文件,内部再调用foodfile.readline()会跳过一行数据,直接用line.strip().split(',')处理当前行即可。
完整实现代码
class City(object): def __init__(self, food='n/a', foodprint='n/a', cal1=-999, cal2=-999, expi1999=-999, expi2000=-999, expi2001=-999): self.food = food self.foodprint = foodprint # 把字符串转为数值类型,方便后续计算 self.cal1 = float(cal1) if cal1 != '' else -999 self.cal2 = float(cal2) if cal2 != '' else -999 self.expi1999 = float(expi1999) if expi1999 != '' else -999 self.expi2000 = float(expi2000) if expi2000 != '' else -999 self.expi2001 = float(expi2001) if expi2001 != '' else -999 # 添加__repr__方法,方便查看对象内容 def __repr__(self): return f"City(food='{self.food}', foodprint='{self.foodprint}', cal1={self.cal1})" meals = [] # 用with语句自动管理文件关闭,避免资源泄漏 with open('Food.csv', 'rt') as foodfile: # 读取并处理表头 headers = foodfile.readline().strip().split(',') # 逐行处理数据 for line in foodfile: # 跳过空行 if not line.strip(): continue foodfields = line.strip().split(',') # 注意CSV里的id列未在类中使用,从第2个元素开始匹配类的参数 meal = City( food=foodfields[1], foodprint=foodfields[2], cal1=foodfields[3], cal2=foodfields[4], expi1999=foodfields[5], expi2000=foodfields[6], expi2001=foodfields[7] ) meals.append(meal) # 后续调用示例:遍历所有meal对象,访问属性 for meal in meals: print(f"食物:{meal.food},1999年指数:{meal.expi1999}")
关键说明
- 类型转换:CSV读取的内容默认是字符串,需要把数值型字段转为
float(或int),避免后续计算时出现类型错误。 - 字段对应:注意CSV表头的
food_print和类属性foodprint的命名差异,要严格一一对应,避免传参错误。 - 调试便利:自定义
__repr__方法后,打印对象时能直接看到核心属性,方便调试和验证数据是否正确写入。
内容的提问来源于stack exchange,提问作者Sarukira
相关产品推荐
相关产品推荐

