How to add attributes to a class in __init__() of the class with __dict__ in Python 3?

3227 views python
4

The following code works in Python 2.7 with _x.__dict__['c']=8

class _x:
    def __init__(self):
        self.a = 6
        self.b = 7
        _x.__dict__['c']=8
        print("good!")

y=_x()
print(y.__dict__)
print(_x.__dict__)

Output:

good!
{'a': 6, 'b': 7}
{'c': 8, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x00000000049227B8>}

The above code does not work in Python 3.6 with _x.__dict__['c']=8 and got errors:

TypeError                             Traceback (most recent call last)
<ipython-input-5-b4146e87f5a4> in <module>()
      6         print("good!")
      7 
----> 8 y=_x()
      9 print(y.__dict__)
     10 print(_x.__dict__)

<ipython-input-5-b4146e87f5a4> in __init__(self)
      3         self.a = 6
      4         self.b = 7
----> 5         _x.__dict__['c']=8
      6         print("good!")
      7 

TypeError: 'mappingproxy' object does not support item assignment

Any suggestions?

answered question

Why do you want to go through __dict__? Do you just not know about setattr?

Why are you doing this? It's usually a very bad idea for new construction to just set values on the class (the rare case where it makes sense is when you're numbering instances or the like, but in that case, the class variable should be defined with a base value at definition time). This smells like an XY problem.

2 Answers

7

Is there any reason you're trying to use non-public interface? If for some reason you want to set class attribute during instantiation, try

class A:
    def __init__(self):
        self.__class__.k = 1

If you want to set access dynamically, use setattr

Reasoning behind mutability changes described in this answer

posted this
12

You can set a class variable by specifying the class name before the variable name.

Change:

_x.__dict__['c']=8

to:

_x.c=8

posted this

Have an answer?

JD

Please login first before posting an answer.