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

发布于 2021-01-29 16:57:57

今天,当我注意到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"]

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

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

print spam1
print spam2

结果令人费解:

My favorite type of bacon is American bacon
My favorite type of bacon is American bacon

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

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

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

My favorite type of bacon is Canadian bacon
My favorite type of bacon is American bacon

因此,尽管我不受这种行为的束缚,但我不明白为什么Python这样工作。谁能对此有所启发?

关注者
0
被浏览
44
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    正如Ignacio所说,在Python中的类作用域分配的变量是类变量。基本上,在Python中,类只是语句下的class语句列表。一旦该语句列表执行完毕,Python就会搜集在执行过程中创建的所有变量,并从中创建一个类。如果需要实例变量,则实际上必须将其分配给实例。

    另一个注意事项:听起来您可能是从Java(或类似Java)的角度来进行此操作的。因此,也许您知道,因为Java要求显式声明变量,所以它需要在类范围内具有实例变量声明。

    class Foo {
        String bar;
        public Foo() {
            this.bar = "xyz";
        }
    }
    

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

    Python不需要变量声明。因此,在Python翻译中,您只需删除声明。

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

    内存将在需要时分配;实际上只写出作业。就像在Java中一样,它也包含在构造函数中。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看