Могу ли я использовать декоратор для перебора вложенного списка?

#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 = [значение]. Но, возможно, моя версия не так уж и неэлегантна.