Идиоматический Python для нетривиального понимания списка
Выполнение простого преобразования над итерируемым в Python идиоматически достигается с помощью понимания списка:
y = [f(arg) for arg in args]
где f
это простое утверждение или функционал map
если f
является именованной функцией:
y = map(f, args)
Гвидо одобряет списки map(lambda x:..., args)
и на самом деле перечислить понимание использования map
или же filter
на всех.
Однако мне не ясно, как я должен подходить к проблемам, которые:
- изменить каждый элемент в итерации,
- нетривиальным образом,
- используя дискретную часть логики (может быть функцией),
- это никуда не годится
Какой самый идиоматический способ решения этого типа проблемы? Некоторые вещи, которые я видел и пробовал в проектах Python, над которыми я работал:
Предобъявление и петля
Очевидный способ - предварительно объявить результат и цикл:
def transform(...):
...
y = []
for arg in args:
first_statement
second_statement
...
y.append(statement)
Комментарии:
- (про) легко следовать логике
- (con) логика не ограничена (утечка абстракции)
- (con) логика не явная (откуда вы знаете, что это карта без проверки того, как работают все ветви в цикле?)
- (con) излишне предварительно объявляет переменную бесполезным способом (
y
ДОЛЖЕН быть такой же длины, какargs
)
Вложенная функция
Другой вариант - заключить логику во вложенную функцию, а затем вызвать ее, используя карту или списки:
def transform(...):
...
def anonymous(arg):
first_statement
second_statement
...
return statement
y = map(anonymous, args)
# y = [anonymous(arg) for arg in args]
Комментарии:
- (Pro) Инкапсулирует логику
- (Pro) Может получить доступ к внешней области видимости
- (Pro) Невозможно изменить внешнюю область видимости (явно об отсутствии побочных эффектов)
- (Con) Внутренняя функция переопределяется каждый раз, когда она вызывается
- (Con) Внутренняя функция не имеет реального имени (должна быть анонимной в области видимости карты)
Внешняя функция
Перемещение внутренней функции во внешнюю область решает некоторые из этих проблем, но вводит больше:
def _anonymous(arg):
first_statement
second_statement
...
return statement
def transform(...):
...
y = map(_anonymous, args)
Комментарии:
- (Pro): функция компилируется один раз в разбор
- (Con): функция слишком далека от call-сайта для небольшого кусочка логики (вызывает ненужное переключение контекста для программиста)
- (Con): функция не имеет доступа к внешней области видимости. Любые требования должны быть соблюдены (предотвращение использования
map
) или жеpartial
роскопию
Резюме
Я в конфликте. Как вы решаете проблемы, когда вам нужно сделать нетривиальную одноразовую карту?