Составные функции в Python - двойная композиция - PullRequest
2 голосов
/ 27 марта 2019

Мне попалась следующая домашняя задача:

enter image description here

Мой код для этой проблемы был помечен как неправильный, и когда я просмотрел предлагаемое решение, я не мог понять, где я ошибся. Я запустил коды обеих функций в компиляторе Python IDLE только для того, чтобы убедиться, что обе функции возвращают один и тот же вывод, как показано ниже:

>>> def dual_function(f,g,n): #Suggested solution
    def helper(x):
        f1,g1 = f,g
        if n%2==0:
            f1,g1=g1,f1
        for i in range(n):
            x=f1(x)
            f1,g1=g1,f1
        return x
    return helper

>>> def dual_function_two(f,g,n): #My solution
    def helper(x):
        if n%2==0:
            for i in range (n):
                if i%2==0:
                    x = g(x)
                else:
                    x = f(x)
        else:
            for i in range(n):
                if i%2==0:
                    x = f(x)
                else:
                    x = g(x)
        return x
    return helper

>>> add1 = lambda x: x+1
>>> add2 = lambda x: x+2
>>> dual_function(add1,add2,4)(3)
9
>>> dual_function_two(add1,add2,4)(3)
9
>>> 

Буду признателен, если кто-то сможет выявить ошибку в моем решении. Спасибо.

1 Ответ

3 голосов
/ 27 марта 2019

Предлагаемое решение излишне сложно. Бесчисленные переназначения переменных и цикл - рецепт головной боли. Вот упрощенная альтернатива -

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))
...