Предлагаемое решение излишне сложно. Бесчисленные переназначения переменных и цикл - рецепт головной боли. Вот упрощенная альтернатива -
def dual (f, g, n):
if n == 0:
return lambda x: x
else:
return lambda x: f(dual(g, f, n - 1)(x))
add1 = lambda x: 1 + x
add2 = lambda x: 2 + x
print(dual(add1,add2,4)(3))
# 9
# (1 + 2 + 1 + 2 + 3)
print(dual(add1,add2,9)(3))
# 16
# (1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 3)
print(dual(add1,add2,0)(3))
# 3
Причина, по которой это работает, заключается в том, что в рекурсивной ветви мы вызываем dual
с замененными аргументами dual(g,f,n-1)
. Так что f
и g
меняются местами каждый раз, когда n
уменьшается до 0
, базовый случай, который возвращает функцию идентификации (без операции).
Немного менее читаемая версия, но работает идентично -
def dual (f, g, n):
return lambda x: \
x if n == 0 else f(dual(g, f, n - 1)(x))