🎯 Criando Listas de Listas em Python
Em poucas palavras
Usar o operador
*para criar listas de listas, como[['_'] * 3] * 3, não gera sublistas independentes: cria múltiplas referências ao mesmo objeto, de modo que alterar uma posição afeta todas as linhas. A forma segura é construir cada sublista separadamente.
📝 Notas e Desenvolvimento
O Problema com o Operador * para Listas Aninhadas
Quando você usa o operador * para criar uma lista de listas, como [['_'] * 3] * 3, o Python não cria novas listas independentes para cada sublista. Em vez disso, ele cria múltiplas referências à mesma lista interna.
Exemplo Incorreto:
### Usando o operador * para criar uma lista de listas
weird_board = [['_'] * 3] * 3
print("weird_board inicial:", weird_board)
### Saída: [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
### Modificando um elemento em uma das sublistas
weird_board[1][2] = 'O'
print("weird_board após modificação:", weird_board)
### Saída: [['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]
Como você pode ver, ao modificar weird_board[1][2], todas as sublistas foram afetadas, pois weird_board[0], weird_board[1] e weird_board[2] são, na verdade, o mesmo objeto de lista na memória.
A Solução Correta: Usando Compreensão de listas em Python
A maneira recomendada e segura de criar listas de listas onde cada sublista é um objeto independente é usando uma Compreensão de listas em Python. Isso garante que cada sublista seja criada como uma nova instância.
Exemplo Correto:
### Usando compreensão de lista para criar uma lista de listas
board = [['_'] * 3 for _ in range(3)]
print("board inicial:", board)
### Saída: [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
### Modificando um elemento em uma das sublistas
board[1][2] = 'X'
print("board após modificação:", board)
### Saída: [['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]
Neste caso, a modificação em board[1][2] afeta apenas a segunda sublista, como esperado, porque cada ['_'] * 3 dentro da compreensão de lista cria uma nova lista distinta.
Por que a Diferença?
- Operador
*(repetição de lista): Realiza uma “cópia rasa” (shallow copy). Se os elementos da lista original são objetos mutáveis (como outras listas), o operador*apenas copia as referências a esses objetos. Assim, todas as “cópias” apontam para os mesmos objetos subjacentes. - Compreensão de listas em Python: Executa a expressão para cada iteração. No exemplo
[['_'] * 3 for _ in range(3)], a expressão['_'] * 3é avaliada três vezes, criando três novas e distintas listas['_', '_', '_'], e então essas três listas são coletadas na lista externa.
Sempre que precisar de listas aninhadas independentes, prefira o uso de Compreensão de listas em Python para garantir que cada sublista seja um objeto distinto na memória.
:: Referência :: Site oficial do Python sobre compreensões de lista