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.
Método 1a
Python3
# First method to create a 1 D array N = 5 arr = [0]*N print(arr)
[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)
[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)
[[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)
[[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)
[[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]
[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.
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.
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.
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.
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)]
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])
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