import numpy as np # Line 01
y = np.zeros((3,3)) # Line 02
y = y.astype(np.int16) # Line 03
y[1,1] = 1 # Line 04
x = np.ones((3,3)) # Line 05
t = (1-y).astype(np.int16) # Line 06
print(t) # Line 07
print(x[t]) # Line 08
x[(1-y).astype(np.int16)] = 0 # Line 09
print(x) # Line 10
Строка 02:
Создает двумерный 3 x 3-мерный массив нулей.y
- это имя, которое указывает на этот ndarray.
Строка 03:
Устанавливает тип данных каждого элемента y
, чтобы16-разрядное целое число.
Строка 04:
Устанавливает элемент y
на пересечении среднего ряда и среднего столбца на 1
.
Строка 05:
Создает двумерный массив из 3 x 3 единиц.x
- это имя, которое указывает на этот ndarray.
Строка 06:
Вычитание (1-t
) приводит к нескольким скалярным вычитаниям (1- elem
), где elem
- каждый элемент t
.Результатом будет другой ndarray, имеющий ту же форму, что и t
, и имеющий результат вычитания (1- elem
), в качестве его значений.То есть значения ndarray (1-t)
будут:
[[1-t[0,0], 1-t[0,1], 1-t[0,2]],
[1-t[1,0], 1-t[1,1], 1-t[1,2]],
[1-t[2,0], 1-t[2,1], 1-t[2,2]]]
, поскольку t
полон нулей, а одиночный 1
на пересечении среднего ряда и среднего столбца, (1-t)
будет двумерным ndarray, полным единиц, с одинокой 0
на пересечении среднего ряда и среднего столбца.
Строка 07:
Печать t
Строка 08:
Здесь все немного сложнее.То, что здесь происходит, называется «Комбинированное расширенное и базовое индексирование» (https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html#combining-advanced-and-basic-indexing).. Давайте рассмотрим подробности, шаг за шагом. Во-первых, обратите внимание, что x
, это двумерный ndarray, принимая другое целое числоndarray t
в качестве индекса. Поскольку для x
необходимо указать два индекса, t
будет принят за первый из этих двух индексов, а второй индекс будет неявно принят за :
.x[t]
сначала интерпретируется как x[t,:]
. Наличие этих двух индексов, где один индекс представляет собой массив целых чисел t
, а другой индекс представляет собой срез :
, приводит к ситуации, которая называется «комбинированная».Расширенное и базовое индексирование ".
Теперь, что именно происходит в этом" комбинированном "сценарии? Здесь говорится: во-первых, форма результата будет получать вклады из первого индекса t
, а также извторой индекс :
. Теперь t
имеет форму (3,3)
, и, следовательно, вклад t
в форму результата x[t,:]
состоит в том, чтобы предоставить самый крайний (самый левый)размеры формы результата.Следовательно, форма результата будет начинаться с (3,3,)
.Теперь вклад :
в форму x[t,:]
основан на ответе на вопрос: к какому измерению x
применяется :
?Ответ - второе измерение (поскольку :
является вторым индексом в x[t,:]
).Следовательно, вклад :
в результирующую форму x[t,:]
равен 3
(поскольку 3
- это длина второго измерения x
).Напомним, что мы пришли к выводу, что результирующая форма x[t]
будет такой же, как x[t,:]
, что в свою очередь будет (3,3,3)
.Это означает, что x[t]
будет трехмерным массивом, хотя x
сам по себе является только двумерным массивом.
Обратите внимание, что в форме (3,3,3)
результата первые два 3
s были добавлены расширенным индексом t
, а последний 3
был внесен неявным базовым индексом :
.Эти два индекса t
и :
также используют различные способы для получения своих соответствующих вкладов.Вклад 3,3
, полученный от индекса t
, является просто формой самого t
.Его не волнует положение t
среди индексов в выражении x[t,:]
(не имеет значения, происходит ли t
до того, как :
или :
появится до t
).Вклад 3
, полученный из индекса :
, представляет собой длину второго измерения x
, и мы рассматриваем второе измерение x
, потому что :
это второй индекс в выражении x[t,:]
.Если бы x
имел форму (3,5)
вместо (3,3)
, тогда форма x[t,:]
была бы (3,3,5)
вместо (3,3,3)
.
Теперь, когда мы вывели форму результата x[t]
как (3,3,3)
, давайте перейдем к пониманию того, как сами значения будут определены,в результате.Значения в результате, очевидно, являются значениями в позициях [0,0,0], [0,0,1], [0,1,2], [0,1,0], [0,1,1], [0,1,2], [0,2,0], [0,2,1], [0,2,2] и так далее.Давайте пройдемся по одному из примеров этих позиций, и вы, надеюсь, получите дрейф.Для нашего примера, давайте посмотрим на позицию [0,1,2] в результате.Чтобы получить значение для этой позиции, мы сначала индексируем в массив t
, используя 0 и 1. То есть мы находим t[0,1]
, что будет 1
(см. Вывод print(t)
).Это 1
, которое было получено в t[0,1]
, должно быть принято за наш первый индекс в x
.Второй индекс в x
будет 2
(помните, что мы обсуждаем позицию [0,1,2]
в результате и пытаемся определить значение в этой позиции).Теперь, учитывая эти первый и второй индексы в x
, мы получаем из x
значение, которое нужно заполнить в позиции [0,1,2]
из x[t]
.
Теперь, x
просто полон единиц,Таким образом, x[t]
будет состоять только из них, хотя форма x[t]
равна (3,3,3)
.Чтобы действительно проверить ваше понимание того, что я уже сказал, вам нужно заполнить x
различными значениями: поэтому временно закомментируйте строку 05 и поставьте на ее место следующую строку:
x = np.arange(9).reshape((3,3)) # New version of Line 05
Теперь вы обнаружите, что print(x[t])
в строке 08 дает вам:
[[[3 4 5]
[3 4 5]
[3 4 5]]
[[3 4 5]
[0 1 2]
[3 4 5]]
[[3 4 5]
[3 4 5]
[3 4 5]]]
Против этого вывода проверьте ваше понимание того, что я описал выше, о том, как получатся значения в результатеопределяется.(То есть, если вы поняли приведенное выше объяснение x[t]
, вы сможете вручную пересоздать тот же вывод, что и выше, для print (x[t])
.
Строка 09:
Учитывая определение t
в строке 06, строка 09 эквивалентна x[t]
, что, как мы видели выше, эквивалентно x[t, :] = 0
.
.Эффект присваивания x[t, :] = 0
такой же, как эффект x[0:2, :] = 0
.
Почему это так? Просто потому, что в x[t, :]
:
- Сгенерированы значения индексаиндексом
t
являются 0
с и 1
с (поскольку t
является целочисленным индексным массивом, состоящим только из 0
с и 1
с) - Значения индекса, сгенерированныеиндексами
:
являются 0
, 1
и 2
. - Мы имеем в виду только те позиции в пределах
x
, которые соответствуют комбинациям этих значений индекса. То есть x[t, :]
относится только к тем позициям x[i,j]
, где i
принимает значения 0
или 1
, а j
принимает значения 0
, 1
или 2
.x[t, :]
относится только к позициям x[0,0]
, x[0,1]
, x[0,2]
, x[1,0]
, x[1,1]
, x[1,2]
, внутри массива x
. - Итак, оператор присваивания
x[t, :] = 0
присваивает значение 0 в этих позициях в x
.По сути, мы присваиваем значение 0
во все три столбца в первых двух строках x
, и мы оставляем третий ряд x
без изменений.
Строка10:
Печатает значение x
после указанного выше назначения.