Python | Usando arreglos/listas 2D de la manera correcta

Python proporciona muchas formas de crear listas/arrays bidimensionales. Sin embargo, uno debe conocer las diferencias entre estas formas porque pueden crear complicaciones en el código que pueden ser muy difíciles de rastrear. Comencemos mirando formas comunes de crear una array 1d de tamaño N inicializada con 0s.

Java-Foundation-Course

 
Método 1a 
 

Python3

# First method to create a 1 D array
N = 5
arr = [0]*N
print(arr)
Producción: 

[0, 0, 0, 0, 0]

 

Método 1b 
 

Python3

# Second method to create a 1 D array
N = 5
arr = [0 for i in range(N)]
print(arr)
Producción: 

[0, 0, 0, 0, 0]

 

Extendiendo lo anterior, podemos definir arrays bidimensionales de las siguientes maneras. 
Método 2a 
 

Python3

# Using above first method to create a 
# 2D array
rows, cols = (5, 5)
arr = [[0]*cols]*rows
print(arr)
Producción: 

[[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]]

 

Método 2b 
 

Python3

# Using above second method to create a 
# 2D array
rows, cols = (5, 5)
arr = [[0 for i in range(cols)] for j in range(rows)]
print(arr)
Producción: 

[[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]]

 

Método 2c 
 

Python3

# Using above second method to create a 
# 2D array
rows, cols = (5, 5)
arr=[]
for i in range(rows):
    col = []
    for j in range(cols):
        col.append(0)
    arr.append(col)
print(arr)
Producción: 

[[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]]

 

Ambas formas dan aparentemente el mismo resultado a partir de ahora. Cambiemos uno de los elementos en la array del método 2a y el método 2b. 
 

Python3

# Python 3 program to demonstrate working 
# of method 1 and method 2.
  
rows, cols = (5, 5)
  
# method 2a
arr = [[0]*cols]*rows
  
# lets change the first element of the 
# first row to 1 and print the array
arr[0][0] = 1
  
for row in arr:
    print(row)
# outputs the following
#[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]
  
# method 2b
arr = [[0 for i in range(cols)] for j in range(rows)]
  
# again in this new array lets change
# the first element of the first row 
# to 1 and print the array
arr[0][0] = 1
for row in arr:
    print(row)
  
# outputs the following as expected
#[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]
Producción: 

[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]

 

Esperamos que solo el primer elemento de la primera fila cambie a 1, pero el primer elemento de cada fila se cambia a 1 en el método 2a. Este peculiar funcionamiento se debe a que Python utiliza listas poco profundas que trataremos de entender.
En el método 1a, Python no crea 5 objetos enteros sino que crea solo un objeto entero y todos los índices de la array arr apuntan al mismo objeto int como se muestra. 
 

1d shallow array representation

Si asignamos el índice 0 a otro entero, digamos 1, entonces se crea un nuevo objeto entero con el valor de 1 y luego el índice 0 ahora apunta a este nuevo objeto int como se muestra a continuación.
 

1d shallow array changed value

De manera similar, cuando creamos una array 2d como «arr = [[0]*columnas]*filas» estamos esencialmente extendiendo la analogía anterior. 
1. Solo se crea un objeto entero. 
2. Se crea una sola lista 1d y todos sus índices apuntan al mismo objeto int en el punto 1. 
3. Ahora, arr[0], arr[1], arr[2]…. arr[n-1] todos apuntan al mismo objeto de lista anterior en el punto 2.
La configuración anterior se puede visualizar en la imagen a continuación.
 

2d shallow array representation

Ahora cambiemos el primer elemento en la primera fila de «arr» como 
arr[0][0] = 1
=> arr[0] apunta al único objeto de lista que creamos arriba. (Recuerde arr[1], arr[2 ] …arr[n-1] todos apuntan al mismo objeto de lista también) 
=> La asignación de arr[0][0] creará un nuevo objeto int con el valor 1 y arr[0][0] ahora apuntará a este nuevo objeto int. (y también arr[1][0], arr[2][0] …arr[n-1][0])
Esto se puede ver claramente en la siguiente imagen.
 

2d shallow array changed

Entonces, cuando se crean arrays 2D de esta manera, el cambio de valores en una determinada fila afectará a todas las filas, ya que esencialmente solo hay un objeto entero y solo un objeto de lista al que hacen referencia todas las filas de la array.
Como era de esperar, es difícil rastrear los errores causados ​​por el uso de listas poco profundas. Por lo tanto, la mejor manera de declarar una array 2d es 
 

Python3

rows, cols = (5, 5)
arr = [[0 for i in range(cols)] for j in range(rows)]
Producción: 

 

 

Este método crea 5 objetos de lista separados a diferencia del método 2a. Una forma de verificar esto es usar el operador ‘es’ que verifica si los dos operandos se refieren al mismo objeto. 
 

Python3

rows, cols = (5, 5)
# method 2b
arr = [[0 for i in range(cols)] for j in range(rows)]
  
# check if arr[0] and arr[1] refer to
# the same object
print(arr[0] is arr[1]) # prints False
  
# method 2a
arr = [[0]*cols]*rows
  
# check if arr[0] and arr[1] refer to 
# the same object
# prints True because there is only one
# list object being created.
print(arr[0] is arr[1])
Producción: 

False
True

 

Publicación traducida automáticamente

Artículo escrito por Pranav Devarakonda y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *