是否有可能在python lambda表达式中有多个语句?

ott*_*akt 96 python

我是一个蟒蛇新手试图实现以下目标:

我有一份清单清单:

lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]
Run Code Online (Sandbox Code Playgroud)

我想将map lst放入另一个列表中,该列表仅包含每个子列表中的第二个最小数字.所以结果应该是:

[345, 465, 333]
Run Code Online (Sandbox Code Playgroud)

例如,如果我只对最小数字感兴趣,我可以这样做:

map(lambda x: min(x),lst)
Run Code Online (Sandbox Code Playgroud)

我希望我能做到这一点:

map(lambda x: sort(x)[1],lst)
Run Code Online (Sandbox Code Playgroud)

但排序不会链.(返回无)

也不允许这样的事情:

map(lambda x: sort(x); x[1],lst) #hence the multiple statement question
Run Code Online (Sandbox Code Playgroud)

有没有办法在python中使用map但不定义命名函数?(例如,在ruby中使用匿名块很容易)

Bri*_*ian 120

我可以在这里给出几个不同的答案,从您的具体问题到更一般的问题.所以从最具体到最一般:

问:你能在lambda中放多个语句吗?

:不.但你实际上并不需要使用lambda.您可以将语句放入其中def.即:

def second_lowest(l):
    l.sort()
    return l[1]

map(second_lowest, lst)
Run Code Online (Sandbox Code Playgroud)

问:你可以通过对列表进行排序来获得lambda中第二低的项目吗?

答:是的.正如alex的回答一样,sorted()是一个排序版本,它创建一个新列表,而不是就地排序,并且可以链接.请注意,这可能是你应该使用的 - 你的地图在原始列表上有副作用是不好的做法.

问:如何从列表序列中的每个列表中获取第二低的项目.

A. sorted(l)[1]实际上并不是最好的方法.它具有O(N log(N))复杂度,而存在O(n)解.这可以在heapq模块中找到.

>>> import  heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]
Run Code Online (Sandbox Code Playgroud)

所以只需使用:

map(lambda x: heapq.nsmallest(x,2)[1],  list_of_lists)
Run Code Online (Sandbox Code Playgroud)

使用列表理解通常也更清楚,这完全避免了lambda:

[heapq.nsmallest(x,2)[1] for x in list_of_lists]
Run Code Online (Sandbox Code Playgroud)

  • 文档(http://docs.python.org/2/library/heapq.html#heapq.nsmallest)确实警告说使用heapq.nsmallest()可能效率低于仅使用sorted(),因此只有测量可以告诉您哪种解决方案最快.但是,heapq.nsmallest()的复杂度为O(k*log(n)+ n)我认为,n是列表的长度,k是你想要提取的最小项目的数量.O(n)将列表堆积并且k乘以O(log(n))以弹出k个项目.这比O(n*log(n))更好,特别是对于小k. (7认同)
  • 从技术上讲,你也不需要lambda用于单行,但它肯定更方便.希望稍后会增加更好的lambda支持. (5认同)
  • 我不认为你在heapq模块中找到的O(n)解决方案是正确的.你所做的就是对列表进行堆排序,即O(n log n),然后找到最小的元素. (3认同)
  • @Vortexfive,对于常数k(如此处为“第二低”),O(k * log(n)+ n)简化为O(n)。 (2认同)
  • @avpx:这不是堆排序。我们只维护所见的 2 个最小项的 2 元素堆,而不是像堆排序那样堆化整个列表并弹出所有元素。 (2认同)

jmk*_*mkg 73

将语句放在列表中可以模拟多个语句:

例如:

lambda x: [f1(x), f2(x), f3(x), x+1]
Run Code Online (Sandbox Code Playgroud)

  • 只是为了澄清,函数调用不被认为是Python中的语句,它们是表达式.所以这个列表只是一个表达式列表,可能都是"无". (8认同)
  • 更好的是: lambda x: [f1(x), f2(x)][-1],它将返回最后一个表达式的计算结果,正如预期的那样。 (5认同)
  • 谢谢!这对我有所帮助.也许对某些人来说,展示它的工作原理很有帮助:http://pastebin.com/JNquX1Kh (2认同)

2rs*_*2ts 19

时间旅行者在这里 如果您通常希望在lambda中包含多个语句,则可以将其他lambda作为参数传递给该lambda.

(lambda x, f: list((y[1] for y in f(x))))(lst, lambda x: (sorted(y) for y in x))
Run Code Online (Sandbox Code Playgroud)

实际上你不能有多个语句,但你可以通过将lambdas传递给lambdas来模拟它.

编辑:旅行者返回的时间!您还可以滥用布尔表达式的行为(记住短路规则和真实性)到链操作.使用三元运算符可为您提供更强大的功能.同样,你不能有多个语句,但你当然可以有很多函数调用.这个例子用一堆数据做了一些任意的垃圾,但是,它表明你可以做一些有趣的事情.print语句是返回函数的示例None(.sort()方法也是如此),但它们也有助于显示lambda正在执行的操作.

>>> (lambda x: print(x) or x+1)(10)
10
11
>>> f = (lambda x: x[::2] if print(x) or x.sort() else print(enumerate(x[::-1]) if print(x) else filter(lambda (i, y): print((i, y)) or (i % 3 and y % 2), enumerate(x[::-1]))))
>>> from random import shuffle
>>> l = list(range(100))
>>> shuffle(l)
>>> f(l)
[84, 58, 7, 99, 17, 14, 60, 35, 12, 56, 26, 48, 55, 40, 28, 52, 31, 39, 43, 96, 64, 63, 54, 37, 79, 25, 46, 72, 10, 59, 24, 68, 23, 13, 34, 41, 94, 29, 62, 2, 50, 32, 11, 97, 98, 3, 70, 93, 1, 36, 87, 47, 20, 73, 45, 0, 65, 57, 6, 76, 16, 85, 95, 61, 4, 77, 21, 81, 82, 30, 53, 51, 42, 67, 74, 8, 15, 83, 5, 9, 78, 66, 44, 27, 19, 91, 90, 18, 49, 86, 22, 75, 71, 88, 92, 33, 89, 69, 80, 38]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
(0, 99)
(1, 98)
(2, 97)
(3, 96)
(4, 95)
(5, 94)
(6, 93)
(7, 92)
(8, 91)
(9, 90)
(10, 89)
(11, 88)
(12, 87)
(13, 86)
(14, 85)
(15, 84)
(16, 83)
(17, 82)
(18, 81)
(19, 80)
(20, 79)
(21, 78)
(22, 77)
(23, 76)
(24, 75)
(25, 74)
(26, 73)
(27, 72)
(28, 71)
(29, 70)
(30, 69)
(31, 68)
(32, 67)
(33, 66)
(34, 65)
(35, 64)
(36, 63)
(37, 62)
(38, 61)
(39, 60)
(40, 59)
(41, 58)
(42, 57)
(43, 56)
(44, 55)
(45, 54)
(46, 53)
(47, 52)
(48, 51)
(49, 50)
(50, 49)
(51, 48)
(52, 47)
(53, 46)
(54, 45)
(55, 44)
(56, 43)
(57, 42)
(58, 41)
(59, 40)
(60, 39)
(61, 38)
(62, 37)
(63, 36)
(64, 35)
(65, 34)
(66, 33)
(67, 32)
(68, 31)
(69, 30)
(70, 29)
(71, 28)
(72, 27)
(73, 26)
(74, 25)
(75, 24)
(76, 23)
(77, 22)
(78, 21)
(79, 20)
(80, 19)
(81, 18)
(82, 17)
(83, 16)
(84, 15)
(85, 14)
(86, 13)
(87, 12)
(88, 11)
(89, 10)
(90, 9)
(91, 8)
(92, 7)
(93, 6)
(94, 5)
(95, 4)
(96, 3)
(97, 2)
(98, 1)
(99, 0)
[(2, 97), (4, 95), (8, 91), (10, 89), (14, 85), (16, 83), (20, 79), (22, 77), (26, 73), (28, 71), (32, 67), (34, 65), (38, 61), (40, 59), (44, 55), (46, 53), (50, 49), (52, 47), (56, 43), (58, 41), (62, 37), (64, 35), (68, 31), (70, 29), (74, 25), (76, 23), (80, 19), (82, 17), (86, 13), (88, 11), (92, 7), (94, 5), (98, 1)]
Run Code Online (Sandbox Code Playgroud)

  • 从一个时间旅行者到另一个旅行者.你可能会发现这很有趣.我使用了一些技巧,包括你的(在某种意义上),创建'多语句'匿名函数:https://github.com/yawaramin/lambdak (2认同)

Evg*_*nZh 9

在阅读这一长串答案时,我想出了一种滥用元组的巧妙方法:

lambda x: (expr1(x), expr2(x), ..., result(x))[-1]
Run Code Online (Sandbox Code Playgroud)

这将生成一个 lambda,它计算所有表达式并返回最后一个表达式的值。仅当这些表达式具有副作用(例如print()或 )时,这才有意义sort()

普通赋值 ( =) 不是表达式,因此如果要在 lambda 中分配变量,则必须使用:=也返回分配值的运算符(在 Python 3.8 中添加):

lambda: (answer := 42, question := compute(answer), question)[-1]
Run Code Online (Sandbox Code Playgroud)

但以上仅适用于局部变量赋值。要分配例如 dict 元素,您必须使用d.update({'key': 'value'}),但即使使用 a 也list没有类似的选项,l.__setitem__(index, value)必须使用。与删除相同:标准容器支持x.pop(index)相当于del x[item]但也返回删除的值,但如果不可用则必须x.__delitem__(index)直接使用。

要影响全局变量,您必须修改返回的字典globals()

lambda: (g := globals(), g.__setitem__('answer', 42), g.__delitem__('question'), None)[-1]
Run Code Online (Sandbox Code Playgroud)

可以使用列表、字典甚至集合代替元组将表达式分组为一个,但元组速度更快(主要是因为不可变)并且似乎没有任何缺点。

另外,请勿在生产代码中使用任何此类内容!漂亮请!


ale*_*asi 7

使用排序函数,如下所示:

map(lambda x: sorted(x)[1],lst)
Run Code Online (Sandbox Code Playgroud)


Bil*_*ore 7

在 python 中将多个语句组合成单个语句的一种 Hacky 方法是使用“and”关键字作为短路运算符。然后你可以直接使用这个单一的语句作为 lambda 表达式的一部分。

这类似于在 bash 等 shell 语言中使用“&&”作为短路运算符。

另请注意:您始终可以通过包装函数来修复函数语句以返回真值。

例子:

def p2(*args):
    print(*args)
    return 1 # a true value

junky = lambda x, y: p2('hi') and p2('there') and p2(x) and p2(y)

junky("a", "b")
Run Code Online (Sandbox Code Playgroud)

再想一想,使用 'or' 而不是 'and' 可能更好,因为许多函数在成功时返回 '0' 或 None 。然后你可以去掉上面例子中的包装函数:

junky = lambda x, y: print('hi') or print('there') or print(x) or print(y)

junky("a", "b")
Run Code Online (Sandbox Code Playgroud)

'and' 操作将计算表达式,直到它得到第一个零返回值。之后它短路。1 and 1 and 0 and 1 求值: 1 and 1 and 0,并丢弃 1

'or' 操作将对表达式求值,直到得到第一个非零返回值。之后它短路。

0 或 0 或 1 或 0 计算 0 或 0 或 1,并丢弃 0


Jan*_*sen 6

从这里使用 begin():http : //www.reddit.com/r/Python/comments/hms4z/ask_pyreddit_if_you_were_making_your_own/c1wycci

Python 3.2 (r32:88445, Mar 25 2011, 19:28:28) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]
>>> begin = lambda *args: args[-1]
>>> list(map(lambda x: begin(x.sort(), x[1]), lst))
[345, 465, 333]
Run Code Online (Sandbox Code Playgroud)


小智 5

实际上,您可以在python中的lambda表达式中包含多个语句。这并不简单,但在您的示例中,以下工作原理:

map(lambda x: x.sort() or x[1],lst)
Run Code Online (Sandbox Code Playgroud)

您必须确保每个语句不返回任何内容,或者是否将其包装在(..和False)中。结果是最后一次评估返回的结果。

例:

>>> f = (lambda : (print(1) and False) or (print(2) and False) or (print(3) and False))
>>> f()
1
2
3
Run Code Online (Sandbox Code Playgroud)