Python2列表理解和评估

Python2列表理解和评估,python,lambda,eval,list-comprehension,Python,Lambda,Eval,List Comprehension,如何在列表理解或评估中使用多行语句 我试图转换此代码: def f(x, y, b=''): for i in x: if i in y: y.remove(i) i *= 2 b += i return b 转化为lambda函数,如下所示: j=lambda x,y:''.join(eval('y.remove(i);i*2')if i in y else i for i in x) 在这两个

如何在列表理解或评估中使用多行语句

我试图转换此代码:

def f(x, y, b=''):
    for i in x:
        if i in y:
            y.remove(i)
            i *= 2
        b += i
    return b
转化为lambda函数,如下所示:

j=lambda x,y:''.join(eval('y.remove(i);i*2')if i in y else i for i in x)
在这两个
x
中都有一个字符串,如
“拟声词”
y
是一个列表,如
['o','a','o']


但由于某种原因,它返回一个语法错误。有人能解释一下吗?

我非常喜欢你的功能,但这可以满足你的需要

from itertools import chain
j = lambda x, y: ''.join(filter(None,chain.from_iterable((i * 2,y.remove(i)) if i in y else i for i in x)))

print(j("'onomatopoeia'",['o','a','o']))
'oonoomaatopoeia'

首先,由于循环中的副作用,您可能不应该用lambda重写它。如果你真的想这样做,不要使用评估

我建议:

j = lambda x, y: ''.join((y.remove(i) or 2 * i) if i in y else i for i in x)
因为remove的结果是
None
,所以
的第二个参数将是结果。这避免了评估。但比for循环更糟糕



如在对原始问题的评论中所述,
2*y.pop(y.index(i))
结构更具可读性。您将在
y
上循环两次,但性能似乎不是问题。

如果您想编写好的函数表达式(使用
lambda
s、
map
reduce
filter
等),应该避免副作用

我强烈希望你的代码是一个函数,而不是一个有副作用的lambda

这是一个lambda表达式中的无副作用实现:

>>> from functools import reduce
>>> (lambda x, y: reduce(lambda a, b: \
...     (a[0]+2*b, a[1][:a[1].index(b)]+a[1][a[1].index(b)+1:]) if b in a[1] \
...     else (a[0]+b, a[1]), x, ('',y))[0])('onomatopoeia', ['o','a','o'])
'oonoomaatopoeia'
恐怕它既不短,也不漂亮,也不容易理解,因为人们希望它是一只羔羊<代码>:/(希望有人能提出改进建议)

这只是一个反例,不鼓励在此上下文中使用lambda

在python中,lambdas最大的问题是没有像标准ML中那样的
where
语法来定义同一表达式中的变量别名。所以,对于任何非琐碎的事情,事情都会很快变得丑陋


如果您想了解它的功能,可以使用reduce来运行自动机,其中(每一步)的结果就是计算的“状态”

初始“状态”是
(“”,['o','a','o'])
,reduce函数将根据需要从
“拟声词”开始进行替换

这就是“国家”的演变:


我们只取最后一个状态的第一个元素。

x
和y的值是多少?你到底为什么要这样做?预期的输出是什么
oonoomaatopoeia
?也许他正在寻找一种使用lambdaI实现这一点的漂亮方法。他同意其他人的观点,即你不应该这样做,但如果你这样做,至少不要使用eval。您可以简单地使用
y.pop(y.index(i))+i
2*y.pop(y.index(i))
代替您的eval调用。顺便说一句,我怀疑您对性能感兴趣,但由于您逐个删除列表中的所有元素,因此该算法效率相当低;一个更快的选择是使用
集合。计数器
并减少字母的计数。为什么不简单地
''。加入(2*y.pop(y.index(i)),如果我在y中,否则i代表i在x中)
?@l4mpi,因为我使用的是OP自己的代码,索引的成本也并不比过滤好。如果由我决定,我不会使用这两种方法。我同意这两种方法都不是真正可行的方法,但是
pop
变体在我看来更具可读性。我怀疑速度是一个问题,如果是这样的话,完全取消
remove
调用可能是最好的做法(例如,使用
计数器
并减少字母计数)。@l4mpi,正如我所说,我使用的是OP提供的代码,并使其按规定工作,但没有提供我个人使用的方式。
'.join(2*y.pop(y.index(I)),如果我在y中,否则I代表I在x中)
我也不会使用
( '',     ['o','a','o'] )    'o'
( 'oo',       ['a','o'] )    'n'
( 'oon',      ['a','o'] )    'o'
( 'oonoo',        ['a'] )    'm'
( 'oonoom',       ['a'] )    'a'
( 'oonoomaa',        [] )    't'
( 'oonoomaat',       [] )    'o'
( 'oonoomaato',      [] )    'p'
( 'oonoomaatop',     [] )    'o'
( 'oonoomaatopo',    [] )    'e'
( 'oonoomaatopoe',   [] )    'i'
( 'oonoomaatopoei',  [] )    'a'
( 'oonoomaatopoeia', [] )