【问题标题】:Python - creating multiple objects for a classPython - 为一个类创建多个对象
【发布时间】:2016-10-18 16:57:00
【问题描述】:

在 python 中,我需要通过读取文件 (Students.txt) 并对其进行解析来创建包含变量 first_name、middle_name、last_name、student_id 的类“Student”的 43 个实例。文本文件如下所示:

Last Name  Midle Name  First Name   Student ID  
----------------------------------------------
Howard                  Moe         howar1m     
Howard                  Curly       howar1c     
Fine                    Lary        fine1l      
Howard                  Shemp       howar1s     
Besser                  Joe         besse1j     
DeRita      Joe         Curly       derit1cj    
Tiure       Desilijic   Jaba        tiure1jd    
Tharen                  Bria        thare1b     
Tai         Besadii     Durga       tai1db      
Hego                    Damask      hego1d      
Lannister               Tyrion      lanni1t     
Stark                   Arya        stark1a     
Clegane                 Sandor      clega1s     
Targaryen               Daenerys    targa1d     
Bombadil                Tom         bomba1t     
Brandybuck              Meriadoc    brand1m     
Took                    Pregrin     took1p      
McCoy                   Leonard     mccoy1l     
Scott                   Montgomery  scott1m     
Crusher                 Wesley      crush1w     
Montoya                 Inigo       monto1i     
Rugen                   Tyrone      rugen1t     
Solo                    Han         solo1h      
Corey                   Carl        corey1c     
Flaumel                 Evelyn      flaum1e     
Taltos                  Vlad        talto1v     
e'Drien                 Morrolan    edrie1m     
Watson                  John        watso1j     
McCoy                   Ebenezar    mccoy1e     
Carpenter               Molly       carpe1m     
Graystone               Zoe         grays1z
Adama                   William     adama1w
Adama       Joseph      Leland      adama1l
Roslin                  Laura       rosli1l
Baltar                  Gaius       balta1g
Tigh                    Ellen       tigh1e
Tigh                    Saul        tigh1s
Cottle                  Sherman     cottl1s
Zarek                   Thomas      zarek1t
Murphy      James       Alexander   murph1a
Sobchak                 Walter      sobch1w
Dane                    Alexander   dane1a
Gruber                  Hans        grube1h
Biggs       John        Gil         biggs1gj

班级学生是:

class Student (object):
    def __init__(self, first_name, middle_name, last_name, student_id):
        self.__first_name = first_name
        self.__middle_name = middle_name
        self.__last_name = last_name
        self.__student_id = student_id

读入“Students.txt”并创建每个学生实例的最简单方法是什么?

【问题讨论】:

  • 1.逐行读取 2. 将行拆分为 firstname、middlename、lastname、id 3. 创建实例
  • 使用私有属性不是很有用...
  • 数据如何分隔?也可以有多个名字,例如约翰保罗?

标签: python class object object-oriented-analysis


【解决方案1】:

分步教程

要读取文件内容,请使用io.open。如果任何名称包含重音字符,请不要忘记指定文件编码。

with io.open('students.txt', mode="r", encoding="utf8") as fd:
    content = fd.read()

在这里,您读取整个内容并将其存储在内存中(数据量很小)。您也可以使用迭代器。

然后,你可以用str.splitlines()逐行拆分内容:

lines = content.splitlines()
# print(lines)

你会得到类似的东西:

['Last Name  Midle Name  First Name   Student ID  ',
 '----------------------------------------------',
 'Howard                  Moe         howar1m     ',
 'Howard                  Curly       howar1c     ',
 'Fine                    Lary        fine1l      ',
 'Howard                  Shemp       howar1s     ',
 'Besser                  Joe         besse1j     ',
 'DeRita      Joe         Curly       derit1cj    ',
 'Tiure       Desilijic   Jaba        tiure1jd    ',
 'Tharen                  Bria        thare1b     ']

您有(几乎)固定长度的行,因此您可以使用切片来提取字段。

以下是您可以对标题执行的操作:

header = lines.pop(0)
fields = header[0:8], header[11:21], header[23:33], header[36:46]
# print(fields)

你得到:

('Last Nam', 'Midle Name', 'First Name', 'Student ID')

你可以去掉连字符:

lines.pop(0)

对于每一行,您也可以使用切片提取值。注意:切片索引略有不同:

for line in lines:
    record = line[0:8], line[12:21], line[23:34], line[36:46]
    # print(record)

您将获得带有尾随空格的值:

('Howard  ', '         ', ' Moe       ', 'howar1m   ')
('Howard  ', '         ', ' Curly     ', 'howar1c   ')
('Fine    ', '         ', ' Lary      ', 'fine1l    ')
('Howard  ', '         ', ' Shemp     ', 'howar1s   ')
('Besser  ', '         ', ' Joe       ', 'besse1j   ')
('DeRita  ', 'Joe      ', ' Curly     ', 'derit1cj  ')
('Tiure   ', 'Desilijic', ' Jaba      ', 'tiure1jd  ')
('Tharen  ', '         ', ' Bria      ', 'thare1b   ')

为避免尾随空格,请使用str.strip() 函数:

for line in lines:
    record = line[0:8], line[12:21], line[23:34], line[36:46]
    record = [v.strip() for v in record]
    # print(record)

你得到:

['Howard', '', 'Moe', 'howar1m']
['Howard', '', 'Curly', 'howar1c']
['Fine', '', 'Lary', 'fine1l']
['Howard', '', 'Shemp', 'howar1s']
['Besser', '', 'Joe', 'besse1j']
['DeRita', 'Joe', 'Curly', 'derit1cj']
['Tiure', 'Desilijic', 'Jaba', 'tiure1jd']
['Tharen', '', 'Bria', 'thare1b']

此时,我建议您将记录作为dict 存储在列表中:

records = []
for line in lines:
    record = line[0:8], line[12:21], line[23:34], line[36:46]
    record = [v.strip() for v in record]
    records.append(dict(zip(header, record)))

你得到:

[{'First Name': 'Moe', 'Last Nam': 'Howard', 'Midle Name': '', 'Student ID': 'howar1m'},
 {'First Name': 'Curly', 'Last Nam': 'Howard', 'Midle Name': '', 'Student ID': 'howar1c'},
 {'First Name': 'Lary', 'Last Nam': 'Fine', 'Midle Name': '', 'Student ID': 'fine1l'},
 {'First Name': 'Shemp', 'Last Nam': 'Howard', 'Midle Name': '', 'Student ID': 'howar1s'},
 {'First Name': 'Joe', 'Last Nam': 'Besser', 'Midle Name': '', 'Student ID': 'besse1j'},
 {'First Name': 'Curly', 'Last Nam': 'DeRita', 'Midle Name': 'Joe', 'Student ID': 'derit1cj'},
 {'First Name': 'Jaba', 'Last Nam': 'Tiure', 'Midle Name': 'Desilijic', 'Student ID': 'tiure1jd'},
 {'First Name': 'Bria', 'Last Nam': 'Tharen', 'Midle Name': '', 'Student ID': 'thare1b'}]

但你也可以使用类:

class Student(object):
    def __init__(self, first_name, middle_name, last_name, student_id):
        self.first_name = first_name
        self.middle_name = middle_name
        self.last_name = last_name
        self.student_id = student_id
    
    def __repr__(self):
        fmt = "<Student('{first_name}', '{middle_name}', '{last_name}', '{student_id}')>"
        return fmt.format(first_name=self.first_name, middle_name=self.middle_name, last_name=self.last_name, student_id=self.student_id)
        

并构造一个学生列表:

students = []
for line in lines:
    record = line[0:8], line[12:21], line[23:34], line[36:46]
    record = [v.strip() for v in record]
    students.append(Student(*record))

你得到:

[<Student('Howard', '', 'Moe', 'howar1m')>,
 <Student('Howard', '', 'Curly', 'howar1c')>,
 <Student('Fine', '', 'Lary', 'fine1l')>,
 <Student('Howard', '', 'Shemp', 'howar1s')>,
 <Student('Besser', '', 'Joe', 'besse1j')>,
 <Student('DeRita', 'Joe', 'Curly', 'derit1cj')>,
 <Student('Tiure', 'Desilijic', 'Jaba', 'tiure1jd')>,
 <Student('Tharen', '', 'Bria', 'thare1b')>]

【讨论】:

  • 您需要更多解释吗?我建议你投票并accept我的回答。
【解决方案2】:
list_of_students = []
with open('students.txt') as f:
    for line in f:
        data = line.split()
        if len(data) == 3:
            firstname, lastname, id = data
            list_of_students.append(Student(firstname, '', lastname, id))
        elif len(data) == 4:
            list_of_students.append(Student(*data))
        else:
            raise ValueError

我不知道你的输入文件是如何布局的,所以这里有一些处理来处理没有中间名的情况。

【讨论】:

  • 我正在使用你的 sn-p 但我得到的只是 ValueError @PatrickHaugh
  • 如果您将print(data) 放在data = line.split() 正下方,它会打印什么?
  • @BenjaminDareEdwards,你肯定是从标题中得到的,拆分后有超过 4 个元素。此外,如果您有空行或带有空格的名称,那么也会导致错误。
  • @BenjaminDareEdwards 您可以将raise ValueError 替换为continue。这只会跳过它不喜欢的行
猜你喜欢
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
  • 2016-10-14
  • 1970-01-01
相关资源
最近更新 更多