Python实例的成员变量像成员变量一样工作,有些像静态变量。

11

我是 Python 的新手,我的 Python 代码中类的成员变量表现得很奇怪。有些像普通变量,但有些像静态变量!

class Chaos:
    list_value = []
    value = "default"

    def set_value(self, word):
        self.list_value.append(word)
        self.value = word 

    def show(self, num):
        print(str(num) + "====")
        print("value : " + self.value)
        for st in self.list_value:
            sys.stdout.write(st)
        print("\n=====\n")

a = Chaos()
a.show(0)
a.set_value("A")
a.show(1)
b = Chaos()
a.show(2)
b.show(3)

结果

0====
value : default

=====

1====
value : A
A
=====

2====
value : A
A
=====

3====
value : default
A
=====
但是最后一次测试的结果与我在上次测试中期望的不同。 'b'实例的'list_value'中不应该有"A"。它刚被创建,并且以前从未添加过"A"。 我将"A"添加到'a'的实例中,而不是'b'的实例。 但是结果显示'b'中也有'A'。 此外,类中的'list_value'和'value'的工作方式不同。 它们看起来具有相同的语法,为什么它们的工作方式不同呢?

4
可能是为什么类属性被记住了?的重复问题。 - Ignacio Vazquez-Abrams
2个回答

23

实际上,那些是类变量。要创建实例变量,请在__init__函数中初始化它们:

class Chaos:
    def __init__(self):
        self.list_value = []
        self.value = "default"

value 的行为像实例变量是因为你使用了 self.value 进行设置。当 Python 看到 self.X 时,它会查找对象中是否有属性 X,如果没有,则查找其类。由于您从未设置过 self.list_value,它正在访问类变量,这些变量在所有实例之间共享,因此任何修改都会反映在其他所有对象中。


list_value 在所有实例中都是相同的,因为 "list" 是可变数据类型,而不是类变量。如果通过实例访问类变量,它们将像实例变量一样行为。 - aaronn
@aaronn 这是一个与问题不同的问题。可变对象在通过任何方式共享时都可能会引起问题。但在这种情况下,没有共享任何东西,它仍然是相同的类变量。OP的疑问源于Python允许您即时创建新变量。这给人留下了value类变量的行为像实例变量的印象,而实际上并非如此。如果类有__slots__,则差异将消失,两个变量都不允许通过实例更改(只能更改指向的可变对象)。 - mgibsonbr

3
关键区别在于您正在附加到list_value,并且正在分配给value。它们被称为“类变量”。每个实例都有对类变量的自己的引用,这就是为什么列表是共享的原因。但是,当您分配时,您正在更改该实例的引用以指向不同的变量,这解释了value的行为。
如果您希望从list_value获取实例变量行为,请在构造函数中(称为__init__的类方法)初始化它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接