例如,下面的代码不是内联的:
with x:
do(stuff)
我可以像这样单行:
with x: do(stuff)
但是我想知道是否有一种方法可以做这样的事情(内联):
a = [(lambda x: with x: do(stuff))(x) for x in someList]
编辑:
详细地说,我有一个对象列表,每个对象都有自己的上下文。这意味着do(stuff)
在使用with x
时的行为会有所不同,并且上面的语句将遍历该列表中的每个对象,输入它们的上下文,运行do(stuff)
,然后继续下一个。
由于我尝试过这样做是行不通的,所以我想知道是否有任何方法可以做到这一点,以及如何做到。
上述代码的扩展版本如下所示(并且可以正常工作):
a = []
for x in someList:
with x: a.append( do(stuff) )
答案 0 :(得分:5)
好吧,既然您可以解决问题,那么more-itertools.with_iter
可能是您最好的选择。
注意:这是一个第三方软件包,因此如果没有,则需要安装它
from more_itertools import with_iter
a = [do(stuff) for _ in with_iter(x)]
#your example lacks what do and x really are/do so this comprehension is inferred
如果您不想使用第三方套餐,那么with_iter
所做的就是:
def with_iter(context_manager):
with context_manager as iterable:
yield from iterable
所以这很容易实现。
答案 1 :(得分:3)
特别是对于lambda表达式,这是不可能的(与lambdas处理的部分原因是您不能在其中分配变量)。一种解决方法是预先构造一个适当的函数,然后让lambda调用该适当的函数:
def _f(x):
with x as y:
return do(stuff)
a = [_f(x) for x in someList]
我无法让with:
在Lambda内工作,不幸的是,您也无法手动执行打开/关闭例程-我怀疑出于同样的原因(您无法在Lambda内分配变量)。
但是,使用lambdas和python 3.8中引入的赋值运算符,则可以执行以下操作:
>>> a = [(lambda x:(f := open(x), f.read(), f.close())[1])(i)
for i in ('hello.txt', 'dunno.txt', 'goodbye.txt')]
>>> print(a)
['Hello', 'I dunno', 'Goodbye']
使用元组作为类似物,将多个语句放入lambda中。简而言之,它按顺序执行以下操作:
file.close()
返回None
,我们不在乎,因为它实际上不会引发错误。这既利用了python 3.8中新添加的Assignment Operator,又利用了从前到后按顺序评估元组的事实。从理论上讲,您可以使用此范例在元组中实现整个功能,尽管该代码会变得非常复杂。这是非Python的。
免责声明:此方法确实需要手动打开和关闭文件(或者,就您而言,我想是手动调用__enter__()
和__exit__()
),并且结果它没有完全封装with
的功能。我不知道您将如何对此进行错误处理。
我使用python 3.8 beta进行了测试,直到at least October 21 2019之前3.8才能正确发布。这在3.8之前的任何当前版本的python中均不起作用。我不知道这是否符合预期的功能或是否有错误,因此如果您出于任何原因选择尝试使用此功能,请小心。