#python #decorator
#python #декоратор
Вопрос:
Мне приходится многократно перебирать 2-мерную сетку (строки и столбцы) для выполнения различных функций в каждой ячейке сетки. Каждый раз, когда я хочу применить другой к ячейкам, я должен закодировать вложенный цикл…
for row in rows:
for col in row:
func(col)
Поэтому, чтобы не повторяться, я начал с этого (старая школа — Python 2.7.x)
#version 1
grid = [[1,2,3,],[4,5,6],[7,8,9]]
def loop(grid,func):
results = []
for row in grid:
for col in row:
results.append(func(col))
return results
def func(x):
return x 1
results = loop(grid,func)
вывод:
[2, 3, 4, 5, 6, 7, 8, 9, 10]
Для меня передача функции в качестве аргумента в другую функцию пахла вариантом использования декоратора. Но я не понял, как заставить это работать — передача аргумента grid в любую функцию-оболочку сбивает меня с толку.
Единственное улучшение, которое я внес в вышесказанное, — это использование map
#version 2
def func(x):
return x 1
def loop(grid,func):
return map(func,[col for row in grid for col in row])
Итак, мой вопрос в том, можно ли это сделать с помощью декоратора и как? (Предупреждение об этикете: какой способ лучше?)
Комментарии:
1. Привет, спасибо за очистку, Джонатан… давно здесь не был и не мог вспомнить, как правильно форматировать.
Ответ №1:
Конечно, вы можете написать декоратор для преобразования функции, которая работает с одним элементом, в функцию, которая работает с сеткой, используя вложенный цикл:
def gridfunc(func):
def wrapper(grid):
results = []
for row in grid:
for col in row:
results.append(func(col))
return results
return wrapper
@gridfunc
def foo(x):
return x 1
grid = [[1,2,3,],[4,5,6],[7,8,9]]
results = foo(grid)
Единственным недостатком этого является то, что исходная функция foo
недоступна (легко), если вы хотите запустить ее для одного значения, а не для их сетки. Если вы хотите иметь возможность использовать обе версии, вы можете использовать gridfoo = gridfunc(foo)
вместо @decorator
синтаксиса.
Комментарии:
1. Ну, это было просто. Каким-то образом во всех рассмотренных мною примерах декоратора я, должно быть, пытался сделать его более сложным, чем необходимо. — Вы поднимаете очень хороший вопрос, указав, действительно ли это хороший вариант использования, если я захочу использовать функцию с одним значением… Я думаю, в этом случае вы могли бы создать grid = [значение]. Но, возможно, моя версия не так уж и неэлегантна.