Python: функция коротких координат неожиданно изменяет значение входящего аргумента - PullRequest
1 голос
/ 22 марта 2012

Цель здесь - взять некоторый список координат, например [[1,2],[3,4],[7,1]], а затем выяснить, насколько большим должен быть холст, если вы хотите напечатать все эти координаты. Возьмите максимальную нижнюю левую координату и минимальную верхнюю правую координату, которые будут плотно прилегать к этим точкам. Например, в приведенном выше списке мы ищем [[1,1],[7,4]], который определяет наименьший прямоугольник, в который поместятся все эти точки.

В середине этой функции я вижу, что входящей "доске" присвоено новое значение.

def print_board(board):
    # import pdb; pdb.set_trace()
    dimensions = None
    for i in board:
        if dimensions == None:
            dimensions = [i, i]
        else:
            dimensions[0][0] = min(dimensions[0][0], i[0])
            #'board' is redefined !!!
            dimensions[0][1] = min(dimensions[0][1], i[1]) 
            #dimensions[1][0] = max(dimensions[1][0], i[0])
            #dimensions[1][1] = max(dimensions[1][1], i[1])
    # (after we get the canvas size
    # we print the canvas with the points on it
    # but we never make it that far without an error)

Поскольку цикл for перемещается через координаты входящего board, он, похоже, устанавливает board[0] в любую координату, на которую он смотрит в данный момент. Так что [[1,2],[3,4],[7,1]] сначала изменится на [[3,4],[3,4],[7,1]], затем на [[7,1],[3,4],[7,1]].

Я бы не ожидал, что board изменится вообще.

(Python 3.2.2)

Ответы [ 2 ]

3 голосов
/ 22 марта 2012

Когда вы делаете

dimensions = [i, i]

, вы устанавливаете оба элемента в dimensions на первую точку на своей доске, а не копируете эту точку.

Затем, когда выdo

        dimensions[0][0] = min(dimensions[0][0], i[0])
        dimensions[0][1] = min(dimensions[0][1], i[1]) 

вы обновляете ту же самую точку - первую точку на вашей доске - до результатов функций min.

Вместо этого попробуйте что-то подобное:

def print_board(board):
    xs, ys = zip(*board) # separate out the x and y coordinates
    min_x, max_x = min(xs), max(xs) # find the mins and maxs
    min_y, max_y = min(ys), max(ys)
    dimensions = [[min_x, min_y], [max_x, max_y]] # make the dimensions array
0 голосов
/ 22 марта 2012

В качестве расширения ответа agfs вы можете использовать numpy для еще более эффективного и краткого кода:

import numpy as np
def print_board(board):
    a = np.array(board)
    return [a.min(axis=0).tolist(), a.max(axis=0).tolist()]

Если ваша доска уже является массивом numpy, и вы позволяете функции возвращать кортеж массивов numpy, она сокращается еще больше:

def print_board(board):
    return board.min(axis=0), board.max(axis=0)
...