0

I currently have a textfile with saved data just as:

surname1
name1
number1
address1
surname2
name2
number2
address2
...

I want to use this textfile to create instances in my class:

class Contact(object):

    def __init__(self, surname, name, number, address):
        self.surname = surname
        self.name = name
        self.number = number
        self.address = address

I need a function that can read from the textfile, use 4 rows as attributes for a new instance, append that instance to a list & then do it again for the next 4 rows and so on...how can this be done?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • This is rather broad, can you narrow down what exactly is giving you a problem? Is it reading data from a file? There are many ways to go about this, probably the best is to re-think your serialization and rather than use an improvised text-based serialization format, you could consider using one of the various existing solutions (JSON, YAML). Or maybe just using binary serialization, like `pickle`? – juanpa.arrivillaga Nov 28 '17 at 22:04
  • The problem is that i can't find a way to set the "nth" row as the first attribute, the "nth+1" row as the second attribute etc, for every new instance. for n=0,4,8... of course – Nicholas Thorne Nov 28 '17 at 22:09
  • Right, well, that essentially boils down to chunking an iterable by 4, which there are many such questions already. But why not go with a better serialization approach, one that doesn't require parsing the data like that? Like JSON, or `pickle`? – juanpa.arrivillaga Nov 28 '17 at 22:10
  • I am required to use a file with this seralization format, it's a school project. However, thank you, I will see if I manage to solve it by chunking an iterable by 4. – Nicholas Thorne Nov 28 '17 at 22:18
  • Well, if you are curious, you should check out [this answer](https://stackoverflow.com/a/8290490/5014455) to a question regarding exactly that. The writer of the answer is a core-developer on CPython, so probably good to see what they would say about it. – juanpa.arrivillaga Nov 28 '17 at 22:21

2 Answers2

1

You can use more-itertools' sliced() method to slice an iterable into equal chunks:

import more_itertools

contacts = []

class Contact:

    def __init__(self, surname, name, number, addr):
        self.surname = surname
        self.name = name
        self.number = number
        self.addr = addr

with open('file.txt', 'r') as f:
    content = f.read().split('\n')
    for x in more_itertools.sliced(content, 4):
        c = Contact(*x)
        contacts.append(c)
adder
  • 3,512
  • 1
  • 16
  • 28
  • Not the greatest approach in my opinion. Seems like any advantage to using an iterative tool gets effectively canceled-out by first reading the entire file into memory...so why even bother...especially since doing so is going to require downloading and installing a third-party module first (assuming you haven't done this already for some other reason). – martineau Nov 28 '17 at 23:27
  • [more_itertools.chunked()](https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.chunked) will do the same thing without reading everything into memory. `sliced()` is only for things that natively support slicing. – bbayles Dec 01 '17 at 00:07
0

Essentially each line of the input file represents the value of an attribute. You can mirror that in your code by reading the lines in groups and then pass those onto the Contact class constructor.

Here's what I mean:

class Contact:
    fields = 'surname', 'name', 'number', 'address'

    def __init__(self, surname, name, number, address):
        self.surname = surname
        self.name = name
        self.number = number
        self.address = address

    def __repr__(self):
        return '{}({})'.format(self.__class__.__name__,
                               ', '.join(getattr(self, field)
                                            for field in self.fields))

filename = 'class_data.txt'
contacts = []
with open(filename) as file:
    try:
        while True:
            fields = [next(file).strip() for _ in range(len(Contact.fields))]  # Read group.
            contacts.append(Contact(*fields))
    except StopIteration:  # end-of-file
        pass

from pprint import pprint
pprint(contacts)

Output:

[Contact(surname1, name1, number1, address1),
 Contact(surname2, name2, number2, address2),
 Contact(surname3, name3, number3, address3)]
martineau
  • 119,623
  • 25
  • 170
  • 301