简体   繁体   English

Python:类和实例变量的行为

[英]Python : Behavior of class and instance variables

I have following two code samples 我有以下两个代码示例

Example 1: 范例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: 例2:

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 输出: 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. 为什么仅通过添加_dict = {}行并在类作用域中显示行来成功编译example2。 also why None output? 还为什么None输出? I believed class scope variables has no relation with instance variable (special with self ) 我相信类范围变量与实例变量没有关系(特别是对self

Any Explaination? 有什么解释吗?

Your 'example 2' defines a single dictionary at the class level. 您的“示例2”在班级定义了一个字典。 All instances of the class will share that same dictionary, at least unless you reassign _dict on the instance. 该类的所有实例将共享同一词典,至少除非您在实例上重新分配_dict。

See this question for a detailed explanation: Why do attribute references act like this with Python inheritance? 有关详细说明,请参见此问题: 为什么属性引用在Python继承中表现得如此?

As for why you're getting None - the update method changes its dict in place, and returns None . 至于为什么会得到None ,则update方法将dict更改为原位,并返回None

The None output is because dict.update returns None. None输出是因为dict.update返回无。 It modifies the dictionary itself, but does not return anything. 它修改字典本身,但不返回任何内容。 So you probably wanted self._dict.update({key:value}) . 因此,您可能需要self._dict.update({key:value}) However, self._dict doesn't exist at initialization. 但是, self._dict在初始化时不存在。 So it would make more sense to do self._dict = {key: value} . 因此,做self._dict = {key: value}会更有意义。 If you're trying to modify the object's internal dictionary, then you should do self.__dict__.update({key:value}) . 如果您尝试修改对象的内部字典,则应执行self.__dict__.update({key:value}) However, this is bad practice. 但是,这是不好的做法。 A better idea would be to write setattr(self, key, value) . 一个更好的主意是编写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. Example2成功运行的原因是因为如果您尝试执行getattr(instance, thing) instance.__class__.__dict__ getattr(instance, thing)instance.thing所做的thing ),而thing不在instance.__dict__ ,则将改为检查instance.__class__.__dict__

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

Example 1: you are trying to update an object that is yet to be created. 示例1:您尝试更新一个尚未创建的对象。 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. 示例2:在函数的内部范围内工作时,如果修改变量,它将更改先前定义的_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. 因此,不会在外部范围内对_dict进行任何更改。 Your _dict in the outer scope is still empty and returns None. 您在外部范围中的_dict仍然为空,并返回None。

self._dict does not yet exist, so the first version raises that exception. self._dict还不存在,因此第一个版本会引发该异常。 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. 第二个实际上是通过在实例上查找_dict ,然后更新class属性,然后将类级字典分配给instance-scope _dict属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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