#python #lambda #functional-programming #higher-order-functions
#python #лямбда #функциональное программирование #функции более высокого порядка
Вопрос:
Я столкнулся со следующей проблемой домашнего задания:
Мой код для этой проблемы был помечен неправильно, и когда я просмотрел предложенное решение, я не мог понять, где я ошибся. Я запустил коды обеих функций в Python IDLE compiler только для того, чтобы увидеть, что обе функции возвращают один и тот же результат, как показано ниже:
>>> 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. Знаете ли вы тестовые примеры, используемые для оценки вашей проблемы? Я не могу найти ни одного случая, когда эти две функции различались.
2. Это не очень хорошие тестовые функции, поскольку сложение является коммутативным — если вы вызовете их в неправильном порядке, вы не заметите разницы. Но я попытался смешать сложение и умножение, и я также не смог найти разницы.
3. Вероятно, это намного медленнее, чем предлагаемое решение из-за постоянных операций по модулю. Замена будет намного быстрее.
4. @Sebastian К сожалению, у меня нет тестовых примеров : (
5. @Barmar Спасибо, что сообщили мне об использовании коммутативных операторов в таких функциях, буду помнить о них при работе над подобными проблемами в будущем.
Ответ №1:
Предлагаемое решение излишне сложно. Бесчисленные переназначения переменных и цикл — это рецепт головной боли. Вот упрощенная альтернатива —
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))
Комментарии:
1. Отлично, никогда не знал, что я могу быть таким простым. Спасибо за объяснение! 🙂