请问有人能澄清Python中的这两个符号:
[ [] ] * n
:显然这会创建n个指向同一个对象(在本例中为一个空列表)的引用。在哪些情况下会有用?(i,)
:我看到一些人在sets
函数的定义中使用了这种“尾随逗号”符号(例如:生成{0, 1, 2,... n-1}所有大小为k的子集)。这是什么意思?
请问有人能澄清Python中的这两个符号:
[ [] ] * n
:显然这会创建n个指向同一个对象(在本例中为一个空列表)的引用。在哪些情况下会有用?(i,)
:我看到一些人在sets
函数的定义中使用了这种“尾随逗号”符号(例如:生成{0, 1, 2,... n-1}所有大小为k的子集)。这是什么意思?是的,它确实会创建指向同一对象的引用:
>>> 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'>
[ [] ] * n
会创建n
个对同一个空列表对象的引用。这几乎总是一个错误,因为通常您会在n
个列表中的一个上使用破坏性操作,然后当它应用于外部列表的“所有”元素时感到惊讶。
然而,[0] * n
会创建n
个对整数零对象的同一引用。像这样的表达式对于初始化计数器列表非常方便(您可能随后会替换列表中的单个插槽)。由于整数是不可变的,因此没有意外更改“所有”零的危险。其他“完全不可变”的类型也是如此(不一定是元组,因为尽管元组本身是不可变的,但它可以包含可变值)。
因此,“列表乘法”操作并不无用。但我建议除了复制保证不可变值的列表之外,避免使用它。虽然可以安全地将可变值的列表相乘,但它太脆弱了,往往是错误的根本原因,即使这是您要做的事情,您最好以稍微冗长的方式完成它,以使显然您确实是认真考虑它。
至于(i,)
,Python允许在列表、字典、元组和集合文字中使用“额外”逗号。例如,以下都是有效的:
(1, 2, 3,)
[1, 2, 3,]
{1: 'one', 2: 'two', 3: 'three',}
{1, 2, 3,}
foo = [
'this',
'is',
'a',
'long',
'list',
]
使用这种风格的书写方式使我能够通过重新排列源代码行来重新排序列表; 如果我重新排序的其中一项是列表中的最后一项,我就不必去清理逗号。
同样地,如果我正在使用版本控制,添加更多的项到最后一项不会改变先前最终项的行,因此差异是一个纯粹的添加。如果最后一行没有逗号,则需要添加一个逗号以添加更多项,这将使更改记录为对该行的编辑,从而使合并冲突(略微)更有可能,并且历史日志(稍微)更难阅读。
[[]] * n会创建对同一个可变列表的引用。很多时候这不是需要的,相反你需要独立修改的唯一列表对象。为了做到这一点,你可以使用以下代码:
list_of_lists = [[] for i in xrange(n)]
到目前为止,[...] * n
最常见的用途必须是 分组配方
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)
(i,)
жҳҜдёҖдёӘеҢ…еҗ«е…ғзҙi
зҡ„е…ғз»„гҖӮжң«е°ҫзҡ„йҖ—еҸ·жҳҜеӣ дёә(i)
зӯүеҗҢдәҺi
гҖӮ - falsetrui,
中不需要括号。 - Lie Ryanreturn i,
,a, = [1]
等是可以的。但对于func(i,)
,i, + another_tuple
等则不行。 - falsetru