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)
因为删除的结果是 None
,or
的第二个参数将是结果。这避免了评估。但它仍然比 for 循环更糟糕。
如对原始问题的评论所述,2 * y.pop(y.index(i))
比 or
结构更具可读性。您将在 y
上循环两次,但性能似乎不是问题。
如果你想写出好的函数表达式(使用lambda
、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'
恐怕不短也不漂亮也不好理解 * 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', [] )
我们只取最后一个状态的第一个元素。
如何在列表推导式或 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)
因为删除的结果是 None
,or
的第二个参数将是结果。这避免了评估。但它仍然比 for 循环更糟糕。
如对原始问题的评论所述,2 * y.pop(y.index(i))
比 or
结构更具可读性。您将在 y
上循环两次,但性能似乎不是问题。
如果你想写出好的函数表达式(使用lambda
、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'
恐怕不短也不漂亮也不好理解 * 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', [] )
我们只取最后一个状态的第一个元素。