1

我正在制作一个抽认卡程序,其中我获取一个包含几列的文本文件,例如英语单词、法语等效、性别、单词类型等。我的想法是创建一个循环来读取文本文件的每一行,用制表符分隔,并为每一行创建一个用户定义的 Word 对象的实例。

在下面的代码块中,我导入文本文件,将其处理成一个列表,然后尝试创建一个先前定义的对象的实例:Word。我希望该对象的名称在列表中具有第二项,以便它易于搜索,但它不允许我这样做,请有人帮我提供代码:

    file = (open('dictionary.txt', 'r')).readline()
    import re
    line_list = re.split(r'\t', file.rstrip('\n')) 

    line_list[1] = Word(line_list[0], line_list[1], line_list[2], line_list[3]) 
4

5 回答 5

3

创建一个dict实例并使用列表的第二项作为键。创建动态变量是个坏主意。

import re
instance_dict = {}
with open('dictionary.txt') as f:
    for line in f:
        line_list = re.split(r'\t', line.rstrip('\n')) 
        instance_dict[line_list[1]] = Word(*line_list[:4]) 

为什么with声明

with处理文件对象时最好使用关键字。这样做的好处是文件在其套件完成后正确关闭,即使在途中引发异常也是如此。

于 2013-11-11T20:44:08.197 回答
1

您还可以使用该csv模块:

import csv

instances = {}
with open('dictionary.txt', 'rb') as f:
    reader = csv.reader(f, delimiter='\t')
    instances = {line[1]: Word(*line) for line in reader}
于 2013-11-11T20:48:48.857 回答
0

根据对您的要求的一些澄清,您可能有一个合适的解决方案

“我的想法是创建一个循环来读取文本文件的每一行,用制表符分隔,并且”

如果文本文件已经预先验证或可靠忽略错误处理(例如,没有被单个选项卡均匀分隔)。

with open('dictionary.txt', 'r') as f:
    [line.strip().split("\t") 
              for line in f.read().split("\n") 
                                  if line.strip()]

将为您提供创建 Word 对象实例所需的(综合)列表,而无需使用 re

“然后尝试创建一个先前定义的对象的实例:Word。”

with open('dictionary.txt', 'r') as f:
    [Word(line.strip().split("\t"))
              for line in f.read().split("\n") 
                                  if line.strip()]

“我希望该对象的名称在列表中的第二项,以便于搜索,”

你能用一个例子重写这个吗?

但它不允许我这样做,

  line_list[1] = Word(line_list[0], line_list[1], line_list[2], line_list[3]) 

对不起,我在这里失去了你,为什么使用 line_list[1] 来引用新创建的 Word 实例,其中 line_list[1] 本身就是一个参数?

随着你的澄清,我会有类似这样的 重做代码:

from pprint import pprint

我对你的类定义的假设:

class Word():
    def __init__(self, **kwargs):
        self.set_attrs(**kwargs)

    def __call__(self):
        return self.get_attr("swedish_word")

    def set_attrs(self, **kwargs):
        for k, v in kwargs.iteritems():
            setattr(self, k, v)

    def get_attr(self, attr):
        return getattr(self, attr)

    def get_attrs(self):
        return ({attr.upper():getattr(self, attr) for attr in self.__dict__.keys()})

    def print_attrs(self):
        pprint(self.get_attrs())


if __name__ == '__main__':

# sample entries in dictionary.txt
#    swedish_word    english_word    article           word_type
#    hund            dog              ett                noun
#    katt            cat              ett                noun
#    sova            sleep            ett                verb

    with open('dictionary.txt', 'r') as f:
        header = f.readline().strip().split("\t")


        instances = [Word(**dict(zip(header, line.strip().split("\t"))))
                              for line in f.read().split("\n")
                                                  if line.strip()]

#        for line in f.read().split("\n"):
#             data = dict(zip(header, line.strip().split("\t")))
#             w = Word(**data)

您可以像这样获取给定 swedish_word 的实例属性

def print_swedish_word_properties(swedish_word):
    for instance in instances:
       if instance() == swedish_word:
           print "Properties for Swedish Word:", swedish_word
           instance.print_attrs()

print_swedish_word_properties("hund")

有这样的输出

Properties for Swedish Word: hund
{'ARTICLE': 'ett',
 'ENGLISH_WORD': 'dog',
 'SWEDISH_WORD': 'hund',
 'WORD_TYPE': 'noun'}

或者您可以使用任何其他类方法来搜索各种属性的实例

于 2013-11-11T23:17:57.913 回答
0

这是使用命名元组的更清洁的解决方案。你最终会得到一个名为“words”的字典,你可以用它来按名称查找每个单词。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pprint
from collections import namedtuple

Word = namedtuple('Word', ['name', 'french', 'gender', 'type_'])

words = {}
with open('dictionary.txt', 'rU') as fin:
    for word in (Word(*r.rstrip('\n').split('\t')) for r in fin):
        words[word.name] = word

pprint.pprint(words)
于 2013-11-11T20:49:39.340 回答
0

首先,最好使用 with 作为从文件获取输入的语句,因为关闭过程会自动处理。其次,要从文件中读取所有行,您必须使用 readlines() 而不是 readline()。尝试这样的事情:

with open('dictionary.txt','r') as file : 
    line_list = file.readlines() 
splitLineList = [] 
for lines in line_list : 
    splitLineList.append(re.split(r'\t',lines.strip('\n')) 
于 2013-11-11T20:54:44.060 回答