#go #variable-assignment #slice #scanline
# #Вперед #присвоение переменной #срез #scanline
Вопрос:
Просматриваю документацию для 2D-фрагментов golang и не могу понять синтаксис, используемый в последнем примере:
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:]
Мой вопрос в том, как вышеупомянутое достигает того же, что и метод!»избегать математики»? Некоторые документы о том, что происходит, были бы замечательными.
Ответ №1:
Это:
picture[i], pixels = pixels[:XSize], pixels[XSize:]
Это назначение кортежа. Он присваивает значение picture[i]
и значение pixels
. Значения, назначенные по порядку, являются pixels[:XSize]
и pixels[XSize:]
.
Назначение выполняется в два этапа. Во-первых, операнды индексных выражений и косвенных указателей (включая неявные косвенные указатели в селекторах) слева и выражения справа вычисляются в обычном порядке. Во-вторых, назначения выполняются в порядке слева направо.
Здесь происходит то, что при запуске цикла ( i = 0
) первому элементу picture
(первой строке) присваивается значение среза, являющееся первыми XSize
элементами pixels
, и pixels
срез повторно используется, поэтому его первым элементом будет XSize
th element 1 .
Итак, на следующей итерации picture[i]
будет 2-й элемент в picture
(2-й строке), и опять же, первые XSize
элементы из pixels
будут установлены для него как срез. Но поскольку на предыдущей итерации мы изменили pixels
, на каждой итерации его первыми XSize
элементами будут последующие строки.
Комментарии:
1. Благоговейный трепет. Полностью имеет смысл.
(picture[i], pixels) = (pixels[:XSize], pixels[XSize:])
. Просто не видел этого таким образом.
Ответ №2:
Этот пример назначения кортежа можно переписать следующим образом:
for i := range picture {
picture[i]= pixels[:XSize]
pixels = pixels[XSize:]
}
Теперь легче увидеть, что изображение — это первые элементы XSize в пикселях.
И эти пиксели изменяются в каждом цикле и отбрасывают свои первые элементы XSize.