0

这两个类定义的结构相同,除了在奇怪的()类定义中,属性“d”是一个列表,而在 normal() 类定义中它是一个 int。我不明白为什么怪异()类会导致 self.d = d,而类 normal()则不是这种情况。为什么在这种情况下 Python 对待 int 和 list 的方式不同?

class weird:
    def __init__(self):
        d = [1,2,3]
        self.d = d
        for x in range(3):
            d[x] = 10+x 
        print "d =", d
        print "self.d =", self.d

class normal:
    def __init__(self):
        d = 1
        self.d = d
        d = 11
        print "d =", d
        print "self.d =", self.d

当我运行代码时,我得到

>>> a=weird()
d = [10, 11, 12]
self.d = [10, 11, 12]
>>> b=normal()
d = 11
self.d = 1
4

4 回答 4

7

您将分配与对象的突变混淆了。

在一种方法中,您为 分配了新值d,从而更改了它所指向的内容:

d = 11

但在另一种方法中,您更改了包含在以下内容中的值d

d[x] = 10 + x

注意[x]那里;本质上,您是在告诉 python 这样做:

d.__setitem__(x, 10 + x)

d指向列表的变量的值永远不会改变。引用的列表中的值d确实发生了变化。

看看我以前的答案,它更详细地说明了这两个语句之间的区别:Python list does not reflect variable change

于 2012-12-17T17:20:12.063 回答
2

事实上,这里的语言是完全一致的。您正在观察两种不同的行为,因为您正在执行两种根本不同的操作。

的前两行在__init__两个类中都是一致的(除了不同类型的d):

class WeirdOrNormal:
    def __init__(self):
        d = ... # 1 or [1, 2, 3]
        self.d = d

此时,两者都dself.d代同一个对象。

然而,在那之后,这两个类别出现了分歧:

  1. weird通过引用修改对象:

    for x in range(3):
        d[x] = 10+x 
    

    由于两者都dself.d代同一个对象,因此可以通过两者观察到变化。

  2. normal重新绑定d以指向除以下之外的某个地方self.d

    d = 11
    

    通过这样做,您已经断开了 和 之间的d链接self.d。他们现在完全独立了。

如果您要更改weird以重新绑定引用,就像这样normal做一样,您会看到这两个类的行为彼此一致:

class notweird:
    def __init__(self):
        d = [1,2,3]
        self.d = d
        d = [10+x for x in self.d]
        print "d =", d
        print "self.d =", self.d

a = notweird()

这打印

d = [11, 12, 13]
self.d = [1, 2, 3]
于 2012-12-17T17:23:50.713 回答
1

对于文档:

值可以改变的对象称为可变对象;其值一旦创建就不可更改的对象称为不可变对象。(包含对可变对象的引用的不可变容器对象的值可以在后者的值更改时更改;但是容器仍然被认为是不可变的,因为它包含的对象集合不能更改。因此,不可变性并不是严格意义上的与具有不可更改的值相同,它更微妙。)对象的可变性由其类型决定;例如,数字、字符串和元组是不可变的,而字典和列表是可变的。

在你的情况下list是可变的,int是不可变的。没什么奇怪的。

更多关于数据模型

于 2012-12-17T17:16:19.397 回答
0

在第一个示例中,两者d和都self.d指向一个可变对象。当您将十个添加到对象中的元素时,您正在修改该可变对象。因为d和都self.d指向那个对象,所以他们都“看到”了结果。

在第二个示例中,您重新分配 d 以指向不同的不可变数字,因此dself.d指向两个不同的事物。

请注意区别:在一种情况下,它们都指向您正在更改的相同值,而在另一种情况下,它们指向两个不同的值。

于 2012-12-17T17:17:30.267 回答