优雅的解包可变长度元组

时间:2013-07-31 10:04:41

标签: python tuples

一个真实的,如果愚蠢的问题:

https://github.com/joshmarshall/tornadorpc/blob/master/tornadorpc/base.py

def start_server(handlers, ...):
    ...
    for (route, handler) in handlers:
        ...

通常“处理程序”是2元素元组的列表。但是通过这个特殊的解决方案(Tornado),您可以将第三个参数传递给特定的处理程序(kw args)。所以“处理程序”中的元组有时可能有2个元素,有时可能有3个元素。

我需要在循环中解压缩它。当然,我可以像长度检查或尝试那样做。除了打开包装。啊。

你能想到更好/更聪明的事情吗?

In [8]: handlers
Out[8]: [(1, 2), (3, 4, 5), (6, 7)]


In [9]: new_handlers = [x + (None,) for x in handlers]

2 个答案:

答案 0 :(得分:5)

如果该处理程序采用关键字参数,则使用字典作为第三个元素:

handlers = [(1, 2, {}), (3, 4, {'keyword': 5), (6, 7, {})]

for route, handler, kwargs in handlers:
    some_method(route, handler, **kwargs)

或者您可以使用*args语法应用参数;在这种情况下,只需在循环中捕获所有值:

for args in handlers:
    some_method(*args)

如果解压缩到至少2个参数中,请在单独的步骤中执行此操作:

for handler in handlers:
    route, handler, args = (handler[0], handler[1], handler[2:])

其中args将是0或更多元素的元组。

在Python 3中,您可以使用splat(*)目标处理任意宽度解包:

for route, handlers, *args in handlers:

其中*args在解包中捕获0个或更多额外值。

另一条路线,handlers中的元素到最小长度可以通过以下方式完成:

[(h + (None,) * 3)[:3] for h in handlers]

演示:

>>> handlers = [(1, 2), (3, 4, 5), (6, 7)]
>>> [(h + (None,) * 3)[:3] for h in handlers]
[(1, 2, None), (3, 4, 5), (6, 7, None)]

答案 1 :(得分:2)

从Python 3开始,您可以使用PEP 3132扩展解包:

for route, handler, *kw in handlers:
    ...

如果这不是一个选项,请与中间人解包:

for handler in handlers:
    (route, handler), kw = handler[:2], handler[2:]
相关问题