The class doesn't take values as numbers when creating an object of a class, but takes them as default values

Viewed 28

The task is to write a class decorator, which reads a JSON file and makes its key/values to become properties of the class.

But one of conditions is that there has to be the ability to pass values manually (by creating a class object) as well.

I almost did it. There's just a tiny problem. The program reads data from JSON file and passes them successfully to the class. But when passing values manually during creation of an object of the class, values don't change and they are still being taken from JSON.

The problem only disappears when passing values as default values.

room = Room(1, 1) # Doesn't work
room = Room(tables=1, chairs=1) # Does work

Since arguments have to be passed only as numbers in tests, I have to manage it to work with just numbers, not default values.

Here's the code.

from json import load

def json_read_data(file):
    def decorate(cls):
        def decorated(*args, **kwargs):
            if kwargs == {}:
                with open(file) as f:
                    params = {}
                    for key, value in load(f).items():
                        params[key] = value
                return cls(**params)
            else:
                return cls(*args, **kwargs)
        return decorated
    return decorate


@json_read_data('furniture.json')
class Room:
    def __init__(self, tables=None, chairs=None):
        self.tables = tables
        self.chairs = chairs

    def is_it_enough(self):
        return self.chairs * 0.5 - self.tables > 0.4
       

kitchen = Room() # This is passing values from JSON file
print(kitchen.__dict__) # Prints {'tables': 2, 'chairs': 5}
room = Room(tables=1, chairs=1) # This is passing values manually
print(room.__dict__) # Prints {'tables': 1, 'chairs': 1}

'''
JSON file:
{
  "tables": 2, 
  "chairs": 5
}
'''

But if we change to room = Room(1, 1), print(room.dict) prints {'tables': 2, 'chairs': 5} again. Please help me solve this problem!

2 Answers

You need to add your arguments to the decorator. Remember that your decorator is called first and then it calls the decorated function.

You could declare your decorator as: def json_read_data(file, *args): then the subsequent calls to cls() would have to be adapted to accept them. The second one already does, the first one needs modification.

It seems, this edit really worked:

def decorated(*args, **kwargs):
    if not args and not kwargs:
Related