优雅的拆包可变长度元组

Let*_*t4U 5 python tuples

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

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

def start_server(handlers, ...):
    ...
    for (route, handler) in handlers:
        ...
Run Code Online (Sandbox Code Playgroud)

通常,“处理程序”是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]
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

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

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

for route, handler, kwargs in handlers:
    some_method(route, handler, **kwargs)
Run Code Online (Sandbox Code Playgroud)

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

for args in handlers:
    some_method(*args)
Run Code Online (Sandbox Code Playgroud)

如果您必须解压缩至少两个参数,请在一个单独的步骤中进行解压缩:

for handler in handlers:
    route, handler, args = (handler[0], handler[1], handler[2:])
Run Code Online (Sandbox Code Playgroud)

其中args将是一个包含0个或更多元素的元组。

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

for route, handlers, *args in handlers:
Run Code Online (Sandbox Code Playgroud)

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

另一种方法是,以handlers最小长度插入元素:

[(h + (None,) * 3)[:3] for h in handlers]
Run Code Online (Sandbox Code Playgroud)

演示:

>>> 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)]
Run Code Online (Sandbox Code Playgroud)