查看: 2062|回复: 2

TypeError: 'tuple' object does not support item assignment

[复制链接]

15

主题

97

帖子

310

积分

论坛管理

Rank: 4

积分
310
发表于 2018-9-19 08:55:52 | 显示全部楼层 |阅读模式
运行下面代码
  1. tup = ([1,2,3],[7,8,9])
  2. tup[0] += (4,5,6)
复制代码

生成此错误:
TypeError: 'tuple' object does not support item assignment
虽然这段代码:
  1. tup = ([1,2,3],[7,8,9])
  2. try:
  3.     tup[0] += (4,5,6)
  4. except TypeError:
  5.     print tup
复制代码

然而输出tup:
([1, 2, 3, 4, 5, 6], [7, 8, 9])
这种行为是合理的吗?
回复

使用道具 举报

22

主题

107

帖子

266

积分

中级会员

Rank: 3Rank: 3

积分
266
发表于 2018-9-19 08:57:47 | 显示全部楼层
是的,这是合理的。
元组无法更改。像列表一样的元组是指向其他对象的结构。它并不关心那些对象是什么。它们可以是字符串,数字,元组,列表或其他对象。
因此,对元组中包含的某个对象执行任何操作,包括如果它是列表,则附加到该对象,与元组无关。
或者另一个例子:
  1. >>> l1 = [1, 2, 3]
  2. >>> l2 = [4, 5, 6]
  3. >>> t = (l1, l2)
  4. >>> l3 = [l1, l2]
  5. >>> l3[1].append(7)
复制代码

由列表和元组引用的两个可变列表。最后一行不会报错。
如果你想要一个连续结构的不可变对象,那么它应该一直是元组。
为什么会出错?
  1. l = [1, 2, 3]
  2. tup = (l,)
  3. tup[0] += (4,5,6)
复制代码

相当于:
  1. l = [1, 2, 3]
  2. tup = (l,)
  3. x = tup[0]
  4. x = x.__iadd__([4, 5, 6]) # like extend, but returns x instead of None
  5. tup[0] = x
复制代码

该__iadd__行成功,并修改第一个列表。所以列表已经改变了。该__iadd__调用返回变异列表。
第二行尝试将列表分配回元组,这会失败。
因此,在程序结束时,列表已被扩展,但操作的第二部分+=失败。
回复

使用道具 举报

13

主题

53

帖子

131

积分

注册会员

Rank: 2

积分
131
发表于 2018-9-19 08:58:18 | 显示全部楼层
嗯,我想tup[0] += (4, 5, 6)等价于:
tup[0] = tup[0].__iadd__((4,5,6))
tup[0].__iadd__((4,5,6))通常在第一个元素中更改列表。但由于元组是不可变的,因此赋值失败
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表