Python 2 列表理解和评估

Python 2 list comprehension and eval

如何在列表推导式或 eval 中使用多行语句?

我试图打开这段代码:

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是一个字符串,例如'onomatopoeia'y是一个列表,例如['o','a','o']

但由于某种原因,它 returns 是一个语法错误。谁能解释一下?

我非常喜欢你的功能,但这会做你想要的。

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 重写它。如果您确实想要,请不要使用 eval。

我建议:

j = lambda x, y: ''.join((y.remove(i) or 2 * i) if i in y else i for i in x)

因为删除的结果是 Noneor 的第二个参数将是结果。这避免了评估。但它仍然比 for 循环更糟糕。


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

如果你想写出好的函数表达式(使用lambdamapreducefilter等),你应该避免副作用。

我强烈希望您的代码是函数而不是有副作用的 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'

恐怕不也不漂亮也不好理解 * as人们会希望它用于 lambda。 :/(希望有人能提出改进建议)

只是一个反例,以阻止在这种情况下使用 lambda。

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


如果您有兴趣了解它的作用,我们的想法是使用 reduce to 运行 一个自动机,其中(每一步的)结果是计算的 "state"。

最初的"state"是('', ['o','a','o']),reduce函数会根据需要进行替换,从'onomatopoeia'开始。

这是"state"的进化:

( '',     ['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', [] )

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