简体   繁体   中英

Python : Behavior of class and instance variables

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?

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 .

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.

因为示例2中的_dict是类变量,所以它是MyClass的属性,而示例1中的_dict是实例变量,因此它是实例属性。

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.

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