关于python:可怕的初始值-可变类型共享相同的引用?

Terrifying initial values - mutable types share same reference?

本问题已经有最佳答案,请猛点这里访问。

我刚被拥有。我不敢相信这是真的,但经过测试,我发现它是:

1
2
3
4
5
class A(object):
    v = []

a = A()
b = A()

您认为下面的代码将返回什么?

1
a.v is b.v

这个代码怎么办?

1
2
a.v.append(1)
a.v[0] == b.v[0]

可以肯定的是,a.v is b.v中,它们对同一个列表的引用是相同的。从其他编程语言的背景来看,这有什么意义?

在Java中,如果我要写一个这样的类:

1
2
3
class A {
    public Object[] v = new Object[]{};
}

…在我最疯狂的梦中,我永远不会想到类的两个实例将共享对数组的相同引用。

我的主要问题是,Python类中的初始值是否等同于爪哇、C等?为什么类的所有实例都共享对同一列表的相同引用?


您定义了类属性而不是实例属性。Python做得对。

而不是

1
2
class A(object):
    v = []               # Class attribute, shared across all instances!

你需要

1
2
3
class A(object):
    def __init__(self):  # Instance attribute, created anew for each new object
        self.v = []


Java语法与Python不同。试着根据Java知识尝试使用正确的方法不是一个好主意。

1
2
3
4
5
6
7
class A(object):
    v = []  # class attribute


class A(object):
    def __init__(self):
        self.v = []  # instance attribute

好吧,规则有点滑稽。

如果尝试访问self.v,首先python会查找实例属性,如果没有实例属性,则会查找该类,然后查找父类,直到找到实例属性或引发属性错误为止。

当您分配给self.v时,它总是将它绑定到一个实例属性,即使它以前不是。

还有描述符…


这是因为EDOCX1×0是一个类属性(在C++中考虑EDCOX1×4的成员变量)。

如果需要非共享成员属性,则必须在构造函数中声明它:

1
2
3
class A(object):
    def __init__(self):
        selv.v = []

1
2
class A(object):
    v = []

在这里,v是一个类属性而不是实例属性,它们在类定义期间只定义一次。所以,这就是为什么它指向同一个物体。

改为使用实例属性:

1
2
3
4
5
6
class A(object):
    def __init__(self):
        self.v = []     #different for each instance
a= A()
b = A()
print a is b  #prints False