为什么 python 在元组设计中选择逗号而不是括号?

Why did python choose commas over parenthesis in tuple design?

来自python wiki

Multiple Element Tuples

In Python, multiple-element tuples look like:

1,2,3

...

but again, it is the commas, not the parentheses, that define the tuple.

哦,真的吗?!

那为什么:

>>> tuple((((((1, 2, 3)))))) # creates a valid tuple
# (1, 2, 3)
>>> tuple(1, 2, 3, ) # But not here
# TypeError: tuple() takes at most 1 argument (3 given)

更严重的是,我不明白为什么没有选择括号而不是逗号?

因为我认为在以下情况下会产生悖论:

>>> 1, # is a valid tuple
# (1,)
>>> tuple([1]) # Or this
# (1,)
>>> tuple(1) # But not this one
# TypeError: 'int' object is not iterable

但是,如果您认为括号 总是 负责实例化 tuple,那么实例化 tuple 与多个项目的所有问题都是走了。

例如在我想象的世界里:

>>> (1, 2, 3) # stay valid
# (1, 2, 3)
>>> (1) # is newly valid
# (1)
>>> () # stay valid
# ()
>>> 1, 
# TypeError: int() takes exactly 1 argument (2 given) 

我知道这是一个众所周知的功能,如果重复,我已经很抱歉了。我发现了很多关于元组如何工作的类似主题,但是 none 详细解释了为什么要这样创建此功能。

我也知道这个主题可以基于意见关闭,但我最感兴趣的是技术原因(如果有的话),或者至少历史原因.

谢谢

这是 grammar 的神器。

用逗号分隔的术语是元组、列表和集合的构建块,具体取决于它们是被方括号、大括号包裹还是什么都不包裹。

指定语法时的主要挑战是平衡相同字符的多种竞争使用。逗号分隔列表、元组、字典和集合的各个部分。逗号还在函数调用中分隔参数。尾随逗号允许用于这两种用途(并且对于长度为一的元组是必需的)。同样,圆括号有多种用途,包括函数调用和算术表达式的分组。句点用作小数点并用于 getattribute 运算符。

tuple(..) 接受多个参数的原因是因为 (1) 具有应转换为的可迭代对象的单个元素之间可能存在混淆一个元组,以及 (2) 个多个参数。

假设您使用单个可迭代元素调用元组,那么可能会混淆 Python 是否应该使用 一个 元素构造一个元组:可迭代;或基于给定可迭代构造的元组。 Python的设计者选择了后者。正如在 documentation:

中指定的

tuple(iterable)

这是合理的,因为可以写:

tuple(x*x for x in somelist if x%2)

例如用 somelist 的奇数元素的平方构造一个元组。

在你的第一个例子中:

tuple((((((1, 2, 3))))))

您已经构造了一个元组(1, 2, 3)。现在将该元组作为唯一参数传递给元组构造函数。由于元组是可迭代的,因此您可以根据传递的唯一可迭代构造一个元组。

你的表情:

tuple(1, 2, 3, )

但是会引发错误,因为您提供的元素多于您 可以 并且 应该 通过的唯一元素。

接下来你有元组文字。文字是逗号分隔的表达式列表。它用给定的元素构造一个元组。但是,如果您调用一个没有附加括号的方法,则会混淆 (1) 元组文字;和 (2) 您传递给该方法的多个参数。

Python 中还有其他 "grammar" 方面。例如,如果您将生成器传递给具有多个参数的函数,则生成器也需要用括号括起来。

通常,parens除了分组之外不提供任何服务,但是当它们出现在可调用对象之后时,它们具有与分组表达式不同的含义; Python 与 Haskell 不同,需要那些 parens 才能拨打电话。

在以下示例中,parens 的外部对绑定到函数调用(语言构造),而嵌套的对将内部表达式(函数参数)分组为一个元组:

>>> tuple((1, 2, 3))
(1, 2, 3)

本质上,元组是由逗号创建的。