有人可以在Python中澄清这两个符号:
[ [] ] * n
:显然这会创建对同一对象的n个引用(在本例中为空列表)。在哪种情况下这有用? (i,)
:我看到有些人在sets
函数的定义中使用了这种“尾随逗号”符号(例如:Generating all size k subsets of {0, 1, 2, ... n-1})。这是什么意思?答案 0 :(得分:10)
是的,确实会创建对同一对象的引用:
>>> L = [[]] * 3
>>> L
[[], [], []]
>>> L[0].append(1)
>>> L
[[1], [1], [1]]
>>> map(id, L)
[4299803320, 4299803320, 4299803320]
这对于您想要创建具有相同项目的对象非常有用。
(i,)
使用项i
创建一个元组:
>>> mytuple = (5,)
>>> print mytuple
(5,)
>>> print type(mytuple)
<type 'tuple'>
需要逗号的原因是因为否则它将被视为整数:
>>> mytuple = (5)
>>> print mytuple
5
>>> print type(mytuple)
<type 'int'>
答案 1 :(得分:3)
[ [] ] * n
创建对同一个空列表对象的n
个引用。这几乎总是一个错误,因为通常你最终会在其中一个n
列表上使用破坏性操作,然后当它应用于外部列表中的“所有”元素时会感到惊讶。
但是[0] * n
创建对同一整数零对象的n
引用。像这样的表达式可以很方便地初始化计数器列表(你可能会继续替换列表中的各个插槽)。由于整数是不可变的,因此没有意外地改变“全部”零的危险。对于任何其他“不可变的一直向下”类型也是如此(不一定是元组,因为虽然元组本身是不可变的,但它可以包含可变值)。
所以这个“列表乘法”操作并没有用。但我建议避免使用除之外的复制保证不可变值列表的具体情况。虽然可以安全地使用可变值列表可以,但它是如此脆弱,并且经常是错误的根本原因,即使这是你的意思,你最好在稍微冗长一点的方式让你明白你真正的意思。
对于(i,)
,Python允许在列表,字典,元组和集合文字中使用“额外”逗号。例如,以下各项均有效:
(1, 2, 3,)
[1, 2, 3,]
{1: 'one', 2: 'two', 3: 'three',}
{1, 2, 3,}
如果你遗漏了尾随的逗号,这没有任何不同之处,只是允许它作为可选的附加内容。
返回(i,)
。这只是一个带有尾随逗号的项目的元组。但是有一个问题;对于仅包含一个项目的元组的特殊情况,尾随逗号不是可选的附加,它是强制。这是因为“one-tuple”否则会被写成(i)
,但是已经采用了这种句法形式来使用括号来对子表达式进行分组(例如,你无法判断(1 + 1) * 2
是否是假设生成4
或(2, 2)
)。
顺便说一下,当您将多元组/列表/字典/集分割为多行时,您可能希望使用可选尾随逗号的原因有时更明显:
foo = [
'this',
'is',
'a',
'long',
'list',
]
使用此样式编写,只需重新排序源代码行即可重新排序列表。如果我重新订购的项目之一是列表中的最后一项,我就不必去清理逗号。
同样,如果我正在使用版本控制,则在最后一个项目之后添加更多项目不会更改先前最终项目的行,因此差异是纯粹的添加。如果最后一行没有逗号,则需要添加一个以添加更多项目,这会将更改记录为对该行的编辑,这会使合并冲突(稍微)更可能,并且历史记录(稍微)更难以读取。
答案 2 :(得分:0)
[[]] * n创建对同一可变列表的引用。很多时候,这不是所需要的,而是需要可以单独修改的唯一列表对象。要做到这一点,你可以使用它:
list_of_lists = [[] for x in xrange(n)]
答案 3 :(得分:0)
到目前为止,[...] * n
的最常见用途必须是grouper recipe
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)