【问题标题】:Why can't I add a tuple to a list with the '+' operator in Python?为什么我不能在 Python 中使用“+”运算符将元组添加到列表中?
【发布时间】:2012-03-27 20:20:35
【问题描述】:

Python 不支持将元组添加到列表中:

>>> [1,2,3] + (4,5,6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list

在语言中提供这种支持有什么缺点?请注意,我希望这是对称的:[1, 2] + (3, 4)(1, 2) + [3, 4] 都将评估为一个全新的列表 [1, 2, 3, 4]。我的理由是一旦有人将运算符 + 应用于元组和列表的混合,他们很可能会再次这样做(很可能在同一个表达式中),所以我们不妨提供列表以避免额外的转换。

这是我提出这个问题的动机。

经常发生我喜欢将小集合存储为元组以避免意外修改并提高性能的情况。然后我需要将这样的元组与列表结合起来,并且必须将它们中的每一个都转换为列表会导致代码非常难看。

请注意,+=extend 可能适用于简单的情况。但总的来说,当我有表情时

columns = default_columns + columns_from_user + calculated_columns

我不知道哪些是元组,哪些是列表。所以我要么必须将所有内容都转换为列表:

columns = list(default_columns) + list(columns_from_user) + list(calculated_columns)

或者使用itertools:

columns = list(itertools.chain(default_columns, columns_from_user, calculated_columns))

这两种解决方案都比简单的求和更难看; chain 也可能更慢(因为它必须一次遍历一个元素的输入)。

【问题讨论】:

  • 保持一致怎么样?使用元组或列表,但不能同时使用。
  • 如果它被支持完全我同意这将是最好的行为,但我认为如果有人这样做2 + 'abc'他们显然想要'2abc'所以为什么不允许它,等等等等——它的解释太多了。显式优于隐式。
  • 你可以简单地使用itertools.chain 来链接你的东西,而不是使用+
  • 我想说你的论点中的弱点是“他们可能再做一次”
  • 你不能这样链接extends。你必须.extend(chain(...))

标签: python operator-overloading language-design internals


【解决方案1】:

这不受支持,因为 + 运算符应该是对称的。您期望什么返回类型? Python Zen 包含规则

面对模棱两可,拒绝猜测。

以下是可行的:

a = [1, 2, 3]
a += (4, 5, 6)

这里使用什么类型没有歧义。

【讨论】:

  • 我希望返回是一个列表,因为一旦我开始使用 + 运算符,我可能需要再做一次。请参阅我对问题的更新。
  • @max:我不明白为什么这应该总是返回一个列表。我很高兴 Python 在这种情况下会抛出错误,我相信这永远不会改变。
  • @max:你问过为什么 Python 不支持将元组添加到列表中。恕我直言,斯文的回答明确了这个问题。
  • @SvenMarnach 您能否描述一些您会很高兴 tuple + list 引发异常而不是像我描述的那样静默工作的情况?
  • 这太疯狂了。列表添加不是对称的!!!序列“+”的一个非常简单/明确的语义是返回其第一个参数的类型。该函数已经不是对称的。对我来说似乎是一个似是而非的限制。
【解决方案2】:

为什么python不支持添加不同的类型:简单的答案是它们是不同的类型,如果你尝试添加一个可迭代对象并期望一个列表出来怎么办?我自己想返回另一个迭代。还要考虑['a','b']+'cd' 应该是什么输出?考虑到显式优于隐式,所有此类隐式转换都是不允许的。

为了克服这个限制,使用extend list 方法添加任何可迭代的例如

l = [1,2,3]
l.extend((4,5,6))

如果你必须添加许多列表/元组,请编写一个函数

def adder(*iterables):
    l = []
    for i in iterables:
        l.extend(i)
    return l

print adder([1,2,3], (3,4,5), range(6,10))

输出:

[1, 2, 3, 3, 4, 5, 6, 7, 8, 9]

【讨论】:

  • 他知道怎么做,他想知道为什么用+做不到。
  • @agf: “并且必须将它们中的每一个都转换为列表会导致非常丑陋的代码”。不,显然他没有,因为.extend() 不会转换任何东西。
  • @RikPoggi 他想要一个像[1] + (2,) + (3,) + [4] + (5,) 这样的长表达式能够在没有转换的情况下立即完成,或者chain 或类似的东西没有简单的缘故。任何在一行中使用extend 的代码都会比那个加法表达式更难看。
  • @RikPoggi “我的理由是,一旦有人将运算符 + 应用于元组和列表的混合,他们很可能会再次这样做(很可能在同一个表达式中),所以我们不妨提供避免额外转换的列表。”查看他对extend 清楚了解的问题的新编辑。
  • 对不起,我的错没有在原始问题中写下更多细节。查看更新。
【解决方案3】:

如果有帮助,您可以使用 += 运算符:

>>> x = [1,2,3]
>>> x += (1,2,3)
>>> x
[1, 2, 3, 1, 2, 3]

您也可以显式使用列表构造函数,但就像您提到的那样,可读性可能会受到影响:

>>> list((1,2,3)) + list((1,2,3))
[1, 2, 3, 1, 2, 3]

【讨论】:

  • 如果我只有一个元组要添加的话。我经常有几个对象,一些元组,一些列表。
猜你喜欢
  • 2023-04-03
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 2014-11-29
相关资源
最近更新 更多