<p>重复组合二进制函数的结果通常被称为“折叠”或“减少”,它在Python中通过<code>functools.reduce</code>(或者在Python 2中仅<code>reduce</code>)实现。有两种可能的折叠方向:左折叠,给定<code>f</code>和<code>[a, b, c, d, e]</code>将返回<code>f(f(f(f(a, b), c), d), e)</code>,右折叠,将产生<code>f(a, f(b, f(c, f(d, e))))</code>。默认情况下,<code>functools.reduce</code>实现左折叠,但可以通过将参数交换到reduced函数并反转要缩减的列表来将其转换为右折叠</p>
<p>为了解决您的问题,我们不需要颠倒列表。我们只需要按照正确的顺序生成它。事实上,我们并不真正需要一个列表,因为<code>reduce</code>在迭代器中可以很好地工作。例如,这个简单的迭代器:</p>
<pre class="lang-py prettyprint-override"><code>def oneAatK(A, B, k, n):
"""Returns a generator which produces n values, all of them
B except for the one at index -(k+1)
"""
return (A if i + k == n - 1 else B for i in range(n))
# Using this function for f makes the results more visible.
>>> f = lambda a,b: str(a)+str(b)
>>> [* oneAatK('a', 'b', 0, 6) ]
['b', 'b', 'b', 'b', 'b', 'a']
>>> [* oneAatK('a', 'b', 2, 6) ]
['b', 'b', 'b', 'a', 'b', 'b']
def rfoldrev(f, riter):
"""Right folds f on the reverse of the sequence produced by riter"""
return reduce(lambda acc,val:f(val, acc), riter)
>>> rfoldrev(f, oneAatK('a', 'b', 0, 6))
'abbbbb'
>>> rfoldrev(f, oneAatK('a', 'b', 2, 6))
'bbabbb'
</code></pre>
<p>这样,我们可以生成您想要求和的各个术语:</p>
<pre class="lang-py prettyprint-override"><code># This import is only needed if using Python 3
from functools import reduce
def gen(f, A, B, n):
return (rfoldrev(f, oneAatK(A, B, k, n))
for k in range(n))
>>> [* gen(f, 'a', 'b', 6) ]
['abbbbb', 'babbbb', 'bbabbb', 'bbbabb', 'bbbbab', 'bbbbba']
</code></pre>
<p>因为这些是字符串,所以不能用<code>sum</code>求和,如果<code>f</code>返回一个数字,就可以这样做。但您可以使用<code>reduce</code>将它们与不同的二进制函数组合:</p>
<pre class="lang-py prettyprint-override"><code>>>> reduce(lambda acc,v:f"{acc}+{v}", gen(f, 'a', 'b', 6))
'abbbbb+babbbb+bbabbb+bbbabb+bbbbab+bbbbba'
</code></pre>