如何在python中从文件中创建元组列表

时间:2014-04-22 21:00:45

标签: python tuples knapsack-problem

好的我有一个像这样的文件。

panite,1,1800
ruby,2,100
diamond,0.75,900
emerald,3,250
amethyst,2,50
opal,1,300
sapphire,0.5,750
benitoite,1,2000
malachite,1,60

我们的老师给了我们使用try / except的代码来帮助我们打开文件。我需要打开文件并读取每一行,并使每一行成为一个元组,然后将其放入一个列表中。该列表应该是最后一个数字除以中间数字,然后该值后跟gem的名称(中间数字是gem的克拉)。我遇到的问题是我甚至无法从文件中创建列表。这就是我试图打开它而没有取得多大成功。

def main():
    fileFound = False
    while not fileFound:
        fileName = input('File name containing jewel data: ')
        try:
            dataFile = open(fileName, "r")
            fileFound = True
            knapsack()
        except:
            print ('Could not find that file -- try again')

def knapsack():
    list = dataFile.readline()

当我在def knapsack()下将其更改为简单的printstatement时,我确实取得了一些成功,它会打印一些像2 + 2这样简单的东西,但是当我尝试制作一个列表时,它会给我一个除了错误代替。这是我的第一个编程课程,所以对此的任何见解都将受到赞赏。

5 个答案:

答案 0 :(得分:1)

def make_jewel(line):
    name, carats, price = line.split(",")
    return (float(price)/float(carats), name)

def main():
    while True:
        file_name = input('File name containing jewel data: ')
        try:
            with open(file_name) as inf:
                data = [make_jewel(line) for line in inf]
            break
        except FileNotFoundError:
            print('Could not find that file -- try again')

main()

和一些评论:

  • except:没有指定的异常类型(也称为"裸异常"),因为它捕获所有内容而不受欢迎。您应该指定您希望看到的异常类型,并且只处理这些异常;如果你抓住了所有东西并且完全出乎意料的事情失败了(即ComputerOnFireError!)你将永远不会发现它。

  • 首选使用with打开文件,因为它可以确保文件始终正常关闭。

  • 在文本模式下打开文件时,可以逐行迭代;这是处理文件的最常用方法。

  • 当你.split()一个字符串时,你会得到一个字符串列表。在对棋子进行数学运算之前,您必须使用int()float()将它们从字符串转换为数值。

希望有所帮助。

答案 1 :(得分:0)

使用csv模块将行读取为csv行。

import csv

def knapsack(datafile):
    output_data = []
    csv_reader = csv.reader(datafile, delimiter=',')
    for row in csv_reader:
        output_data.append(tuple(row))
    return output_data

这将为您提供output_data

[('panite', '1', '1800'),
 ('ruby', '2', '100'),
 ('diamond', '0.75', '900'),
 ('emerald', '3', '250'),
 ('amethyst', '2', '50'),
 ('opal', '1', '300'),
 ('sapphire', '0.5', '750'),
 ('benitoite', '1', '2000'),
 ('malachite', '1', '60')]

这是一个元组列表。这解决了从文件中创建列表的问题。现在,你应该这样做:

  • 元组中的数字是字符串。在进行描述中提到的算术运算之前,您需要确保you convert them to int
  • output_data作为参数传递给一个单独的函数,该函数执行您在问题中提到的算术函数。此函数应构建输出列表。

对您的代码进行一些评论:

  • 您可以在main函数中定义文件句柄,但不要传递它 到knapsack函数。但你在背包中引用它 功能,不会给你你想要的。所以你需要通过 datafile文件句柄作为knapsack函数的参数。您可以通过以下方式替换main方法中的这一行:

    knapsack()
    

    knapsack(datafile)
    
  • list是Python中内置类型的名称。因此,明智的做法是不要将它用作代码中变量的名称。

答案 2 :(得分:0)

你应该:

  • dataFile发送到您的knapsack功能。
  • except更改为except IOError,以避免捕获 希望查看的例外情况。
  • 关闭文件(考虑使用with打开文件以避免必须明确关闭它

    try:
        dataFile = open(fileName, "r")
        fileFound = True
        knapsack(dataFile)
        dataFile.close()
    except IOError:
        print ('Could not find that file -- try again')
    

如果您从一开始就使用过except IOError,那么您会看到此错误:

Traceback (most recent call last):
  ...
  ...
NameError: global name 'dataFile' is not defined

knapsack不知道dataFile是什么,因此错误。使用try..except时,始终捕获特定的例外。如果您不知道抛出了哪个错误 - 在python解释器中编写代码之前重现它(例如,尝试打开一个不存在的文件,并注意抛出IOError)。

knapsack中,您需要从readline更改为readlines

def knapsack(dataFile):
    list = dataFile.readlines()

您还应考虑使用其他答案中提到的csv模块来处理数据。

答案 3 :(得分:0)

如果我正确理解您的问题,则例外是因为在dataFile函数中找不到knapsack变量。我建议在Python中学习范围规则,或者阅读this关于该主题的优秀章节(或在网上搜索此主题!)。

我推荐的另一件事是不处理所有异常,因为您已经在代码段中显示了这些异常。 Here's why

固定代码可能如下所示:

def main():
    fileFound = False
    while not fileFound:
        fileName = raw_input('File name containing jewel data: ')
        try:
            dataFile = open(fileName, "r")
            fileFound = True
            knapsack(dataFile)
        except IOError:
            print ('Could not find that file -- try again')

def knapsack(dataFile):
    list = dataFile.readline() ### Or you want `readlines()` ?
    print list ### Print to let you know that it works
    # return list ### ???

if __name__ == '__main__':
    main()

答案 4 :(得分:0)

我会使用list comprehensions

更多地使用Pythonic
def knapsack(dataFile):
    with open(dataFile, 'r') as fp:
        lines = [line.strip() for line in fp]

    data = [tuple(line.split(',')) for line in lines]

    return data

您要将背包传递给文件的路径。