python变量是指针?

python variables are pointers?

据我所知,python中的变量只是指针。

基于此规则,我可以假设此代码段的结果:

1
2
3
4
i = 5
j = i
j = 3
print(i)

可能是3。但我得到了一个意想不到的结果,那就是江户十一〔一〕号。

此外,我的python书确实涵盖了以下示例:

1
2
3
4
i = [1,2,3]
j = i
i[0] = 5
print(j)

结果将是[5,2,3]

我理解错了什么?


我们称之为参考文献。他们是这样工作的

1
2
3
4
i = 5     # create int(5) instance, bind it to i
j = i     # bind j to the same int as i
j = 3     # create int(3) instance, bind it to j
print i   # i still bound to the int(5), j bound to the int(3)

小整数被拘留,但这对这个解释并不重要。

1
2
3
4
i = [1,2,3]   # create the list instance, and bind it to i
j = i         # bind j to the same list as i
i[0] = 5      # change the first item of i
print j       # j is still bound to the same list as i


变量不是指针。当您分配给一个变量时,您正在将名称绑定到一个对象。从这一点开始,您可以通过使用名称来引用对象,直到该名称被反弹为止。

在第一个示例中,名称i与值5绑定。将不同的值绑定到名称ji没有任何影响,因此稍后打印i的值时,该值仍为5

在第二个示例中,您将ij绑定到同一列表对象。当您修改列表的内容时,无论您使用哪个名称引用列表,都可以看到更改。

请注意,如果您说"两个列表都已更改",则是不正确的。只有一个列表,但它有两个名称(ij引用它。

相关文件

  • 执行模型-命名和绑定


python变量是绑定到对象的名称

来自文档:

Names refer to objects. Names are introduced by name binding operations. Each occurrence of a name in the program text refers to the binding of that name established in the innermost function block containing the use.

当你这样做的时候

1
2
i = 5
j = i

就像这样:

1
2
i = 5
j = 5

j不指向i,任务完成后,j不知道i存在。j简单地与i在分配时所指的内容绑定在一起。

如果您在同一行上执行了任务,则如下所示:

1
i = j = 5

结果完全一样。

因此,以后做

1
i = 3

不改变j所指的东西,你也可以交换它。j = 3不会改变i所指的东西。

您的示例不会取消引用列表

所以当你这样做的时候:

1
2
i = [1,2,3]
j = i

就像这样:

1
i = j = [1,2,3]

因此,ij都指向同一个列表。然后您的示例改变了列表:

1
i[0] = 5

python列表是可变的对象,所以当您从一个引用中更改列表,并从另一个引用中查看它时,您将看到相同的结果,因为它是相同的列表。


它们不是很好的指针,它们是对对象的引用。对象可以是可变的,也可以是不可变的。不可变对象在修改时被复制。一个可变的物体被改变了位置。整数是不可变的对象,由I和J变量引用。列表是可变对象。

在第一个例子中

1
2
3
4
5
6
7
8
i=5
# The label i now references 5
j=i
# The label j now references what i references
j=3
# The label j now references 3
print i
# i still references 5

在第二个示例中:

1
2
3
4
5
6
7
8
i=[1,2,3]
# i references a list object (a mutable object)
j=i
# j now references the same object as i (they reference the same mutable object)
i[0]=5
# sets first element of references object to 5
print j
# prints the list object that j references. It's the same one as i.

"="符号左侧的Ever变量与"="符号右侧的值一起赋值。

i = 5

j = i—j有5个

j = 3--j有3个(覆盖了5的值),但是关于i没有任何改变。

print(i)--所以这张照片是5


赋值不会修改对象;它所做的只是更改变量点的位置。改变一个变量点的位置不会改变另一个变量点的位置。

您可能会想到数组和字典是可变类型。有一些运算符可以在适当的位置修改实际对象,如果使用其中一个,则可以看到指向同一对象的所有变量的变化:

1
2
3
4
x = []
y = x
x.append(1)
# x and y both are now [1]

但分配仍然只是移动指针:

1
2
x = [2]
# x is now [2], y is still [1]

数字是值类型,这意味着实际值是不可变的。如果你做了x=3; x += 2,你就不会把数字3变成数字5;你只是让x指向5而不是3。3仍然保持不变,任何指向它的变量仍然会看到3作为它们的值。

(在实际的实现中,数字可能不是引用类型,变量实际上包含值的直接表示,而不是指向它,但是这种区别不会改变涉及值类型的语义。)


当设置j=3时,标签j不再适用于i时,它开始指向整数3。名称i仍指您最初设置的值5


在Python中,一切都是对象,包括返回的内存片段本身。这意味着,当创建新的内存块时(不管您创建了什么:int、str、custom对象等),都会有一个新的内存对象。在您的例子中,这是对3的赋值,它创建一个新的(内存)对象,从而有一个新的地址。

如果你运行下面的程序,你会很容易明白我的意思。

1
2
3
4
5
i = 5
j = i
print("id of j: {}", id(j))
j = 3
print("id of j: {}", id(j))

在内存方面,这是C和Python之间的关键理解/区别。在C/C++中,返回一个内存指针(如果你使用指针语法当然是),而不是内存对象,这会给你在更改引用地址方面提供更多的灵活性。