前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >疯狂的元组

疯狂的元组

作者头像
somenzz
发布2022-10-25 20:09:38
4170
发布2022-10-25 20:09:38
举报
文章被收录于专栏:Python七号Python七号

你好,我是征哥,今天分享一道 Python 题目,可能会让你涨点知识。

题目:以下代码的输出结果是什么?

代码语言:javascript
复制
>>> crazy_tuple = (["x","y"],)
>>> crazy_tuple[0] = crazy_tuple[0].__iadd__(["z"])
>>> print(crazy_tuple[0])
???

选项:

  • A) ["x", "y"]
  • B) ["x", "y", "z"]
  • C) 会抛出 TypeError 异常
  • D) 有没有搞错?

先铺垫一个小知识,列表的魔法函数 __iadd__ 相当于列表的 extend 函数,但是会返回扩展后的结果:

代码语言:javascript
复制
>>> [1,2,3].__iadd__([4])
[1, 2, 3, 4]

接下来你会选择哪个选项呢?

等你 30 秒。

接下来在 Python 解释器上运行一下,看看是否符合你的预期:

代码语言:javascript
复制
>>> crazy_tuple = (["x","y"],)
>>> crazy_tuple[0] = crazy_tuple[0].__iadd__(["z"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> print(crazy_tuple[0])
['x', 'y', 'z']
>>>

会发现,第二行代码抛出了 TypeError 异常,告诉我们,元组不支持元素赋值,此时,你会选择 C,但是打印第一个元素(列表)时发现列表添加了 'z',你又选择了 B。

你又想了想,Python 是不是搞错了,既然你不支持元组内的元素重新赋值,还让它赋值了,是不是搞错了,你想选择 D。

所以这很 crazy !

现在来一起梳理一下。

首先,crazy_tuple 是一个元组,元组不可变,是指元组内元素的地址永不改变:

代码语言:javascript
复制
>>> crazy_tuple = (["x","y"],)
>>> id(crazy_tuple[0])
140468737595456

凡是对列表内的元素使用 = 操作符号的,均抛出 TypeError 异常

代码语言:javascript
复制
>>> id(crazy_tuple[0])
140468737595456
>>> crazy_tuple[0] = object()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> id(crazy_tuple[0])
140468737595456
>>> crazy_tuple[0]
['x', 'y']
>>>

虽然抛出了异常,但是地址仍然不变。

我们执行的代码是 crazy_tuple[0] = crazy_tuple[0].__iadd__(["z"]),Python 解释器先执行的是等号右边的部分 crazy_tuple[0].__iadd__(["z"])

我们可以这样分解它的执行过程:

代码语言:javascript
复制
tmp = crazy_tuple[0].__iadd__(["z"])
crazy_tuple[0] = tmp

在解释器执行一下:

代码语言:javascript
复制
>>> tmp = crazy_tuple[0].__iadd__(["z"])
>>> crazy_tuple[0]
['x', 'y', 'z']
>>> id(crazy_tuple[0])
140468737595456
>>> crazy_tuple[0] = tmp
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>>
tmp = crazy_tuple[0].__iadd__(["z"])
crazy_tuple[0] = tmp 

可以看出, crazy_tuple[0].__iadd__(["z"]) 执行之后,crazy_tuple[0] 的内容已经发生了变化,但地址不变。

因此,你虽然看到了报错,但是修改的结果还是发生了。

总结:元组的不可变,在于元组内元素的地址不可变。如果元组内元素是字符串、数字、元组等不可变对象,其内容永久不变,如果元组内元素是是列表、字典、集合等可变对象,其内容可以被改变。具体可参考前文Python 基础系列--可变/不可变的数据类型

最后的话

本文分享了一道有趣的 Python 题目,希望对你对 Python 编程有所思考。独学而无友,则孤陋而寡闻

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python七号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 最后的话
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档