如何将csv文件的内容读入一个类,每个csv行作为一个类实例

时间:2017-11-22 23:54:22

标签: python list class csv oop

我是一名Python新手,我几天都在努力完成课堂作业。我有一个包含数据的csv文件:

id,latitude,longitude,city,label,yr1970,yr1975,yr1980,yr1985,yr1990,yr1995,yr2000,yr2005
1,35.6832085,139.8089447,Tokyo,Tokyo,23.3,26.61,28.55,30.3,32.53,33.59,34.45,35.62

此文件中大约有40行,每行包含与世界城市相关的数据。如您所见,顶行是标题。我应该在Python中创建一个类并将csv文件读入类中,其中每一行都成为该类的一个实例。然后我将类实例存储在列表中。我已经能够创建一个存储所有数据的实例,但我似乎无法为每一行创建一个实例(我显然不想手动执行)。

这是我到目前为止所得到的:

import csv
Cities = []


with open('filepath','rb') as f:
cityList = csv.reader(f)
for row in cityList:
    if row != 'label':
        for row in cityList:
            citysName = row[3]


            class City:

                def __init__(self, cityName=row[3], Label=row[4], Lat=row[1],
                         Lon=row[2], yr1970=row[5], yr1975=row[6], yr1980=row[7],
                             yr1985=row[8], yr1990=row[9], yr1995=row[10], yr2000=row[11],
                             yr2005=row[12], yr2010=row[13]):
                    self.cityName = cityName
                    self.label = Label
                    self.lat = Lat
                    self.lon = Lon
                    self.yr1970 = yr1970
                    self.yr1975 = yr1975
                    self.yr1980 = yr1980
                    self.yr1985 = yr1985
                    self.yr1990 = yr1990
                    self.yr1995 = yr1995
                    self.yr2000 = yr2000
                    self.yr2005 = yr2005
                    self.yr2010 = yr2010

            citysName = City()

            Cities.append(citysName.cityName)
            Cities.append(citysName.label)
            Cities.append(citysName.lat)
            Cities.append(citysName.lon)
            Cities.append(citysName.yr1970)
            Cities.append(citysName.yr1975)
            Cities.append(citysName.yr1980)
            Cities.append(citysName.yr1985)
            Cities.append(citysName.yr1990)
            Cities.append(citysName.yr1995)
            Cities.append(citysName.yr2000)
            Cities.append(citysName.yr2005)
            Cities.append(citysName.yr2010)

        print Cities

同样,我是Python的新手(以及一般的编码),我意识到这段代码并不好,但是我很难找到将csv文件读入Python的技巧类。

5 个答案:

答案 0 :(得分:4)

你可以试试这个:

import csv
class City:
   def __init__(self, row, header):
        self.__dict__ = dict(zip(header, row))

data = list(csv.reader(open('file.csv')))
instances = [City(i, data[0]) for i in data[1:]]

但是,由于您提到有很多行,您可能希望为每个城市创建一个id,作为列表中的字符串表示形式:

import csv
class City:
   def __init__(self, row, header, the_id):
       self.__dict__ = dict(zip(header, row)) 
       self.the_id = the_id
   def __repr__(self):
       return self.the_id

data = list(csv.reader(open('file.csv')))
instances = [City(a, data[0], "city_{}".format(i+1)) for i, a in enumerate(data[1:])]

您的输出将是这样的列表:

[city_1, city_2, city_3...]

任何属性都可以这样调用:

instances[1].latitude

关于您最近的评论,要按城市名称访问城市属性,您可以稍微重新构建instances

instances = {a[3]:City(a, data[0], "city_{}".format(i+1)) for i, a in enumerate(data[1:])}

答案 1 :(得分:1)

一些帮助您清理代码的提示:

  1. 而不是:

    self.yr1970
    

    定义一个列表以跟踪年份及其值:

    tokyo_years = {
        1970: 23.3,
        1975: 26.61,
        # ...
    }
    

    现在将此结构与每个城市配对:

    cities = [
        { 'city': 'Tokyo',     'years': tokyo_years },
        { 'city': 'Vancouver', 'years': vancouver_years },
        # ...
    ]
    
  2. 不要如此深深地筑巢。此外,以下是非常奇怪的:

    for row in cityList:
        if row != 'label':
            for row in cityList:
    

    你正在循环一些东西,然后在循环它时再次循环它......!

  3. 课程属于顶级。这意味着class之前应该有0个空格。

             class City:
    

    应该是:

    class City:
    
  4. 我提到这一切的原因是因为尝试使用凌乱的代码进行任何进一步操作只会导致代码更加混乱。 :)尝试通过以下方式改进您当前的代码:

    1. 使用数据结构(列表,词典)。
    2. 将嵌套代码的级别限制为2个最大值。 (考虑使用函数来帮助你。)
    3. 将课程放在顶层。

答案 2 :(得分:1)

如果您的数据只是一个不可变记录,请使用namedtuple

const app = require('express')();
const https = require('https').Server(options, app);

您可以在不需要第一个值的情况下对行进行切片,然后使用>>> from collections import namedtuple >>> City = namedtuple('City', 'lat lon cityName label ' ... 'yr1970 yr1975 yr1980 yr1985 yr1990 yr1995 yr2000 yr2005 yr2010') 将其解压缩:

*

您只需将此对象添加到城市列表中,而不是每个属性:

>>> row = ['1', '35.6832085', '139.8089447', 'Tokyo', 'Tokyo',
...        '23.3', '26.61', '28.55', '30.3', '32.53', '33.59', '34.45', '35.62', '35.7']

>>> city = City(*row[1:])

>>> city
City(lat='35.6832085', lon='139.8089447', cityName='Tokyo', label='Tokyo',
     yr1970='23.3', yr1975='26.61', yr1980='28.55', yr1985='30.3', yr1990='32.53',
     yr1995='33.59', yr2000='34.45', yr2005='35.62', yr2010='35.7')

将它与列表推导结合在一起,过滤出标签行:

>>> cities.append(city)

答案 3 :(得分:0)

您可以使用csv.DictReader来执行此操作,该csv将每行作为字典返回。它还允许您根据csv文件的第一行或标题行中定义的字段名轻松定义类,而不是将它们硬编码到程序中。

您仍然可以使用" dot"来引用任何记录的字段。语法,例如city.latitudecity.label

下面是Python 2代码。对于Python 3,使用以下命令打开文件:

with open('cities.csv', 'r', newline='') as f:
而不是所显示的内容。

import csv

with open('cities.csv', 'rb') as f:
    reader = csv.DictReader(f)
    fieldnames = reader.fieldnames

    class City:
        def __init__(self, **fields):
            self.__dict__.update(**fields)

        def __repr__(self):  # Added to make printing instances show their contents.
            fields = ', '.join(('{}={!r}'.format(fieldname, getattr(self, fieldname))
                                   for fieldname in fieldnames))
            return('{}({})'.format(self.__class__.__name__, fields))

    Cities = [City(**row) for row in reader]

print(Cities)

示例输入文件的示例输出:

[City(id='1', latitude='35.6832085', longitude='139.8089447', city='Tokyo', label='Tokyo', yr1970='23.3', yr1975='26.61', yr1980='28.55', yr1985='30.3', yr1990='32.53', yr1995='33.59', yr2000='34.45', yr2005='35.62')]

答案 4 :(得分:-1)

import csv


class City:
    def __init__(self, **kwargs):
        self.id = kwargs.get('id')
        self.latitude = kwargs.get('latitude')
        self.longitude = kwargs.get('longitude')
        self.city = kwargs.get('city')
        self.label = kwargs.get('label')
        self.year_1970 = kwargs.get('yr1970')
        self.year_1975 = kwargs.get('yr1975')
        self.year_1980 = kwargs.get('yr1980')
        self.year_1985 = kwargs.get('yr1985')
        self.year_1990 = kwargs.get('yr1990')
        self.year_1995 = kwargs.get('yr1995')
        self.year_2000 = kwargs.get('yr2000')
        self.year_2005 = kwargs.get('yr2005')

    def __str__(self):
        return self.label


if __name__ == '__main__':
    with open('filepath', 'r') as csvfile:
        reader = csv.DictReader(csvfile)

        for row in reader:
            city = City(**row)
            print(city)