В Python считается лучшим стилем:
- явно определять полезные функции в терминах более общих, возможно внутренних функций, функций; или,
- использовать приложение частичной функции для явного описания функции currying?
Я объясню свой вопрос с помощью надуманного примера.
Предположим, что вы записываете функцию _sort_by_scoring, которая принимает два аргумента: функцию подсчета очков и список элементов. Он возвращает копию исходного списка, отсортированную по баллам, на основе каждой позиции позиции в исходном списке. Также предлагаются две примерные функции подсчета.
def _sort_by_score(scoring, items_list):
unsorted_scored_list = [(scoring(len(items_list), item_position), item) for item_position, item in enumerate(items_list)]
sorted_list = [item for score, item in sorted(unsorted_scored_list)]
return sorted_list
def _identity_scoring(items_list_size, item_position):
return item_position
def _reversed_scoring(items_list_size, item_position):
return items_list_size - item_position
Функция _sort_by_score никогда не вызывается напрямую; вместо этого он вызывается другими функциями одного аргумента, которые передают функцию подсчета очков и их одиночный аргумент (список элементов) в _sort_by_scoring и возвращают результат.
# Explicit function definition style
def identity_ordering(items_list):
return _sort_by_score(_identity_scoring, items_list)
def reversed_ordering(items_list):
return _sort_by_score(_reversed_scoring, items_list)
Очевидно, что это намерение лучше выражено в терминах каррирования функции.
# Curried function definition style
import functools
identity_ordering = functools.partial(_sort_by_score, _identity_scoring)
reversed_ordering = functools.partial(_sort_by_score, _reversed_scoring)
Использование (в любом случае):
>>> foo = [1, 2, 3, 4, 5]
>>> identity_ordering(foo)
[1, 2, 3, 4, 5]
>>> reversed_ordering(foo)
[5, 4, 3, 2, 1]
Явные преимущества явного стиля определения функции:
- полезные функции могут быть определены до того, как будут созданы более общие функции, не повышая значение NameErrors;
- вспомогательные функции (например, функции подсчета очков) могут быть определены внутри тела определения функции;
- возможно проще отладить;
- код выглядит красивым в силу "явного лучше, чем неявный".
Очевидные преимущества стиля определения картой:
- выражает намерение функционального программирования идиоматически;
- код выглядит красивым в силу лаконичности.
Для определения "полезных" функций, какой из двух стилей является предпочтительным? Существуют ли другие стили, более идиоматические/Pythonic/etc.?