为什么Python似乎将实例变量视为对象之间的共享?

lio*_*l b 6 python oop object

我今天正在编写一个简单的脚本,当时我注意到Python处理实例变量的方式有一个奇怪的怪癖.

假设我们有一个简单的对象:

class Spam(object):
    eggs = {}

    def __init__(self, bacon_type):
        self.eggs["bacon"] = bacon_type

    def __str__(self):
       return "My favorite type of bacon is " + self.eggs["bacon"]
Run Code Online (Sandbox Code Playgroud)

我们使用单独的参数创建此对象的两个实例:

spam1 = Spam("Canadian bacon")
spam2 = Spam("American bacon")

print spam1
print spam2
Run Code Online (Sandbox Code Playgroud)

结果令人费解:

My favorite type of bacon is American bacon
My favorite type of bacon is American bacon
Run Code Online (Sandbox Code Playgroud)

似乎所有不同的"垃圾邮件"实例之间共享"蛋"字典 - 无论是每次创建新实例还是覆盖它.这在日常生活中并不是真正的问题,因为我们可以通过在初始化函数中声明实例变量来解决它:

class Spam(object):

    def __init__(self, bacon_type):
        self.eggs = {}
        self.eggs["bacon"] = bacon_type

    def __str__(self):
        return "My favorite type of bacon is " + self.eggs["bacon"]

spam1 = Spam("Canadian bacon")
spam2 = Spam("American bacon")

print spam1
print spam2
Run Code Online (Sandbox Code Playgroud)

使用这种方式编写的代码,结果就是我们所期望的:

My favorite type of bacon is Canadian bacon
My favorite type of bacon is American bacon
Run Code Online (Sandbox Code Playgroud)

因此,虽然我并不担心这种行为,但我不明白为什么Python以这种方式工作.任何人都可以对此有所了解吗?

Dav*_*d Z 8

正如Ignacio发布的那样,在Python中分配给类范围的变量是类变量.基本上,在Python中,类只是语句下的class语句列表.一旦语句列表完成执行,Python就会挖掘在执行过程中创建的任何变量,并从中创建一个类.如果需要实例变量,实际上必须将其分配给实例.

另一方面:听起来你可能从Java(或类似Java)的角度来看这个问题.所以也许您知道因为Java要求显式声明变量,所以它需要在类范围内具有实例变量声明.

class Foo {
    String bar;
    public Foo() {
        this.bar = "xyz";
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,只有声明在类范围内.换句话说,为该变量分配的内存是类"模板"的一部分,但变量的实际不是.

Python不需要变量声明.所以在Python翻译中,你只需删除声明.

class Foo:
    # String bar;  <-- useless declaration is useless
    def __init__(self):
        self.bar = "xyz"
Run Code Online (Sandbox Code Playgroud)

内存将在需要时分配; 只有作业才被写出来.这就像构造函数一样,就像在Java中一样.


Ign*_*ams 6

那不是实例变量,而是一个类变量.通过实例访问它的事实是无关紧要的; 它仍然是同一个对象.

  • 它是类定义的一部分,即`Spam.eggs`.当绑定为`self`的属性时,它不是类的属性,而是实例的属性. (2认同)