Python类变量是静态的吗? [英] Is Python class variable static?

查看:52
本文介绍了Python类变量是静态的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看到以下代码:

class Super:
    powers = 'no power'
    def __init__(self, name):
        self.name = name

    def add_power(self, power):
        self.powers = power

dog = Super('dog')
cat = Super('cat')

dog.add_power("bark")
print (dog.powers) # print bark
print (cat.powers) # print no power

看起来python的class变量独立于每个实例,因为将狗实例的 powers 变量从无权限更改为树皮不会影响cat实例的 powers 变量

it looks like python's class variable is independent to each instance because change dog instance's powers variable from no power to bark does not affect the cat instance's powers variable

但是,通过执行以下操作:

However, by doing this:

class Super:
    powers = ["no power"]
    def __init__(self, name):
        self.name = name

    def add_power(self, power):
        self.powers.append(power) 

dog = Super('dog')
cat = Super('cat')

dog.add_power("bark")
print (dog.powers) # print ['no power', 'bark']
print (cat.powers) # print ['no power', 'bark']  # why cat.powers is also affected???

该示例显示powers变量(这次是列表)是静态的,因为将元素添加到狗实例的 powers 也会影响cat实例的 powers .

The example shows powers variable (it is a list this time) is static since append an element to dog instance's powers also affects cat instance's powers.

我还尝试了通过调用add_power将幂更改为int并将幂增加1的方式,它们彼此之间不会相互影响.因此,我很困惑为什么将元素添加到作为类变量的列表中会影响其他实例.

I also experimented with changing the powers to an int and increment powers by 1 by calling add_power, and they don't affect each other. So I am really confused why appending an element to a list which is a class variable affects other instances.

推荐答案

实例变量名称可以 shadow 相同名称的类变量.

An instance variable name can shadow a class variable of the same name.

>>> class A:
...     var = 'class var'
...     
>>> a = A()
>>> vars(a)  # no instance variables
{}
>>> a.var  # attribute lookup resolved at the class level
'class var'
>>> a.var = 'instance var'  # create an instance variable
>>> vars(a)  # the name `var` now exists in the instance dict
{'var': 'instance var'}
>>> a.var  # attribute lookup resolved at the instance level
'instance var'
>>> type(a).var  # note: the class variable still exists!
'class var'
>>> del a.var  # deletes from the instance dict
>>> a.var  # ..but the name `var` remains available at the class level
'class var'
>>> vars(a)  # instance dict is again empty
{}

并非是class变量是静态的"( A.var 可以通过常规属性访问来修改或删除).相反,发生的是:访问 a.var 首先在实例的名称空间( a .__ dict __ )中尝试名称 var ,如果失败,则查找返回到检入类的名称空间( A .__ dict __ ).

It's not the case that the class variable is "static" (A.var can be modified or deleted via normal attribute access). What's happening instead is: accessing a.var first tries the name var in the instance's namespace (a.__dict__), and if that fails then the lookup falls back to checking in the class's namespace (A.__dict__).

在类对象上使用列表时看不到相同行为的原因是该行不是

The reason you don't see the same behaviour when using a list on the class object is that this line is not an assignment statement:

self.powers.append(power)

使用赋值语句的看似等效的版本会重新创建与您观察到的名称相同的阴影:

A seemingly equivalent version which is using an assignment statement would recreate the same name shadowing that you observed:

self.powers = self.powers + [power]  # not actually equivalent!

总结:对于类属性使用整数或字符串时,您是在实例名称空间中创建一个条目(由于赋值语句),但是当使用列表时,您直接对类变量进行操作,这确实是在所有实例之间共享.

In summary: when using an integer or a string for the class attribute you were creating an entry in the instance namespace (because of the assignment statement), but when using a list you act directly on the class variable, which is indeed shared between all instances.

这篇关于Python类变量是静态的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆