Элегантный способ сохранить доступ к предыдущему элементу в цикле по элементам списка - PullRequest
2 голосов
/ 07 июня 2019

Сводка:

В проекте Python мне нужно применить функцию к каждому из двух элементов списка списков, имеющих одинаковый внутренний индекс и соседний внешний индекс.Выводы сохраняются в новой матрице.

Код, который я написал, работает, но не элегантен, и pyflakes жалуется на это.

Как мне очистить этот код?

Дополнительная информация:

Код, который я пишу, является частью модуля, который решает головоломку с цифрами.

В какой-то момент я перебираю списоксписков экземпляров классов.
Они представляют ячейки в строках в игровом поле.
И мне нужно применить функцию к каждой из двух соседних по вертикали ячеек
и сохранить ее вывод в новой матрице.

Здесь не имеет значения, какая из ячеек в паре является первой, но пары должны быть в порядке.

Отрывок кода:

def func(cell_matrix):
    out_matrix = []
    for y_pos, line in enumerate(cell_matrix):
        out_line = []
        if y_pos != 0:
            for x_pos, cell in enumerate(line):
                out_line.append(compare_func(prev_line[x_pos], cell)
            out_matrix.append(out_line)
        prev_line = line
    return out_matrix

На что жалуется pyflakes:

Line 7: pyflakes [E]: undefined name 'prev_line'
Line 9: pyflakes [E]: local variable 'prev_line' is assigned to but never used

Ответы [ 4 ]

1 голос
/ 07 июня 2019

Вам необходимо объявить имя переменной перед ее использованием:

def func(cell_matrix):
    out_matrix = []
    prev_line = cell_matrix[0]    # use 1st line as prev_line
    for line in cell_matrix[1:]:  # use 2nd to nth line, no y_pos used
                                  # in the following code so no need to enumerate
        out_line = []
            for x_pos, cell in enumerate(line):
                out_line.append(compare_func(prev_line[x_pos], cell) ) # missing )
            out_matrix.append(out_line)
        prev_line = line
    return out_matrix
1 голос
/ 07 июня 2019

Я бы порекомендовал использовать только индексы, поэтому вы избавляетесь от переменной prev_.

Например,

def func(cell_matrix):                                                           
    out_matrix = []                                                              
    for y_pos in range(len(cell_matrix)):                                        
        out_line = []                                                            
        if y_pos != 0:                                                           
            for x_pos in range(len(cell_matrix[y_pos])):                         
                out_line.append(compare_func(cell_matrix[y_pos-1][x_pos],        
                                             cell_matrix[y_pos][x_pos]))         
            out_matrix.append(out_line)                                          
    return out_matrix                                                            

Но это может быть еще более упрощено при использовании понимания:

def func(cell_matrix):                                                           
    return [[compare_func(                                                       
                 cell_matrix[y_pos-1][x_pos], cell_matrix[y_pos][x_pos])         
             for x_pos in range(len(cell_matrix[y_pos]))]                        
            for y_pos in range(1, len(cell_matrix))]                             

Редактировать: Кстати, ошибки, которые вы получаете, являются сообщениями типа pyflakes, код отлично работает.(Можно утверждать, что Pyflakes не может правильно проанализировать код)

0 голосов
/ 07 июня 2019

Я закончил тем, что переместил итерацию в отдельную функцию, потому что мне легче читать таким образом.

def subsequences(var, r=2):
    """Yield subsequences of var with length r"""
    # subsequences("ABCD") --> AB BC CD
    for index in range(len(var)-r+1):
        yield tuple(var[index+n] for n in range(r))

def func(cell_matrix):
    return [
        [
            compare_func(cell_a, cell_b)
            for cell_a, cell_b in zip(prev_line, line)
        ]
        for prev_line, line in subsequences(cell_matrix)
    ]

Хотя это может быть только личный вкус.

0 голосов
/ 07 июня 2019

Измените свой код на:

def func(cell_matrix):
    out_matrix = []
    prev_line = []
    for y_pos, line in enumerate(cell_matrix):
        out_line = []
        if y_pos != 0:
            for x_pos, cell in enumerate(line):
                out_line.append(compare_func(prev_line[x_pos], cell)
            out_matrix.append(out_line)
        prev_line = line
    return out_matrix

Вам необходимо объявить prev_line вне области цикла for, чтобы он мог использовать ее в каждом цикле.

...