Python | Правильное использование двумерных массивов / списков

| | | | | | | | | | | | | | |

Метод 1a


# Первый способ создания одномерного массива

N = 5

arr = [ 0 ] * N

print (arr)

Вывод:

[0, 0, 0, 0, 0] 

Метод 1b

# Второй способ создания массива 1 D

N = 5

arr = [ 0 для i in диапазон (N)]

print (arr)

Выход:

[0, 0, 0, 0, 0 ] 

Расширяя вышеизложенное, мы можем определить двумерные массивы следующими способами.
Метод 2a


# Использование описанного выше первого метода для создания
# 2D-массив

строки, столбцы = ( 5 , 5 )

arr = [[ 0 ] * cols] * rows

print (arr)

Выход:

[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0 ], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] 

Метод 2б


# Используя описанный выше второй метод для создания
# двумерного массива

строк, cols = ( 5 , 5 )

arr = [[ 0 for i in range (cols)] for j in range (rows)]

print (arr)

Вывод:

[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0 , 0, 0], [0, 0, 0, 0, 0]] 

Кажется, что оба метода дают тот же результат, что и сейчас. Давайте заменим один из элементов в массиве метода 2a и метода 2b.


# Программа на Python 3, чтобы продемонстрировать, как она работает
# метод 1 и метод 2.

rows , cols = ( 5 , 5 )


# метод 2a

arr = [[ 0 ] * cols] * rows


# изменить первый element
# первая строка в 1 и печать массива

arr [ 0 ] [ 0 ] = 1

для строка в arr:

print (строка)

# выводит следующее
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]
# [1, 0, 0, 0, 0]


# метод 2b

arr = [[ 0 for i in range (cols)] for j in range (rows)]


# вернуться к этому новому массиву позволяет изменить
# первый элемент первой строки
# в 1 и распечатать массив

arr [ 0 ] [ 0 ] = 1

for row in arr:

print (строка)


# выводит следующее, как и ожидалось
# [1, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]
# [0, 0, 0, 0, 0]

Выход:

[1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1 , 0, 0 , 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [0, 0, 0, 0] , 0] [ 0, 0, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0] 

Мы ожидаем только первый элемент первая строка изменится на 1, но первый элемент каждой строки изменится на 1 в методе 2a. Такой тип функционирования связан с тем, что Python использует неглубокие списки, которые мы попытаемся понять.

В методе 1a Python не создает 5 целочисленных объектов, а создает только один целочисленный объект, и все индексы массива arr указывают на тот же объект int, что и показано.


Если мы назначим 0-й индекс другому целому числу, скажем, 1, то будет создан новый целочисленный объект со значением 1, а затем 0-й индекс теперь указывает на этот новый целочисленный объект, как показано ниже

Аналогично, когда мы создаем двумерный массив типа "arr = [[0] * cols] * row " , мы на самом деле, мы расширяем приведенную выше аналогию.
1. Создается только один целочисленный объект.
2. Создается один список 1d, и все его индексы указывают на один и тот же объект int в точке 1.
3. Теперь обр [0], обр [1], обр [2]‚Ķ. arr [n-1] все указывают на один и тот же объект списка выше на шаге 2.

Вышеуказанная настройка может быть визуализирована на изображении ниже.

Теперь давайте изменим первый элемент в первой строке" arr "как
arr [0] [0] = 1

= & GT; arr [0] указывает на тот же объект списка, который мы создали выше (помните, что arr [1], arr [2]… arr [n-1] также указывают на тот же объект списка)
= & gt ; Присвоение arr[0][0] создаст новый объект int со значением 1, и теперь arr[0][0] будет указывать на этот новый объект int. (И так будет arr[1][0], arr[2][0]‚Ķ arr[n-1][0])

Это хорошо видно на изображении ниже .


Поэтому, когда 2D-массивы создаются таким образом, изменение значения в определенной строке повлияют на все строки, поскольку существует только один целочисленный объект и только один объект списка, на который ссылаются все строки в массиве.

Как и следовало ожидать, отследите ошибки, вызванные таким использованием неглубоких списков. сложный. Следовательно, лучший способ объявить двухмерный массив – это


rows, cols = ( 5 , 5 )

arr = [[ 0 for i in range (cols)] for j in range (rows )]

Выход:

 

Этот метод создает 5 отдельных объектов списка, в отличие от метода 2а. Один из способов проверить это — используйте оператор "is", который проверяет, ссылаются ли два операнда на один и тот же объект.


строки, столбцы = ( 5 , 5 )

# метод 2b

arr = [[ 0 для i in range ( cols)] for j in диапазон (строки)]


# проверьте, ссылаются ли arr [0] и arr [1] на
# один и тот же объект

print (arr [ 0 ] is arr [ 1 ] ) # печатает False


# метод 2a

arr = [[ 0 ] * cols] * строки


# проверьте, ссылаются ли arr [0] и arr [1] на
# этот Сэм e object
# выводит True, поскольку существует только один
# список объектов, которые необходимо создать.

print (arr [ 0 ] is arr [ 1 ])

Выход:

False True