为什么Python似乎将实例变量视为对象之间共享?
今天,当我注意到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这样工作。谁能对此有所启发?
-
正如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中一样,它也包含在构造函数中。