为什么下面的例子表现不同?
示例1:foo
似乎表现为特定于各种对象的类变量
class A:
foo = 1
a, b = A(), A()
a.foo = 5
print b.foo
----------------
Output: 1
示例2:foo
似乎表现得像一个对所有对象都相同的静态类变量。也许这种行为与作为指针的列表有关。
class A:
foo = []
a, b = A(), A()
a.foo.append(5)
print b.foo
----------------
Output: [5]
示例3:没有工作
class A:
self.foo = []
a, b = A(), A()
a.foo.append(5)
print b.foo
----------------
Output: Error
答案 0 :(得分:6)
前两个示例都是类属性。他们看起来不同的原因是因为你在两种情况下都没有做同样的事情:你在第一种情况下分配一个新值,在第二种情况下修改现有值。
请注意,您在前两个示例中没有做同样的事情。在第一个示例中,您执行a.foo = 5
,分配新值。在第二个例子中,如果你做了类似的事情,分配a.foo = [5]
,你会看到与第一个例子中相同的结果。但相反,您使用a.foo.append(5)
更改了现有列表,因此行为不同。 a.foo = 5
仅更改变量(即,它指向的值); a.foo.append(5)
更改值本身。
(请注意,没有办法在第一个例子中做第二个例子。也就是说,没有像a.foo.add(1)
那样添加1到5个。那是因为整数不是可变的,但是列表是。但重要的不是列表"是可变的,而是你突变了一个。换句话说,它不重要你可以使用列表,在特定代码中实际执行的操作非常重要。)
另请注意,虽然您在类定义中定义的foo
是类属性,但在执行a.foo = 5
时,您正在实例上创建新属性 。它碰巧与class属性具有相同的名称,但它并没有更改class属性的值,这是b.foo
仍然可以看到的值。
最后一个例子不起作用,因为就像在前两个例子中一样,class
块内的代码在类范围内。没有self
,因为在定义类时还没有实例。
StackOverflow上有很多很多关于此的问题,我恳请您搜索并阅读其中的一些问题,以便更全面地了解其工作原理。
答案 1 :(得分:1)
这不起作用:
class A:
self.foo = []
这会引发错误。
NameError: name 'self' is not defined
因为self
不是Python中的关键字,所以它只是一个变量名,通常分配给在调用类时传递给类方法的类实例。
以下是一个例子:
class A(object):
def __init__(self):
self.foo = []
a, b = A(), A()
a.foo.append(5)
print(b.foo)
然后返回:
[]
当每个人都被初始化时,他们每个人都有自己的列表,可以通过属性foo
访问,当一个被修改时,另一个是存储在内存中不同位置的单独列表,没有受到影响。
答案 2 :(得分:1)
差异与可变性/不变性无关,而是执行了哪些操作。
在示例1中,该类具有属性foo
。创建对象后,为对象提供另一个属性foo
,该属性隐藏前一个属性。因此class属性充当一种“默认”或“后备”。
在示例2中,您有一个对象可以执行操作(当然,它只适用于可变对象)。因此,A.foo
引用的对象(由于缺少具有相同名称的实例属性而可以通过a.foo
和b.foo
访问)会添加{{1} }。
示例3不起作用,因为在您使用它的地方不存在5
。
请注意,示例1也适用于可变对象,例如list:
self
此处class A:
foo = []
a, b = A(), A()
a.foo = []
a.foo.append(5)
b.foo.append(10)
print a.foo # [5]
print b.foo # [10]
print A.foo # [10]
获取一个新的空列表。缺少实例属性的a.foo
继续引用class属性。所以我们有两个相互独立的空列表,正如我们在b.foo
时看到的那样。