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

我是一个试图达到以下目标的蟒蛇新手:

我有一份名单:

lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]

我想映射 lst 到另一个列表中,只包含每个子列表中的第二个最小数。所以结果应该是:

[345, 465, 333]

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

map(lambda x: min(x),lst)

我希望我能做到这一点:

map(lambda x: sort(x)[1],lst)

但 sort 不链接。(返回 Nothing)

这样的事情也是不允许的:

map(lambda x: sort(x); x[1],lst) #hence the multiple statement question

有没有一种方法可以做到这一点与地图在巨蟒但 而不用定义命名函数?(例如,在 Ruby 中使用匿名块很容易)

205623 次浏览

使用 排序函数,像这样:

map(lambda x: sorted(x)[1],lst)

或者,如果你想避开 lambda,使用一个生成器而不是列表:

(sorted(col)[1] for col in lst)

在这里我可以给出几个不同的答案,从你的具体问题到更普遍的关注点。因此,从最具体的到最一般的:

你能在一个 lambda 中放入多个语句吗?

答强 > 号码。但其实你不需要用到 lambda。您可以将语句放在 def中。例如:

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


map(second_lowest, lst)

通过对列表进行排序,你能从 lambda 中得到第二低的条目吗?

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

我应该如何从一系列的列表中得到每个列表中倒数第二的项目?

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

>>> import  heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]

所以只要使用:

map(lambda x: heapq.nsmallest(x,2)[1],  list_of_lists)

人们通常认为使用列表内涵更清晰,这样可以完全避免使用 lambda:

[heapq.nsmallest(x,2)[1] for x in list_of_lists]

从这里使用 start () : 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]

我是时间旅行者。如果您通常希望在一个 lambda 中包含多个语句,那么可以将其他 lambda 作为参数传递给该 lambda。

(lambda x, f: list((y[1] for y in f(x))))(lst, lambda x: (sorted(y) for y in x))

实际上不能有多个语句,但是可以通过将 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)]

将表达式放在列表中可能会模拟多个表达式:

例如:

lambda x: [f1(x), f2(x), f3(x), x+1]

这对语句不起作用。

可以使用 min 和 index 在 O (n)时间内完成,而不是使用 sort 或 heapq。

首先创建除了原始列表的最小值之外的所有内容的新列表:

new_list = lst[:lst.index(min(lst))] + lst[lst.index(min(lst))+1:]

然后取新列表的最小值:

second_smallest = min(new_list)

现在所有的一起在一个单一的 lambda:

map(lambda x: min(x[:x.index(min(x))] + x[x.index(min(x))+1:]), lst)

是的,它确实很丑陋,但它应该算法便宜。另外,由于这个帖子中的一些人希望看到列表理解:

[min(x[:x.index(min(x))] + x[x.index(min(x))+1:]) for x in lst]

这正是 Monad中的 bind函数的用途。

使用 bind函数,您可以将多个 lambda 组合成一个 lambda,每个 lambda 代表一个语句。

实际上,在 python 中的 lambda 表达式中可以有多个语句。它并不完全是微不足道的,但在你的例子中,下列作品:

map(lambda x: x.sort() or x[1],lst)

您必须确保每个语句不返回任何内容,或者如果它包装了(。.及虚假)。结果是最后一次计算返回的结果。

例如:

>>> f = (lambda : (print(1) and False) or (print(2) and False) or (print(3) and False))
>>> f()
1
2
3

在 python 中,将多个语句组合成单个语句的一种方法是使用“ 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")

转念一想,用“ or”代替“ and”可能更好,因为许多函数在成功时返回“0”或“无”。然后你可以去掉上面例子中的包装函式:

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


junky("a", "b")

’和’操作将计算表达式,直到它得到第一个零返回值。在此之后,它短路。 一,一,零,一 计算: 1和1和0,并删除1

‘ or’operation 将计算这些表达式,直到它得到第一个非零返回值。

0或0或1或0 计算0或0或1,并删除0

我会给你另一个解决方案,让你的 lambda 调用一个函数。

def multiple_statements(x, y):
print('hi')
print('there')
print(x)
print(y)
return 1


junky = lambda x, y: multiple_statements(x, y)


junky('a', 'b');

让我向你们介绍一个光荣而可怕的黑客:

import types


def _obj():
return lambda: None


def LET(bindings, body, env=None):
'''Introduce local bindings.
ex: LET(('a', 1,
'b', 2),
lambda o: [o.a, o.b])
gives: [1, 2]


Bindings down the chain can depend on
the ones above them through a lambda.
ex: LET(('a', 1,
'b', lambda o: o.a + 1),
lambda o: o.b)
gives: 2
'''
if len(bindings) == 0:
return body(env)


env = env or _obj()
k, v = bindings[:2]
if isinstance(v, types.FunctionType):
v = v(env)


setattr(env, k, v)
return LET(bindings[2:], body, env)

你现在可以这样使用 LET表格:

map(lambda x: LET(('_', x.sort()),
lambda _: x[1]),
lst)

结果是: [345, 465, 333]

实际上有一种方法可以在 lambda 中使用多个语句。 我的解决办法是:

lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]


x = lambda l: exec("l.sort(); return l[1]")


map(x, lst)

是的。您可以这样定义它,然后用以下内容包装您的多个表达式:

计划开始:

Start = lambda * x: x [-1]

Common Lisp 程序:

Prog = lambda * x: x [-1]

不使用 lambda 函数有更好的解决方案。但是如果我们真的想使用 lambda 函数,这里有一个处理多个语句的通用解决方案: Map (lambda x: x [1] if (x.sort ()) else x [1] ,lst)

您并不真正关心语句返回什么。

是的,这是可能的。请尝试下面的代码片段。

x = [('human', 1), ('i', 2), ('am', 1), ('.', 1), ('love', 1), ('python', 3), ('', 1),
('run', 1), ('is', 2), ('robust', 1), ('hello', 1), ('spark', 2), ('to', 1), ('analysis', 2), ('on', 1), ('big', 1), ('data', 1), ('with', 1), ('analysis', 1), ('great', 1)
]


rdd_filter = rdd1_word_cnt_sum.filter(lambda x: 'python' in x or 'human' in x or 'big' in x)
rdd_filter.collect()

来演示 lambda x:[f1(),f2()]效应,它使我们能够在 lambda中执行多个函数。它还演示了单行 if else 条件,如果您真的想缩小代码。

  • 注意,f1()也可以是 lambda 函数(递归 lambda 或 Lambda 中的 lambda) ,并且内部 lambda 可以是 你自己选。
  • 你也可以把 exec (’语句’)例如 lambda x:[exec('a=[1]'),exec('b=2')]

Touch (linux)命令的一个 python 实现,如果不存在空文件,它会创建空文件。

def touch(fpath):
check= os.path.exists(fpath)
(lambda fname1:[open(fname1,"w+",errors="ignore").write(""),print('Touched',fname1)]
if not check else None) (fpath)

将打印[触摸 fpath]其中 fpath是文件路径给出的输入。如果文件已经存在,则不执行任何操作。

(lambda x: [ f(x), f2(x) ] ) (inp) <-我们将‘ inp’作为输入传递给 lambda,在本例中是 fpath

在分析了以上提供的所有解决方案后,我想出了这个组合,它似乎对我最有用:

func = lambda *args, **kwargs: "return value" if [
print("function 1..."),
print("function n"),
["for loop" for x in range(10)]
] else None

很漂亮吧? 请记住,必须有东西在列表中,所以它的真值。 另外一件事是 list 可以被 set 替换,看起来更像 C 风格的代码,但是在这种情况下,你不能把 list 放在里面,因为它们不是 hashabe

我在一行使用 lambas 创建了一个类:

(code := lambda *exps, ret = None: [exp for exp in list(exps) + [ret]][-1])(Car := type("Car", (object,), {"__init__": lambda self, brand, color, electro = False: code(setattr(self, "brand", brand), setattr(self, "color", color), setattr(self, "electro", electro), setattr(self, "running", False)), "start": lambda self: code(code(print("Car was already running, it exploded.\nLMAO"), quit()) if self.running else None, setattr(self, "running", True), print("Vrooom")), "stop": lambda self: code(code(print("Car was off already, it exploded.\nLMAO"), quit()) if not self.running else None, setattr(self, "running", False), print("!Vrooom")), "repaint": lambda self, new_color: code(setattr(self, "color", new_color), print(f"Splash Splash, your car is now {new_color}")), "drive": lambda self: code(print("Vrooom") if self.running else code(print("Car was not started, it exploded.\nLMAO"), quit())), "is_on": lambda self: code(ret = self.running)}), car := Car("lamborghini", "#ff7400"), car.start(), car.drive(), car.is_on(), car.drive(), car.stop(), car.is_on(), car.stop())

更易读的变体:

(
code :=
lambda *exps, ret = None:
[
exp
for exp
in list(exps) + [ret]
][-1]
)(


Car := type(
"Car",
(object,),
{
"__init__": lambda self, brand, color, electro = False: code(
setattr(self, "brand", brand),
setattr(self, "color", color),
setattr(self, "electro", electro),
setattr(self, "running", False)


),
"start": lambda self: code(
code(
print("Car was already running, it exploded.\nLMAO"),
quit()
) if self.running
else None,
setattr(self, "running", True),
print("Vrooom")
),
"stop": lambda self: code(
code(
print("Car was off already, it exploded.\nLMAO"),
quit()
) if not self.running
else None,
setattr(self, "running", False),
print("!Vrooom")
),
"repaint": lambda self, new_color: code(
setattr(self, "color", new_color),
print(f"Splash Splash, your car is now {new_color}")
),
"drive": lambda self: code(
print("Vrooom") if self.running
else code(
print("Car was not started, it exploded.\nLMAO"),
quit()
)
),
"is_on": lambda self: code(
ret = self.running
)
}
),


car := Car("lamborghini", "#ff7400"),
car.start(),
car.drive(),
car.is_on(),
car.drive(),
car.stop(),
car.is_on(),
car.stop()
)

我在这里使用了 lambda 函数,它接受任意数量的参数,并将 ret 参数 default 返回给 Nothing,以便能够在被“ ,”分割的一行中有更多的表达式。

在阅读这个长长的答案列表时,我想出了一个滥用元组的简洁方法:

lambda x: (expr1(x), expr2(x), ..., result(x))[-1]

这将生成一个 lambda,该 lambda 计算所有表达式并返回最后一个表达式的值。这只有在那些表达式有副作用的情况下才有意义,比如 print()sort()

普通赋值(=)不是表达式,所以如果你想在 lambda 中赋值一个变量,你必须使用 :=操作符(在 Python 3.8中添加) ,它也返回赋值:

lambda: (answer := 42, question := compute(answer), question)[-1]

但上述方法只适用于局部变量赋值。为了分配一个元素,你必须使用 d.update({'key': 'value'}),但是即使使用 list也没有类似的选项,必须使用 l.__setitem__(index, value)。与删除相同: 标准容器支持等效于 del x[item]x.pop(index),但也返回被删除的值,但是如果它不可用,则必须直接使用 x.__delitem__(index)

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

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

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

还有,不要在生产代码中使用这些内容!漂亮请!

我可以给你三种方法:

map(lambda x: sorted(x)[1], lst))
map(lambda x: min(x[:x.index(min(x))]+x[x.index(min(x))+1:]), lst)
map(lambda x: min([num for num in x if num != min(x)]), lst)

我知道这是个老问题,但它有更相关的答案。因此,基于水仙313的回答,我有一个小小的修正:

原文: Map (lambda x: sort (x)[1] ,lst))

实际情况: Map (lambda x: (sort (x)[1] ,lst))

我知道这是一个很小的东西,这是相当明显的,但它不会工作,如果没有缺少括号。问题是 lambda 表达式不能接受多个参数,但它们可以接受多个操作的列表/元组。