【问题标题】:Python: Read line from file, split it and change objectPython:从文件中读取行,将其拆分并更改对象
【发布时间】:2015-10-01 18:12:48
【问题描述】:

假设我有一个包含 1000 行的文本文件。它们看起来都是这样的:

FirstName:SecondName:1:2:3:4

":" 可以替换为任何其他符号,并且我有 1000 个对象的列表:

class RECORD:
    FNAME = "default"
    SNAME = "default"
    M1 = 0;
    M2 = 0;
    M3 = 0;
    M4 = 0;

    def outname(self):
        print (self.FNAME + self.SNAME)

LIST = []
for i in range(1000):
    LIST.append(RECORD(i))

所以,我想读取这个文件,并用第一行中的字符串和整数填充第一个对象,用第二行等填充第二个对象。 我怎样才能做到这一点?

【问题讨论】:

  • 如果: 被替换为/,你的程序怎么知道?每行的符号可以改变吗?在每一行内?
  • 顺便说一句:这里不需要分号。

标签: python object text-files


【解决方案1】:

对于简单的类(比如你的),collections.namedtuple 通常很有用:

from collections import namedtuple

Record = namedtuple("Record", "FNAME SNAME M1 M2 M3 M4")
with open("records.txt") as record_file:
    records = [Record(*line.split(':')) for line in record_file]

print records[3].FNAME  # For example

此外,您可能希望将相似的项目存储为序列,因此每条记录都是名称列表和整数列表。这是一个可以做到这一点的版本。

from collections import namedtuple
from pprint import pprint

Record = namedtuple("Record", "names m")
records = []
with open("records.txt") as record_file:
    for line in record_file:
        line = line.split(':')
        line = line[0:2] , [int(i) for i in line[2:]]
        line = Record(*line)
        records.append(line)

print records[3].names[0] # Same as first example
pprint (records)          # pretty-print entire list

【讨论】:

    【解决方案2】:

    我认为您正在寻找这样的东西:

    class Record(object):
        """docstring for Record"""
        def __init__(self, FNAME, SNAME, M1, M2, M3, M4):
            super(Record, self).__init__()
            self.FNAME = FNAME
            self.SNAME = SNAME
            self.M1 = M1
            self.M2 = M2
            self.M3 = M3
            self.M4 = M4
    
    with open('your_file_name') as f:
        LIST = [Record(*(line.split(':'))) for line in f]
    

    所有的工作都发生在最后一行。文件上的列表理解为您提供行列表。每一行都在: 上拆分,并通过解包传递给 Record 构造函数。

    【讨论】:

    • 谢谢,但是对象列表呢?我有一个 1000 行和 1000 个对象的文件。我应该把它放到循环中吗?我最近可以调用任何列表对象,比如在 c++ 中吗?我的意思是,我可以打电话给 LIST[1].FNAME 或类似的东西吗?
    • 在这种情况下,LIST 将包含 1000 个 Record 类的对象。 LIST[1] 是对应于文件中第二行的对象。所以 LIST[1].FNAME 确实会返回与该对象对应的名字。
    • 那么,这是否意味着我需要以某种方式将 'for i in range(1000):' 和 'with open('marks.csv') as f:' 放在一个循环中?或者它会自动创建对象直到文件结束?很抱歉再次提出蹩脚的问题。
    • 不需要循环。 [line for line in f] 将返回一个行列表,如 'FirstName:SecondName:1:2:3:4'; [line.split(':') for line in f] 将返回一个列表列表,其中包含 ['FirstName', 'SecondName', '1', '2', '3', '4\n'] 等元素。最后,我们做[Record(*(line.split(':'))) for line in f]。每行中的单词列表被传递给构造函数。需要星号,因为构造函数需要多个参数而不是单个列表参数。
    • 谢谢,但我认为构造函数有问题:当我启动程序时,python 说'NameError:名称'SNAME'未定义'。我试图将它与 M1 分配交换,但它仍然对 SNAME 感到愤怒。当我将 SNAME 重命名为 SNAAME(在括号中和“=”之后)时,它会显示“NameError:名称 'SNAAME' 未定义”。你能帮帮我吗?
    【解决方案3】:

    试试这个代码。我试图让它与你从 C++ 中所知道的非常接近。但是请尝试让自己更多地沉浸在 Python 中...

    class Person:
        def __init__(self,
                     first_name='default',
                     second_name='default',
                     m1=0, m2=0, m3=0, m4=0):
    
            self._first_name = first_name
            self._second_name = second_name
            self._m1 = m1
            self._m2 = m2
            self._m3 = m3
            self._m4 = m4
    
        def full_name(self):
            return self._first_name + ' ' + self._second_name
    
    if __name__ == '__main__':
        INPUTFILE = 'persons.txt'
        persons = list()
        for line in open(INPUTFILE):
            first_name, second_name, m1, m2, m3, m4 = line.strip().split(':')
            persons.append(Person(first_name, second_name, m1, m2, m3, m4))
        for person in persons:
            print(person.full_name())
    

    【讨论】:

      【解决方案4】:
      import csv
      
      class Record(object):
      
          def __init__(self, fname = 'default', sname = 'default', m1 = 0, m2 = 0, m3 = 0, m4 = 0):
      
              self.fname = fname
              self.sname = sname
              self.m1 = int(m1)
              self.m2 = int(m2)
              self.m3 = int(m3)
              self.m4 = int(m4)
      
          def get_name(self):
              return '{0} {1}'.format(self.fname, self.sname)
      
      records = []
      reader = csv.reader(open('file.txt', 'rb'), delimiter = ':')
      for row in reader:
          records.append(Record(*row))
      
      for record in records:
          print(record.get_name())
          #FirstName SecondName
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-19
        • 1970-01-01
        • 2016-04-11
        • 2013-05-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多