Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store file data as class objects? [closed]

Imagine we have a class:

class Car:
    def __init__(self, model, name, price):
        self.model = model
        self.name = name
        self.price = price

And a .txt file:

201    BMW              1.2
202    Mercedes Benz    1.6

Is it possible to store '201' and '202' in model, 'BMW' and 'Mercedes Benz' in name, 1.2 and 1.6 in price without doing it manually...

    car1 = Car('201', 'BMW', 1.2)
    car2 = Car('202', 'Mercedes Benz', 1.6)

... as such, but rather by directly reading and storing data as class object?

I have tried parsing the data from file as such:

    cars = []
    file = open('store-data.txt')
    content = file.readlines()
    for x in range(len(content)):
        new_car = Car()
        cars.append(new_car)

    for car in cars:
        print(car)

But get the following error:

TypeError: __init__() missing 3 required positional arguments: 'model', 'name', and 'price'.
like image 539
Lauss Avatar asked Dec 31 '25 08:12

Lauss


1 Answers

The problem with your code is explained in the very same error message: TypeError: init() missing 3 required positional arguments: 'model', 'name', and 'price'.

While you're trying to create your car without any value: new_car = Car(). The step you're missing is parsing the contents of each line in the file. In order to do that, you must partition the line by the space (the only delimiter in the sample you provided): line.split() will do what you need, and you will have three elements in the returned list: the model, the name of the maker, and the price. The next step is to convert the price to float (the other data seems to be text).

A call to strip() will also remove all possible prefix and postfix spaces.

parts = line.strip().split()
car = Car(part[0], part[1], float(part[2]))

The final code, following your own question:

    cars = []
    file = open('store-data.txt')
    content = file.readlines()
    for x in range(len(content)):
        parts = content[x].strip().split()
        new_car = Car(parts[0], parts[1], float(parts[2]))
        cars.append(new_car)

One important problem is that we are not closing the file, just opening it. The structure with will allow Python to close the file once the work on it is finished (when the with block is over).

Also you don't need to iterate over the number of lines in the file, you can run over them directly. This happens because for iterates over a list, and actually range() returns a list (of integers).

    cars = []
    with open('store-data.txt') as file:
        for x in file.readlines():
            parts = x.strip().split()
            new_car = Car(parts[0], parts[1], float(parts[2]))
            cars.append(new_car)

Now, there are a few issues suitable for polishing: converting a string to floating number (float()), can throw a ValueError exception. Also, we are counting that all lines will have the expected format.

    cars = []
    with open('store-data.txt') as file:
        for x in file.readlines():
            parts = x.strip().split()

            if len(parts) == 3:
                try:
                    new_car = Car(parts[0], parts[1], float(parts[2]))
                    cars.append(new_car)
                except ValueError:
                    print("Missing price in line: " + x)
            else:
                print("Formatting error in line: " + x)

Finally, since we have a maker "Mercedes Benz" which includes the delimiter inside its name, we have to take into account that maybe there is not going to be direct correspondence between the parts of the string and values for the car. We are sure that the first value is the model (#0, parts[0]), and the final one (#-1, parts[-1], this is something special for Python) is the price. The values in-between are the different parts of the name of the maker.

Fortunately in Python we can extract a sublist from a bigger list (this is called slicing). Just enumerate the first position and the last one, and separate them with a colon. Remember that the final position is never included. So, the maker name will be included in the parts[1:-1]. We can also use the method join(ch, l) from str, which makes a new string using the members of the list l, separating them by the character ch. This will work even in the case when the maker name extends only for one part.

if len(parts) >= 3:
        model = parts[0]
        str_price = parts[-1]
        name = str.join(' ', parts[1:-1])
        
        try:
            new_car = Car(model, name, float(str_price))

So, finally:

    cars = []
    with open('store-data.txt') as file:
        for x in file.readlines():
            parts = x.strip().split()

            if len(parts) >= 3:
                model = parts[0]
                str_price = parts[-1]
                name = str.join(' ', parts[1:-1])
        
                try:
                    new_car = Car(model, name, float(str_price))
                    cars.append(new_car)
                except ValueError:
                    print("Missing price in line: " + x)
            else:
                print("Formatting error in line: " + x)

like image 152
Baltasarq Avatar answered Jan 02 '26 21:01

Baltasarq



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!