元组解包:虚拟变量与索引

时间:2010-04-06 05:24:56

标签: coding-style python

用Python编写这个通常/最清晰的方法是什么?

value, _ = func_returning_a_tuple()

或:

value = func_returning_a_tuple()[0]

4 个答案:

答案 0 :(得分:10)

value = func_returning_a_tuple()[0]似乎更清晰,也可以推广。

如果函数返回的元组值超过2,该怎么办? 如果程序逻辑对一个无数元组的第四个元素感兴趣怎么办? 如果返回的元组的大小变化怎么办?

这些问题都不会影响基于下标的习语,但会出现多分配习语。

答案 1 :(得分:9)

如果您在python3.x中有一种方便的方法,请在Python中查看此page of What's New上的python增强建议(PEP)3132:

扩展的Iterable解包。您现在可以编写a, b, *rest = some_sequence之类的内容。甚至*rest, a = stuff。其余对象始终是(可能为空)列表;右侧可以是任何可迭代的。例如:

(a, *rest, b) = range(5)

这会将a设置为0,将b设置为4,将rest设置为[1, 2, 3]

答案 2 :(得分:6)

为了提取单个项目,索引更加惯用。当您提取两个或更多项目时,解压缩变得更加惯用。这只是我的经验观察;我不知道任何风格指南建议或强制要么选择! - )

答案 3 :(得分:2)

对于具有键/值对的列表/生成器理解,我认为虚拟变量的使用可能非常简洁,特别是在需要多次使用解包值(避免重复索引)的情况下,例如:

l = [('a', 1.54), ('b', 4.34), ('c', 3.22), ('d', 6.43)]
s = [x * (1.0 - x) * (2.0 - x) for _, x in l]

s = [x[0] * (1.0 - x[0]) * (2.0 - x[0]) for x in l]

另外需要注意的是,虽然解包和索引大致相同,但扩展解包似乎要慢一个数量级。

使用Python 3.2在IPython中使用%timeit:

定期拆包:

>>> x = (1, 2)
>>> %timeit y, _ = x
10000000 loops, best of 3: 50 ns per loop

>>> %timeit y, _ = x
10000000 loops, best of 3: 50.4 ns per loop

扩展解包:

>>> x = (1, 2, 3)
>>> %timeit y, *_ = x
1000000 loops, best of 3: 1.02 us per loop

>>> %timeit y = x[0]
10000000 loops, best of 3: 68.9 ns per loop