如何忽略元组的解包部分作为lambda的参数?

时间:2017-12-04 21:51:35

标签: python lambda tuples iterable-unpacking argument-unpacking

在Python中,按照惯例,下划线(_)通常用于丢弃未压缩元组的部分内容,如此

>>> tup = (1,2,3)
>>> meaningfulVariableName,_,_ = tup
>>> meaningfulVariableName
1

我正在尝试为lambda的元组参数做同样的事情。它只能用2元组来完成似乎是不公平的......

>>> map(lambda (meaningfulVariableName,_): meaningfulVariableName*2, [(1,10), (2,20), (3,30)]) # This is fine
[2, 4, 6]

>>> map(lambda (meaningfulVariableName,_,_): meaningfulVariableName*2, [(1,10,100), (2,20,200), (3,30,300)]) # But I need this!
SyntaxError: duplicate argument '_' in function definition (<pyshell#24>, line 1)

任何想法为什么,以及实现这一目标的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

您通常最好使用列表推导而不是lambda s:

some_list = [(1, 10, 100), (2, 20, 200), (3, 30, 300)]
processed_list = [2 * x for x, dummy1, dummy2 in some_list]

如果您真的坚持,可以在此使用_代替dummy1dummy2。但是,我建议不要这样做,因为我经常看到这会造成混乱。人们通常认为_是某种特殊语法(例如在Haskell和Rust中),而它只是一些不寻常的变量名而没有任何特殊属性。使用dummy1等名称可以完全避免这种混淆。此外,_与常见的gettext别名冲突,并且 在交互式解释器中也有特殊含义,所以总体而言我更喜欢使用dummy来避免所有的混淆。

答案 1 :(得分:0)

元组在Python中是不可变的,因此您无法“抛弃”(修改)无关的值。

此外,由于您不关心这些值是什么,因此绝对不需要将它们分配给变量。

我要做的是简单地将元组索引到您感兴趣的索引处,如下所示:

>>> list(map(lambda x: x[0] * 2, [(1,10,100), (2,20,200), (3,30,300)]))
[2, 4, 6]

不需要*args或虚拟变量。

答案 2 :(得分:0)

正如评论中所述,只需使用stared参数 在&#34; _&#34;:

中抛出剩余的参数
lambda x, *_: x*2 

如果您在map语句中使用这些语句,因为Python没有将元组中的每个项目映射到不同的参数,您可以使用itertools.starmap,这样做:

from itertools import starmap
result = map(lambda x, *_: x, [(0,1,2),])

但是sortsorted的关键参数没有相同的内容。

如果你不在元组中间使用参数, 只是编号:

lambda x, _1, _2, _3, w: x*2 + w

如果您从某些linter工具收到有关未使用参数的投诉:linter的目的是建议可读代码。我个人的偏好不是让它妨碍实用性,如果发生这种情况,我只需关闭那行代码,而不需要再考虑。

否则,你真的必须做&#34;美丽&#34;事情 - 如果要取悦你和你的团队,或仅仅为了取悦这一点,请使用良好的感觉。在这种情况下,它是编写一个完整的功能,并假装 消耗未使用的参数。

def my_otherwise_lambda(x, unused_1, unused_2, w):
     """My make linter-happy docstring here"""
     unused_1, unused_2  # Use the unused variables
     return 2 * x + w

如果没有使用linter的问题,目的是让lambda参数可读,那么无论如何都要建立一个完整的函数。 lambda非常接近于在3.0版中被剥夺了语言,以致于可读性。

最后,但并非最不重要的是,如果你的元组中的值的语义 有意义,那么你应该考虑使用一个类来保存那里的值。通过这种方式,您可以将该类的实例传递给lambda函数,并通过各自的名称检查值。

Namedtuple可以很好地运行: 来自集合导入namedtuple

vector = namedtuple("vector", "x y z")

mydata = [(1,10,100), (2,20,200), (3,30,300)]
mydata = [vector(*v) for v in mydata]

sorted_data = sorted(mydata, lambda v: v.x * 2)