CSV列表(行,列)到Python的变量列表(名称,值)

时间:2013-01-04 23:25:50

标签: python variables csv variable-assignment

如何将包含3个数据(在相邻列中)的名称的CSV文件转换为创建的类的变量,该类将相邻的数据作为参数?

下面的代码似乎是为了创建对象,但列表是对象位置而不是我想要的名称。

有人可以帮忙吗?

class Teams(object):
  def __init__(self, TeamName, FT, FG, Three):
    self.TeamName = TeamName
    self.FT = FT
    self.FG = FG
    self.Three = Three

North_Carolina = Teams("North Carolina", .643,.458,.371)

print North_Carolina.TeamName, North_Carolina.FT, North_Carolina.FG,North_Carolina.Three
## works fine but manually typed data

def getData(fname):  ##fname is a csv file with 4 columns and 348 rows. One header row.
    Data = open(fname, 'r')
    TeamList = []
    #print Data.read() ## prints a list with comma separated values and line return
    for line in Data:
      info = line.split(",") ##info is a list of lists of Data with Team,FT,FG,3P
      name = info[0]
      FT = info[1]
      FG = info[2]
      Three = info[3]
      newTeam = (name, FT, FG, Three)
      newTeam2 = Teams(newTeam[0],newTeam[1],newTeam[2],newTeam[3]) ##newTeam2 is an object. 
      TeamList.append(newTeam2)
    print TeamList[1].TeamName ##prints North Carolina list[0] print header
    print TeamList #prints list of object locations but not objects themselves

getData("Stats 01-04-2013.csv")

第一个print语句打印:

North Carolina

第二个print语句打印:

[<__main__.Teams object at 0x02953230>, <__main__.Teams object at 0x029532B0>, etc etc

4 个答案:

答案 0 :(得分:1)

对象位置 对象的打印方式。严格来说,在列表中每个元素的str调用repr上调用listrepr。默认情况下,repr(team)对象上的Teams将返回<main.Teams object at 0x02953230>之类的内容。您可以通过在__repr__类上定义Teams方法来覆盖它。但是,这听起来不像你想要的那样。

如果TeamListTeams个对象的列表,并且您想将其转换为TeamName个成员的列表,则只需使用list comprehension进行转换即可:

TeamNameList = [team.TeamName for team in TeamList]

请注意,这仍然不是您想要打印出来的:

>>> print TeamNameList
['North Carolina', 'South Carolina', 'West Carolina', 'East Carolina', 'Underground Carolina', 'Cloud-level Carolina', 'Past Carolina', 'Future Carolina'] # those are all states, right?

你可能想要这样的东西:

>>> print ', '.join(TeamNameList)
North Carolina, South Carolina, West Carolina, East Carolina, Underground Carolina, Cloud-level Carolina, Past Carolina, Future Carolina

来自您的评论:

  

后来有一个函数simGame(teamA,Teamb)

     

我看到了实例,但是我不知道如何在第二个函数中调用它们。我曾打算用名字给他们打电话。在我给出的示例中,North_carolina可以传递给后者(未显示的函数),并且可以对数据运行计算

我想我明白你想要什么。您希望能够模拟北卡罗来纳州和南卡罗来纳州之间的游戏,只需拥有TeamList

为此,您可能想要创建dict,将名称映射到Teams对象,如下所示:

TeamDict = {team.TeamName: team for team in TeamList}

现在,您可以这样做:

simGame(TeamDict['North Carolina'], TeamDict['South Carolina'])

现在,simGameTeams类的北卡罗来纳州和南卡罗来纳州的实例作为其teamAteamB参数,因此它可以执行以下操作: :

def simGame(teamA, teamB):
    scoreA = int(teamA.FT * 1 * 20) + int(teamA.FG * 2 * 40) + int(teamA.Three * 3 * 10)
    scoreB = int(teamB.FT * 1 * 20) + int(teamB.FG * 2 * 40) + int(teamB.Three * 3 * 10)
    if scoreA > scoreB:
        print 'Home team {} beats visitor {} by {}!'.format(teamA.TeamName,
                                                            teamB.TeamName,
                                                            scoreA - scoreB)
    else:
        print 'Visitors {} win by {} over {} at home!'.format(teamB.TeamName,
                                                              scoreB - scoreA,
                                                              teamA.TeamName)

这就是你想要的吗?

其他一些评论:

您也可以使用map执行与列表推导相同的操作,这样可以避免必须两次编写team,但这也意味着您无法使用正常的表达式语法:

TeamNameList = map(operator.attrgetter('TeamName'), TeamList)

或者您可以将maplambda一起使用以取回表达式语法...并重复team

TeamNameList = map(lambda team: team.teamName, TeamList)

但是对于这样的情况,列表理解通常被认为是做到这一点的pythonic方式。 (另外,如果你去Python 3,它不会改变,而maplist更改为迭代器,这意味着print TeamNameList会给你<builtins.map at 0x108022350>之类的东西......但', '.join(TeamNameList)仍然可以使用。)

作为旁注,在标准(PEP 8)Python样式中,通常只有类在TitleCase中,而变量和属性在lower_case中。如果您真的喜欢CamelCase,那么您可以使用lowerFirstCamelCase,但使用TitleCase会让人们阅读您的代码,他们将立即尝试找出TeamName类的定义位置。另请参阅bvukelic的评论。

另一方面,你似乎做了很多重复的代码,我不确定原因:

  name = info[0]
  FT = info[1]
  FG = info[2]
  Three = info[3]
  newTeam = (name, FT, FG, Three)

您只是将info复制到newTeam;为什么要添加所有那些永远不会再次使用的中间变量?

  newTeam2 = Teams(newTeam[0],newTeam[1],newTeam[2],newTeam[3])

你可以用以下方式替换所有这些:

  newTeam2 = Teams(info[0],info[1],newTeam[2],newTeam[3])

甚至:

  newTeam2 = Teams(*info)

如果你需要在某个你没有向我们展示的单独变量,那很好,但你仍然不可能需要newTeam;这样做:

  newTeam2 = Teams(name, FT, FG, Three)

答案 1 :(得分:1)

我会使用csv模块执行类似的操作,主要基于module documentation中的示例。可能需要调整,这只是我的头脑,但在处理这些类型的文件时我总是使用相关的。

import csv

with open('teams.csv', 'rb') as csvfile:
    teamreader = csv.reader(csvfile)
    for row in teamreader:
        newTeam = Teams(row[0], row[1], row[2], row[3])
        teamList.append(newTeam)

答案 2 :(得分:0)

只是为了解释这个问题的另一种解释:

class Teams(object):
    def __init__(self, TeamName, FT, FG, Three):
        self.TeamName = TeamName
        self.FT = FT
        self.FG = FG
        self.Three = Three

    def __str__(self):
        return str(self.TeamName)

    def __repr__(self):
        return self.__unicode__()

每当您打印对象时,它都会显示为TeamName

答案 3 :(得分:0)

如何显示类实例是通过为其提供自定义__str__()和/或__repr__()转换方法来控制的。这是编写代码的一种方式,并使其遵循PEP 8 Style Guide中的许多建议。您也可以使用csv模块阅读文件来改进或简化它,如其他人已经建议的那样,但我会主要关注您问题中显示的代码。

class Team(object):
    def __init__(self, team_name, free_throws, field_goals, three_pointers):
        self.team_name = team_name
        self.free_throws = free_throws
        self.field_goals = field_goals
        self.three_pointers = three_pointers

    def __repr__(self):
        return '{}({!r}, {}, {}, {})'.format(self.__class__.__name__,
                                             self.team_name, self.free_throws,
                                             self.field_goals, self.three_pointers)

def get_data(fname):  # fname is a csv file with 4 columns and one header row
    teams = []
    with open(fname, 'rt') as csv_file:
        csv_file.next()  # skip header row
        for line in csv_file:
            info = line.strip().split(",")
            teams.append(Team(*info))  # create a Team instance and add it to list
    return teams

print get_data("Stats 01-04-2013.csv")

示例输出:

[Team('North Carolina',  .643,  .458,  .371), Team('Michigan',  .543,  .358,  .271)]