Как на самом деле работает эта "общая идиома"?

Глядя на документацию по 2D-слайсам Голанга и не могу понять синтаксис, использованный в последнем примере:

func main() {
    XSize := 5
    YSize := 5

    // Allocate the top-level slice, the same as before.
    picture := make([][]uint8, YSize) // One row per unit of y.

    // Allocate one large slice to hold all the pixels.
    pixels := make([]uint8, XSize*YSize) // Has type []uint8 even though picture is [][]uint8.

    // Loop over the rows, slicing each row from the front of the remaining pixe ls slice.
    for i := range picture {
        picture[i], pixels = pixels[:XSize], pixels[XSize:]
    }
}

Я нашел запрос на изменение, где он был добавлен в документы, и у автора изменений был нормальный / простой для понимания код:

// Loop over the rows, slicing each row.
for i := range picture {
     picture[i] = pixels[i*XSize:(i+1)*XSize]

Тем не менее, есть следующий комментарий:

хорошо. Другая распространенная идиома - избегать математики:

picture[i], pixels = pixels[:XSize], pixels[XSize:]

Мой вопрос заключается в том, как вышеперечисленное позволяет добиться того же, что и метод!"Избежать математики"? Некоторые документы о том, что происходит, было бы здорово.

2 ответа

Решение

Это:

picture[i], pixels = pixels[:XSize], pixels[XSize:]

Это кортеж присваивания. Он присваивает значение picture[i] и значение для pixels, Значения, назначенные по порядку: pixels[:XSize] а также pixels[XSize:],

Назначение происходит в два этапа. Во-первых, операнды выражений индекса и косвенных указателей (включая неявные косвенные указатели в селекторах) слева и выражения справа оцениваются в обычном порядке. Во-вторых, задания выполняются в порядке слева направо.

Здесь происходит то, что когда цикл начинается (i = 0), первый элемент picture (первая строка) назначается со значением среза, являющимся первым XSize элементы в pixelsи pixels срез повторяется, поэтому его первый элемент будет XSize1-й элемент +1.

Итак, в следующей итерации picture[i] будет вторым элементом в picture (2-й ряд) и снова первый XSize элементы из pixels будет установлен к нему в качестве среза. Но так как в предыдущей итерации мы сократили pixelsв каждой итерации свой первый XSize элементы будут последующими строками.

Этот пример назначения кортежа можно переписать так:

for i := range picture {
    picture[i]= pixels[:XSize]
    pixels = pixels[XSize:]
}

Теперь стало проще увидеть, что это первые пиксельные элементы XSize.

И эти пиксели изменяются в каждом цикле и отбрасывают свои первые элементы XSize.

Другие вопросы по тегам