Почему такой странный результат от генератора случайных чисел в списке списков?

import random

def initGrid():
  global cell_array
  for x in range(1, mx - 1):
    for y in range(1, my - 1):
      if random.random() < 0.3:
        cell_array[x][y] = 1
      print(cell_array[x][y], end='')
    print()

mx = 21
my = 17
cell_array = [[0] * my] * mx

initGrid()

Почему вот это выдаёт?

000000000010110
000110000110110
010111000110110
110111010110110
110111010111110
110111111111110
110111111111110
110111111111110
111111111111111
111111111111111
111111111111111
111111111111111
111111111111111
111111111111111
111111111111111
111111111111111
111111111111111
111111111111111
111111111111111

Ответы (2 шт):

Автор решения: Stanislav Volodarskiy

cell_array = [[0] * my] * mx - это массив в котором все строки одинаковые.

cell_array = [[0] * my for _ in range(mx)] - это массив в котором строки разные.

Строки на печати разные потому что вы печатаете одну и ту же строку в разные моменты времени. В неё всё время добавляются новые единицы.

Генератор в порядке.

Я бы решал задачу так:

import random


def initGrid(mx, my):
    return [
        [
            int(0 < x < mx - 1 and 0 < y < my - 1 and random.random() < 0.3)
            for x in range(mx)
        ]
        for y in range(my)
    ]


cell_array = initGrid(21, 27)
for row in cell_array:
    print(*row, sep='')
$ python init-grid.py
000000000000000000000
000001000000000101000
001100100111111010000
000001000000000101010
000001010110011000010
010101110100000001100
000000100010101000010
010010011000011101100
000000010101010111010
000001000100010000100
010001000000001001000
010111100010100100000
000000001100001010000
000110000101001010010
001000000000000000100
011111000100101110000
000010001001001000000
001001001100010000100
001010000111010010100
000000000100001101100
000011000010011000000
001011111000000000000
000000000000011000000
010100100010001100110
010000000100100110000
000000001010100001100
000000000000000000000
→ Ссылка
Автор решения: Pak Uula

Попробуйте чуть чуть изменить программу:

import random as random

def initGrid():
  global cell_array
  for x in range(1, mx - 1):
    for y in range(1, my - 1):
      r = random.random()
      # print(f'({r})')
      if r < 0.3:
        cell_array[x][y] = 1
      else:
        cell_array[x][y] = 0
      print(cell_array[x][y], end='')
    print()

mx = 21
my = 17
cell_array = [[0] * my] * mx

initGrid()

И опа:

010000000000000
000111000001001
011000000011000
110100000000010
010000101000000
101100000110111
000000000100000
000010110000110
000000010110101
001101001010001
011001100000000
010000100010000
110000101000010
010000000000000
100110001000010
000001101000000
001010100000001
000001101000000
000100010001010

Проблема в том, что выражение [[0] * my] * mx создаёт список из указателей на один и тот же список. То есть меняя cell_array[x][y] вы меняете y-вый элемент во всех строках разом.

Для проверки напечатайте

print("\n".join(map(str,cell_array)))

Получите идентичные строки.

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

→ Ссылка