Python中tuple内的list元素为什么能被修改?

先定义一个 tuple 元素 t = ('a', 'b', ['A', 'B']) 然后代码如下: list = t[2]; list[0] = 'OHOH'; print t; list[1] = 'OHOH'; print t;

输出结果: ('a', 'b', ['OHOH', 'B']) ('a', 'b', ['OHOH', 'OHOH'])

问题:这里明明是把 t[2]取出来赋值给了 list,按说无论怎么修改 list,修改的只是 list 的值,并不会影响 t 中的 list 值,但事实是确实影响了,为什么?


Python中tuple内的list元素为什么能被修改?

10 回复

python 日经贴。可以了解下 python 的 object 引用


这个问题问得好,很多人刚开始学Python时都会被这个“坑”到。

简单来说,元组(tuple)的“不可变”指的是它存储的“引用”不可变,而不是引用指向的对象本身不可变。

我给你画个图就明白了:

my_tuple = (1, 2, [3, 4])

在内存里大概是这样的:

my_tuple --> [引用1, 引用2, 引用3]
              |      |      |
              1      2      |
                           ↓
                         [3, 4]  ← 这个列表对象本身是可变的

元组my_tuple里存的是三个引用(指针),分别指向整数1、整数2和一个列表对象。元组保证的是这三个引用永远不变——第一个位置永远指向整数1,第二个永远指向整数2,第三个永远指向同一个列表对象

但是,这个列表对象本身是独立的、可变的。所以你可以:

my_tuple[2].append(5)  # 修改列表,完全没问题
print(my_tuple)  # 输出:(1, 2, [3, 4, 5])

# 但你不能这样做:
my_tuple[2] = [7, 8]  # TypeError: 'tuple' object does not support item assignment
# 因为这是在尝试改变元组第三个位置的引用

这就好比你的通讯录(元组)里记着朋友的电话号码(引用)。你可以随时打电话给朋友(通过引用访问对象),朋友也可以换发型、换衣服(修改对象内容)。但你不能把你通讯录里记的号码本身改成另一个人的号码(修改引用)。

所以记住:元组保证的是“引用不变”,而不是“引用指向的对象内容不变”。

一句话总结:元组固定的是引用,不是被引用的对象。

学到了,刚明白,感谢🙏🏻

流畅的 Python 里说过,指向同一个内存空间

你还修改了 list 本身

  1. 虽然楼主已经知道,还是自作多情解释一下: python 与 C/C++/Golang 有个明显的不同是: 它不允许程序员选择传值或者传址(或者说传引用、传指针)。Python 采用的参数传递采用是"传对象引用": 如果一种不可改变对象,如 str, int, float 等,那么它无法被修改,相当于传值; 另一种是可改变对象,list, dict,那么它总是会修改,相当于传址。
    2. list 是内建类型,不建议作为变量名。

是的,正如如一楼所说,主要是 python 中的 list 的指针指向不变性导致的

哦哦🙏🏻

嗯嗯,解释的很详细了,太感谢了🙏🏻

修改了 list 指向而已,实际上并没有改变

回到顶部