The None
output is because dict.update
returns None. It modifies the dictionary itself, but does not return anything. So you probably wanted self._dict.update({key:value})
. However, self._dict
doesn't exist at initialization. So it would make more sense to do self._dict = {key: value}
. If you're trying to modify the object's internal dictionary, then you should do self.__dict__.update({key:value})
. However, this is bad practice. A better idea would be to write setattr(self, key, value)
. The reason Example2 is working successfully is because if you try to do getattr(instance, thing)
(which is what instance.thing
does), and thing
is not in instance.__dict__
, then instance.__class__.__dict__
will be checked instead.
Python : Behavior of class and instance variables
-
24-06-2022 - |
Вопрос
I have following two code samples
Example 1:
class MyClass(object):
def __init__(self, key, value):
self._dict = self._dict.update({key:value})
m = MyClass('ten',10)
print m._dict
Output:
AttributeError: 'MyClass' object has no attribute '_dict'
Example2:
class MyClass(object):
_dict = {}
def __init__(self, key, value):
self._dict = self._dict.update({key:value})
m = MyClass('ten',10)
print m._dict
Output:
None
I am quite surprised with above behavior
Why the example2 compiled successfully by just addition of _dict = {}
line, and line present at class scope.
also why None
output?
I believed class scope variables has no relation with instance variable
(special with self
)
Any Explaination?
Решение 2
Другие советы
Your 'example 2' defines a single dictionary at the class level. All instances of the class will share that same dictionary, at least unless you reassign _dict on the instance.
See this question for a detailed explanation: Why do attribute references act like this with Python inheritance?
As for why you're getting None
- the update
method changes its dict in place, and returns None
.
Because the _dict
in Example 2 is a class variable so it's an attribute of MyClass
where as the _dict in Example 1 is an instance variable so it's a instance attribute.
Example 1: you are trying to update an object that is yet to be created. therefore error.
Example 2: When working in the inner scope of the function, if you modify the variable it makes changes to the previously defined _dict. But if you assign the value, it makes a new variable with the same name in the inner scope.
This will work.
class MyClass(object):
_dict = {}
def __init__(self, key, value):
self._dict.update({key:value})
This will not.
class MyClass(object):
_dict = {}
def __init__(self, key, value):
self._dict = self._dict.update({key:value})
because you are doing an assigning operation. It makes a new variable. So no changes are made to the _dict in the outer scope. Your _dict in the outer scope is still empty and returns None.
self._dict
does not yet exist, so the first version raises that exception. The second one actually falls through looking _dict
up on the instance and instead updates the class attribute, then assigns the class-level dictionary to the instance-scope _dict
attribute.