<p>即使它不被认为是Pythonic,Python仍然包含<code>map</code>和<code>filter</code>,并且<code>reduce</code>可以从<code>functools</code>导入。使用这些函数,您可以生成与scala中相同的管线,但写入方向相反(从右到左,而不是从左到右):</p>
<pre><code>from functools import reduce
a = reduce(lambda f,s: f'{f} .. {s}',
map(lambda nx: f'Result[{nx[0]}]: {nx[1]}',
enumerate(
filter(lambda n: n%20 == 0,
filter(lambda n: len(str(n)) == 2,
filter(lambda n: n <= 170,
map(lambda n: n*4,
range(1,51))))))))
</code></pre>
<p>现在,这是懒惰的,因为它将在计算下一个值之前让每个值通过整个管道传输。但是,由于所有的值都被最后的<code>reduce</code>调用使用,因此看不到这一点</p>
<p>可以从每个步骤中的每个<code>map</code>或<code>filter</code>对象生成一个列表:</p>
<pre><code>a = reduce(lambda f,s: f'{f} .. {s}',
list(map(lambda nx: f'Result[{nx[0]}]: {nx[1]}',
list(enumerate(
list(filter(lambda n: n%20 == 0,
list(filter(lambda n: len(str(n)) == 2,
list(filter(lambda n: n <= 170,
list(map(lambda n: n*4,
list(range(1,51)))))))))))))))
</code></pre>
<p>这两种表达方式,尤其是第二种,都非常冗长,所以我不知道我是否会推荐它们。我建议使用列表/生成器理解和一些中间变量:</p>
<pre><code>n4 = [n*4 for n in range(1,51)]
fn4 = [n for n in n4 if n <= 170 if len(str(n))==2 if n%20 == 0]
rfn4 = [f'Result[{n}]: {x}' for n, x in enumerate(fn4)]
a = ' .. '.join(rfn4)
</code></pre>
<p>这种方法的另一个好处(至少对您而言)是,使用这种方法,您将保持scala中的操作顺序。它也将,只要我们做列表理解(如图所示)是非惰性的评估。如果我们<em>想要</em>惰性评估,可以改为执行生成器理解:</p>
<pre><code>n4 = (n*4 for n in range(1,51))
fn4 = (n for n in n4 if n <= 170 if len(str(n))==2 if n%20 == 0)
rfn4 = (f'Result[{n}]: {x}' for n, x in enumerate(fn4))
a = ' .. '.join(rfn4)
</code></pre>
<p>因此,唯一的区别是我们使用偏执而不是括号。但是,如前所述,;由于所有数据都已消耗,因此本例中的差异非常小</p>