2D список в Python повторяет случайные числа - PullRequest
1 голос
/ 20 марта 2019

Извиняюсь, поскольку я уверен, что эта проблема возникла раньше, но ни один из примеров, кажется, не подходит.

Я пытаюсь создать 2D-список (4 на 100), который назначает случайные значения в разных диапазонах в каждой строке.

import random
size_of_meadow = 100
no_of_flowers = 100
no_of_flower_types = 3

flower = [[0] * 5] * no_of_flowers

for row in range(no_of_flowers):
    flower[row][0] = random.randint(0, size_of_meadow - 1)  # x coord
    flower[row][1] = random.randint(0, size_of_meadow - 1)  # y coord
    flower[row][2] = random.randint(1, no_of_flower_types)
if random.randint(0, 100) < 5:
    flower[row][3] = 1
else:
    flower[row][3] = 0

print(flower[0][0])
print(flower[0][1])
print(flower[0][2])
print(flower[0][3])
print(" ")
print(flower[1][0])
print(flower[1][1])
print(flower[1][2])
print(flower[1][3])
# Sorry the above isn't in a for loop

Выходные данные просто показывают одинаковый набор чисел для каждой строки списка 2D ...

Выход:

29
21
2
0

29
21
2
0

Я новичок в python, и я знаю, что, должно быть, мне не хватает чего-то фундаментального, но после долгих размышлений и ахинга я не понял этого, любая помощь приветствуется.

Спасибо

Ответы [ 3 ]

3 голосов
/ 20 марта 2019

Используя [[0] * 5] * no_of_flowers, вы создаете 100 ссылок на один и тот же список.Это означает, что в памяти ТОЛЬКО ОДНА СТРОКА .

Когда вы изменяете строку, если она влияет на строку в памяти, и поскольку все остальные «строки» ссылаются на нее, они просто будут использовать список в памяти, который обновлен.

Чтобы избежать этого сценария, вы можете использовать:

flower = [[0 for _ in range(5)] for _ in range(no_of_flowers)]

Вы можете найти пример и объяснение в wtfpython :

# Let's initialize a row
row = [""]*3 #row i['', '', '']
# Let's make a board
board = [row]*3

Вывод:

>>> board
[['', '', ''], ['', '', ''], ['', '', '']]
>>> board[0]
['', '', '']
>>> board[0][0]
''
>>> board[0][0] = "X"
>>> board
[['X', '', ''], ['X', '', ''], ['X', '', '']]

Объяснение:

Когда мы инициализируем переменную row, эта визуализация объясняет, что происходит в памяти.

enter image description here

И когда board инициализируется умножением row, это то, что происходит внутри памяти (каждый из элементов board[0], board[1] и board[2] является ссылкой на тот же список, на который ссылается row)

enter image description here

Мы можем избежать этого сценария, не используя row переменная для генерации board.(Спрашивается в этом выпуске).

>>> board = [['']*3 for _ in range(3)]
>>> board[0][0] = "X"
>>> board
[['X', '', ''], ['', '', ''], ['', '', '']]
2 голосов
/ 20 марта 2019

Привет, @Lee, это правильно, но позвольте мне уточнить

>>> flower = [[0] * 5] * 100
>>> flower[0]
[0, 0, 0, 0, 0]
>>> flower[1]
[0, 0, 0, 0, 0]
>>> id(flower[0])
4354853640
>>> id(flower[1])
4354853640

Здесь вы можете видеть, что каждый подсписок будет указывать на одно и то же место в памяти

Я бы использовал этот метод:

flower = [[None for _ in range(5)] for _ in range(no_of_flowers)] 

>>> id(flower[0])
4354853832
>>> id(flower[1])
4354854600
2 голосов
/ 20 марта 2019

У вас есть один список, который содержит 100 раз один и тот же список

a=[0,0,0]
flower=[a,a,a,a,...]

Лучшим решением будет

import random

size_of_meadow = 100
no_of_flowers = 100
no_of_flower_types = 3

flower = []

for row in range(no_of_flowers):
  flower.append([random.randint(0, size_of_meadow-1),
      random.randint(0, size_of_meadow-1),
      random.randint(1, no_of_flower_types),
      1 if random.randint(0, 100) < 5 else 0])

print(flower[0][0])
print(flower[0][1])
print(flower[0][2])
print(flower[0][3])
print(" ")
print(flower[1][0])
print(flower[1][1])
print(flower[1][2])
print(flower[1][3])
# Sorry the above isn't in a for loop

Однако генератор цветов был бы еще лучше

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...