简体   繁体   中英

Python creating class instances from dictionary

I have class with a lot of fields that can be changed while my program is running, but when I create new object in my init I only can change some of them, I want to save those changes to JSON file and later be able to create new object with those variables. Is there any other way to do it other than making my init taking like 100 arguments?

In other words I would love it to be sth like that:

class MyClass:
    def __init__(self, q, w):
        self.q = q
        self.w = w
        self.e = 30
        self.r = 40
        
a = MyClass(10,20)
dct = {'q': 100, 'w': 200, 'e': 300, 'r': 400}
print('before:', tmp.q, tmp.w, tmp.e, tmp.r)
for i in dct:
    #do sth here
print('after:', tmp.q, tmp.w, tmp.e, tmp.r)
before: 10 20 30 40
after: 100 200 300 400

Here is how you can do that with keyword arguments:

class MyClass:
    def __init__(self, **q):
        self.__dict__.update(q)

a = MyClass(a=10, b=20, c=50, d=69)

print(a.a)
print(a.b)
print(a.c)
print(a.d)

Output:

10
20
50
69


With the dictionary:

class MyClass:
    def __init__(self, **q):
        self.__dict__.update(q)
        
dct = {'q': 100, 'w': 200, 'e': 300, 'r': 400}

a = MyClass(**dct)

print(a.q, a.w, a.e, a.r)

Output:

100 200 300 400

Instead of manipulating the class instances __dict__ , I'd recommend using the setattr method.

class MyClass:
    def __init__(self, new_vals):
        for k, v in new_vals.items():
            setattr(self, k, v)

dct = {'q': 100, 'w': 200, 'e': 300, 'r': 400}

a = MyClass(dct)

print(a.q, a.w, a.e, a.r)

Imho there is a reason why internals such as __dict__ have two leading underscores. My general recommendation would be to avoid accessing any attributes/mehods with two leading underscores as long as possible. Also see below for a reference to the Python documentation considering this topic.

And if you want to reduce it to a one-liner, you could also use a "dummy" list comprehension. The underscore catches the None return, but it is not necessarily required.

class MyClass:
    def __init__(self, new_vals):
        _ = [setattr(self, k, v) for k, v in new_vals.items()]

A short reference to the Python documentation on manipulating the built in __dict__ attribute:

A special attribute of every module is __dict__ . This is the dictionary containing the module's symbol table. Modifying this dictionary will actually change the module's symbol table, but direct assignment to the __dict__ attribute is not possible (you can write m.__dict__['a'] = 1 , which defines ma to be 1 , but you can't write m.__dict__ = {} ). Modifying __dict__ directly is not recommended.

see Python documentation on built in types

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM