为什么我不能在Python中更改类的属性

pyt*_*hon 4 python class object mutable immutability

我们说classes在Python中是可变的,这意味着你可以使用引用我们可以改变将反映在对象中的值.例如,

>>> A = [1, 2, 3]
>>> B = A
>>> B[2] = 5
>>> A
[1, 2, 5]
Run Code Online (Sandbox Code Playgroud)

在这里,我可以更改A对象的值,B因为它list是一个可变类型.我的问题是为什么我不能使用相同的概念更改下面的类的属性:

class C:

    apple = 2

    def __init__(self):
        self.dangerous = 2

D = C # D is pointing to same class C

D().dangerous = 5 # changing the value of class attribute D

D().apple = 3 # changing the value of apple here

print D().apple

print D().dangerous

OUTPUT:
2
2
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释为什么输出22,但不35,因为我们说这个类是一个mutable类型.

更新:参考@ zxq9的答案,如果您在do时看到下图D=C,D实际上是指向同一个类而不是您所描述的新对象.你能解释一下吗:

在此输入图像描述

zxq*_*xq9 10

每次在类之后放置parens时,您都在构造类的新实例对象.因此,您打印的内容是新品牌,并没有反映您之前制作的短期作品.

这是一个示例(扩展为涵盖对C类的基础引用):

>>> class C:
...   red = 2
...   def __init__(self):
...     self.blue = 2
... 
>>> C.red
2
>>> C.blue
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'C' has no attribute 'blue'
>>> C().red
2
>>> C().blue
2
>>> #OOOOH!
... 
>>> z = C()
>>> z.red
2
>>> z.blue
2
>>> D = C
>>> D.red
2
>>> D().red
2
>>> D().red = "over 9000!"
>>> D.red
2
>>> D.red = "No, really over 9000!"
>>> D.red
'No, really over 9000!'
>>> C.red
'No, really over 9000!'
>>> #OOOOOOHHHH!
...
Run Code Online (Sandbox Code Playgroud)

需要注意的是,我们没有直接改变I类分配的时候D.red = "No, really over 9000!"-因为被引用的类定义本身,而不是从它创建一个实例化对象.

仔细阅读示例代码,注意引用 ClassName调用 之间的区别ClassName().第一个是通过变量名引用类定义 - 用于生成带有构造函数的实例对象的蓝图__init__().第二个是invokation,__init__()其返回值是定义它的类的实例对象.

这也是你可以做这样的事情的原因:

def some_fun(another_fun, value):
    another_fun(value)

def foo(v):
    return v + v

def bar(v):
    return v * v

some_fun(foo, 5)
some_fun(bar, 5)
Run Code Online (Sandbox Code Playgroud)

此功能为Python在构建功能抽象方面提供了高度的灵活性.(现在,如果它只有尾声消除......)