Sala de Aprendizaje Karinoya

Certificaciones · Laboratorio para aprobar Cloud / IA / Python

Control de flujo y estructuras de datos

Puedes leer las preguntas y explicaciones en Español. Las lecciones (artículos explicativos) solo están disponibles en japonés.

Ver la versión en japonés (con lecciones) →

Pregunta 1 | for/else

Al ejecutar el siguiente código, que añade una cláusula else a una sentencia for, ¿qué se muestra?

for n in range(4):    if n == 9:        breakelse:    print("done")print(n)
  1. Solo se muestra 3 y no aparece done
  2. Solo se muestra done y no aparece 3
  3. Se muestran 3 y done en este orden
  4. Se muestran done y 3 en este orden
RespuestaD. Se muestran done y 3 en este orden

Una cláusula else (else 節) añadida a una sentencia for se ejecuta cuando el bucle termina sin haber sido interrumpido por break. No hay ningún 9 en range(4), así que break nunca ocurre y, tras recorrer el bucle hasta el final, se ejecuta el print de else, por lo que aparece done. A continuación, print(n) muestra el valor que quedó en n al salir del bucle, el último valor, 3. Invertir el orden da la forma en que 3 aparece primero; creer erróneamente que else siempre se omite al final de un bucle da la forma sin done; y pasar por alto que n permanece tras salir del bucle da la forma sin 3.

Pregunta 2 | break y else

Compruebe cómo se trata la cláusula else cuando se sale de un bucle con break. ¿Cuál es la salida del siguiente código?

for c in "abc":    if c == "b":        break    print(c)else:    print("no break")
  1. Se muestran todos: a b c y no break
  2. Se muestran a y no break en este orden
  3. Se muestran los dos, a y b, en este orden
  4. Se muestra a y no se muestra no break
RespuestaD. Se muestra a y no se muestra no break

En la primera vuelta, c es a, así que se ejecuta print(c) y sale a. En la segunda vuelta, c pasa a ser b y break corta el bucle. La cláusula else de una sentencia for solo se ejecuta cuando el bucle termina sin haber sido interrumpido por break, así que aquí se omite y no aparece no break. Suponer que else siempre se ejecuta al terminar el bucle da la forma en que también aparece no break; malinterpretarlo como si print(c) estuviera antes de break da la forma en que también aparece b; y pasar por alto el propio break da la forma en que se muestran a b c.

Pregunta 3 | else incluso cuando está vacío

Considere qué ocurre con la cláusula else de una sentencia for cuando lo que se recorre está vacío. ¿Cuál es el resultado de ejecutar el siguiente código?

items = []for it in items:    print(it)else:    print("finished")
  1. Se ignora la cláusula else y se produce un TypeError
  2. Como hay 0 iteraciones, se produce un StopIteration
  3. Sale del bucle sin mostrar absolutamente nada
  4. Se muestra finished una sola vez
RespuestaD. Se muestra finished una sola vez

La condición para que se ejecute la cláusula else de una sentencia for es «el bucle terminó sin ser interrumpido por break», no «iteró al menos una vez». Como items está vacía, el cuerpo nunca se ejecuta, pero como tampoco ocurrió break, else se ejecuta igualmente y se muestra finished. Si se piensa que else también se omite cuando está vacía, se obtiene la forma en que no se muestra nada. Pasar una lista vacía a una sentencia for es en sí una sintaxis correcta, así que no se lanza ninguna excepción: ni TypeError ni StopIteration.

Pregunta 4 | while/else

Considere añadir una cláusula else a una sentencia while y salir a mitad de camino con break. ¿Cuál es la salida del siguiente código?

n = 5while n > 0:    n -= 1    if n == 2:        breakelse:    print("loop ended")print(n)
  1. Se muestra 0 y no se muestra loop ended
  2. Se muestra 2 y no se muestra loop ended
  3. Se muestran loop ended y 2 en este orden
  4. Se muestran loop ended y 0 en este orden
RespuestaB. Se muestra 2 y no se muestra loop ended

n disminuye de 1 en 1 desde 5, pasando por 4 y 3, y se ejecuta break en cuanto llega a 2. La cláusula else (else 節) de una sentencia while, al igual que la de una sentencia for, solo se ejecuta cuando el bucle termina sin ser interrumpido por break, así que aquí se omite y no aparece loop ended. Lo único que queda es el 2 de print(n). Pensar que else siempre se ejecuta da la forma en que también aparece loop ended, y pasar por alto break y malinterpretarlo como si el bucle siguiera hasta que la condición fuera falsa da la forma en que n llega a 0.

Pregunta 5 | continue

Al ejecutar el siguiente código, que combina continue y break en un mismo bucle, ¿qué lista se muestra al final?

out = []for i in range(6):    if i == 3:        continue    if i == 5:        break    out.append(i)print(out)
  1. [0, 1, 2, 4, 5]
  2. [0, 1, 2, 3]
  3. [0, 1, 2, 4]
  4. [0, 1, 2, 3, 4]
RespuestaC. [0, 1, 2, 4]

Cuando i es 0, 1 o 2, se pasan las dos sentencias if y el valor se añade. Cuando i es 3, actúa continue, que omite el resto de esa vuelta, es decir, el append. Cuando i es 4, se vuelve a añadir, y cuando i es 5, break corta el bucle, así que no se produce ningún append. Por lo tanto, el resultado es [0, 1, 2, 4]. Pensar que la vuelta con break también se añade da la forma que llega hasta 5, y tratar continue como si fuera pass da la forma en que queda el 3.

Pregunta 6 | range en orden inverso

Considere el orden que se produce cuando a range se le da un paso negativo. ¿Cuál es la salida del siguiente código?

print(list(range(10, 0, -3)))
  1. [9, 6, 3, 0]
  2. [7, 4, 1, -2]
  3. [10, 7, 4, 1, 0]
  4. [10, 7, 4, 1]
RespuestaD. [10, 7, 4, 1]

range(start, stop, step) empieza en start, avanza de step en step y se detiene antes de llegar a stop. Aquí, al restar 3 repetidamente a 10, se avanza como 10, 7, 4, 1, y el siguiente valor, -2, no se adopta porque es 0 o menor. Como el valor de parada 0 no se incluye, no se obtiene una secuencia que termine en 0. Creer erróneamente que start no se incluye da la forma que empieza en 7, y pensar que la cuenta empieza un paso antes de start da la forma que empieza en 9. El hecho de que stop no se incluye es igual que cuando el paso es positivo.

Pregunta 7 | El tipo de range

¿Cuál de las siguientes describe correctamente el objeto que se obtiene al llamar a la función integrada range?

  1. Un objeto de tipo generator que queda vacío después de recorrerse una vez
  2. Un objeto de tipo range que se convierte en lista al pasarlo a list()
  3. Un objeto de tipo tuple cuyos elementos no pueden reemplazarse
  4. Un objeto de tipo list que se muestra tal cual con corchetes
RespuestaB. Un objeto de tipo range que se convierte en lista al pasarlo a list()

Lo que devuelve range es un objeto de tipo range, que calcula el entero necesario cada vez que se le pide. No guarda todos los elementos de antemano como una lista, así que no consume memoria ni siquiera con un rango grande. Para ver el contenido ordenado, se pasa por list(). type(range(3)) es range, no list ni tuple, y si simplemente se muestra, no aparece la secuencia de elementos, sino range(0, 3). Tampoco es un generador, ya que no es de un solo uso y puede recorrerse cualquier número de veces. Tenga en cuenta que la propiedad de poder leerse por índice sin permitir reemplazar elementos es la misma que la de una tupla (タプル), así que esa propiedad por sí sola no permite distinguirlo de una tupla.

Pregunta 8 | Evaluación de cortocircuito

Compruebe qué devuelven los operadores lógicos or y and. ¿Cuál es la salida del siguiente código?

print([] or 0 or "z")print(1 and 0 and 2)
  1. Se muestran True y False en este orden
  2. Se muestran False y 0 en este orden
  3. Se muestran z y 0 en este orden
  4. Se muestran z y 2 en este orden
RespuestaC. Se muestran z y 0 en este orden

or evalúa de izquierda a derecha y devuelve tal cual el primer valor que resulta verdadero. Como una lista vacía y 0 son ambos falsos, se devuelve el último, "z". and, por el contrario, devuelve el primer valor que resulta falso: 1 es verdadero, luego con el siguiente valor, 0, queda determinado el falso y se devuelve 0, y el 2 del extremo derecho nunca se evalúa (evaluación de cortocircuito, 短絡評価). Lo que se devuelve no es un valor booleano (真偽値), sino el valor en el punto en que se detuvo la evaluación, así que nunca sale True ni False. Que and devuelva el 2 del extremo derecho solo ocurre cuando todo lo anterior era verdadero.

Pregunta 9 | Comparación encadenada

Al ejecutar el siguiente código, que combina una comparación encadenada con una expresión ternaria, ¿qué se muestra?

x = 3print(1 < x < 5)print("yes" if x % 2 else "no")
  1. Se muestran True y yes en este orden
  2. Se muestran True y no en este orden
  3. Se muestran False y no en este orden
  4. Se muestran False y yes en este orden
RespuestaA. Se muestran True y yes en este orden

1 < x < 5 significa lo mismo que (1 < x) and (x < 5); si x es 3, ambas se cumplen, así que es True. Una expresión ternaria (三項演算子) se ordena como valor-si-verdadero if condición else valor-si-falso, y aquí la condición es x % 2, es decir, 1. En Python, cualquier entero distinto de cero se trata como verdadero, así que se elige yes. Malinterpretar la comparación encadenada (連鎖比較) como si se asociara desde atrás, como en 1 < (x < 5), lleva a la respuesta errónea de que x < 5 es True, es decir, 1, y entonces 1 < 1 es False. Además, considerar 1 como falso lleva a elegir no.

Pregunta 10 | La función de pass

¿Cuál de las siguientes describe correctamente la sentencia pass de Python?

  1. Indica cortar el propio bucle y salir de él
  2. Indica no hacer nada, en un lugar donde sintácticamente se requiere un bloque
  3. Indica saltarse el resto de un bucle y pasar a la siguiente iteración
  4. Indica que la función ha terminado de ejecutarse y devuelve un valor a quien la llamó
RespuestaB. Indica no hacer nada, en un lugar donde sintácticamente se requiere un bloque

Como Python representa los bloques con sangría, no se puede escribir un bloque vacío. pass es lo que ocupa ese lugar, para cuando se piensa escribir más tarde el contenido de una clase o función, o cuando se quiere deliberadamente no hacer nada al cumplirse una condición. No tiene ningún efecto sobre el flujo de ejecución. Pasar a la siguiente iteración es continue, cortar el bucle es break y devolver un valor a quien llamó es return; cada uno cumple una función distinta de la de pass.

Pregunta 11 | enumerate

Al ejecutar el siguiente código, que pasa un segundo argumento a enumerate, ¿qué aparece en la pantalla?

for i, name in enumerate(["gu", "choki", "pa"], 1):    print(i, name)
  1. Se muestran las 3 líneas 1 gu / 2 choki / 3 pa
  2. Se muestran las 3 líneas 0 gu / 1 choki / 2 pa
  3. Se muestran las 3 líneas gu 1 / choki 2 / pa 3
  4. Solo se muestran las 2 líneas 1 gu / 2 choki
RespuestaA. Se muestran las 3 líneas 1 gu / 2 choki / 3 pa

enumerate devuelve en orden tuplas (タプル) de (número, elemento), y el segundo argumento, start, permite especificar el valor desde el que se empieza a contar. Aquí se pasa 1, así que los números son 1, 2, 3. Confundirlo con el valor predeterminado, que empieza en 0 cuando se omite start, da la forma que empieza en 0. Como la tupla devuelta tiene el número primero y el elemento después, print(i, name) sigue ese mismo orden, así que el nombre nunca sale primero. Se extraen los 3 elementos, así que tampoco se corta después de 2 líneas.

Pregunta 12 | La longitud de zip

Se pasaron a zip dos listas de longitudes distintas. ¿Cuál es el resultado de ejecutar el siguiente código?

print(list(zip([1, 2, 3], [10, 20])))
  1. [(1, 10), (2, 20)]
  2. [(1, 10), (2, 20), (3,)]
  3. [(1, 10), (2, 20), (3, 0)]
  4. [(10, 1), (20, 2)]
RespuestaA. [(1, 10), (2, 20)]

zip toma un elemento cada vez de cada uno de los iterables (反復可能オブジェクト) que recibe, los empareja y se detiene en cuanto se agota el más corto. Aquí, la segunda lista tiene 2 elementos, así que solo se forman 2 pares, y el 3 sobrante se descarta sin aviso. No se produce un error, no se rellena lo que falta con 0 y tampoco se crea una tupla con un solo elemento. El contenido de cada par sigue el orden en que se pasaron, así que no se intercambian como lo harían 10 y 1.

Pregunta 13 | Separar pares con zip

Los datos emparejados se volvieron a pasar a zip con un asterisco. ¿Cuál es la salida del siguiente código?

pairs = [(1, 'a'), (2, 'b'), (3, 'c')]nums, chars = zip(*pairs)print(nums)print(chars)
  1. Se muestra [1, 2, 3] y luego ['a', 'b', 'c']
  2. Se muestra (1, 2, 3) y luego ('a', 'b', 'c')
  3. Se muestra ((1, 'a'),) y luego ((2, 'b'),)
  4. Se muestra (1, 'a') y luego (2, 'b')
RespuestaB. Se muestra (1, 2, 3) y luego ('a', 'b', 'c')

Añadir un asterisco pasa cada par de la lista a zip como un argumento independiente. Es decir, equivale a llamar a zip((1, 'a'), (2, 'b'), (3, 'c')): se reúnen los primeros elementos de cada par por un lado y los segundos por otro, y se separan en las dos secuencias (1, 2, 3) y ('a', 'b', 'c'). Este es el truco habitual para devolver datos emparejados a sus dos secuencias originales, y pasarlos dos veces por zip devuelve el original. Lo que se devuelve son tuplas (タプル), no listas, así que no sale con corchetes. Si se olvida el asterisco y se escribe zip(pairs), cada par se pasa como un solo argumento y se obtiene la forma ordenada como tuplas de un elemento, como ((1, 'a'),).

Pregunta 14 | dict y zip

Se construye un diccionario a partir de una secuencia de claves y una secuencia de valores. ¿Cuál es el resultado de ejecutar el siguiente código?

keys = ["a", "b", "c"]vals = [10, 20, 30]print(dict(zip(keys, vals)))
  1. [('a', 10), ('b', 20), ('c', 30)]
  2. {10: 'a', 20: 'b', 30: 'c'}
  3. {'a', 'b', 'c', 10, 20, 30}
  4. {'a': 10, 'b': 20, 'c': 30}
RespuestaD. {'a': 10, 'b': 20, 'c': 30}

zip(keys, vals) devuelve en orden tuplas (タプル) de (clave, valor), y dict() toma esa secuencia de pares y construye un diccionario a partir de ella. El primer elemento de cada par se convierte en la clave y el segundo en el valor, así que no salen los números como claves. Como se pasa por dict(), tampoco se queda como una lista de tuplas. Aunque se muestre con llaves, lo que hace que algo sea un diccionario es tener pares unidos por dos puntos; si solo hubiera valores ordenados, sería un conjunto.

Pregunta 15 | Comprensión de listas

Al ejecutar el siguiente código, que usa una comprensión de listas, ¿qué lista se muestra?

print([n * n for n in range(1, 5)])
  1. [0, 1, 4, 9]
  2. [2, 4, 6, 8]
  3. [1, 4, 9, 16]
  4. [1, 4, 9, 16, 25]
RespuestaC. [1, 4, 9, 16]

range(1, 5) devuelve 1, 2, 3, 4; el valor de parada especificado, 5, no se incluye. Al elevar cada uno al cuadrado se obtiene 1, 4, 9, 16. Suponer que range empieza en 0 da una secuencia que empieza en 0, y creer erróneamente que stop se incluye da una secuencia que llega hasta 25. Malinterpretar n * n como n * 2 da una secuencia que aumenta de 2 en 2. Conviene acostumbrarse a leer una comprensión de listas (リスト内包表記) como la evaluación de la expresión de la izquierda para cada elemento y la construcción de una nueva lista con los resultados.

Pregunta 16 | Comprensión de diccionarios

Ejecute una comprensión que tiene dos puntos dentro de llaves. ¿Cuál es la salida del siguiente código?

words = ["sun", "moon"]print({w: len(w) for w in words})
  1. {'sun': 3, 'moon': 4}
  2. [('sun', 3), ('moon', 4)]
  3. {3: 'sun', 4: 'moon'}
  4. {'sun', 'moon', 3, 4}
RespuestaA. {'sun': 3, 'moon': 4}

Una comprensión con dos puntos dentro de llaves es una comprensión de diccionarios (辞書内包表記), en la que lo que está a la izquierda de los dos puntos se convierte en la clave y lo que está a la derecha en el valor. Aquí produce un diccionario con cada palabra como clave y su número de caracteres como valor. Leer la clave y el valor intercambiados daría un diccionario con el número de caracteres como clave. Si se encerrara entre corchetes, daría una lista de tuplas, pero aquí son llaves, así que eso no ocurre. Sin dos puntos sería una comprensión de conjuntos (集合内包表記) y saldría como una simple muestra de valores ordenados, pero como hay dos puntos, el resultado es un diccionario.

Pregunta 17 | El tipo que dan los paréntesis

Se encerró entre paréntesis algo que parece una comprensión. ¿Qué tipo se muestra al ejecutar el siguiente código?

g = (n for n in range(3))print(type(g))
  1. <class 'range'>
  2. <class 'list'>
  3. <class 'generator'>
  4. <class 'tuple'>
RespuestaC. <class 'generator'>

En Python no existe la comprensión de tuplas, y esta forma, encerrada entre paréntesis, se convierte en una expresión generadora (ジェネレータ式). Su tipo es generator; en lugar de crear todos los valores de antemano, los calcula uno a uno a medida que se piden, así que ahorra memoria, pero como es un iterador (イテレータ), se agota después de usarse una vez. Cuando se quiere una tupla, se envuelve con tuple(). Si se escribe con corchetes, se convierte en una comprensión de listas y da una list, y si se asigna range(3) directamente se obtiene un range. Con esta forma de escribir no se obtiene tuple.

Pregunta 18 | Comprensión de conjuntos

Cuente el número de elementos del contenedor creado por una comprensión de conjuntos. ¿Cuál es la salida del siguiente código?

print(len({n % 4 for n in range(10)}))
  1. Se muestra 3
  2. Se muestra 0
  3. Se muestra 10
  4. Se muestra 4
RespuestaD. Se muestra 4

Cada valor de range(10) dividido entre 4 deja un resto de 0, 1, 2, 3, 0, 1, 2, 3, 0, 1. Una comprensión con llaves y sin dos puntos es una comprensión de conjuntos (集合内包表記), así que los valores duplicados se reúnen en uno solo, y lo que queda son los 4 valores distintos 0, 1, 2, 3. Pasar por alto que los duplicados desaparecen y simplemente contar el número de valores da 10. Pasar por alto que 0 está entre los restos y contar solo 1, 2, 3 da 3. 0 es el valor si se cree erróneamente que la comprensión no produce nada, pero mientras recorra range(10), el contenido nunca está vacío. El orden en que se muestra un conjunto no es fijo, así que comprobarlo por el número de elementos es la forma fiable.

Pregunta 19 | Una comprensión anidada

Considere el orden cuando se colocan dos cláusulas for en una comprensión. ¿Cuál es el resultado de ejecutar el siguiente código?

print([(x, y) for x in [1, 2] for y in "ab"])
  1. [(1, 'a'), (2, 'b'), (1, 'b'), (2, 'a')]
  2. [('a', 1), ('b', 1), ('a', 2), ('b', 2)]
  3. [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
  4. [(1, 'a'), (2, 'a'), (1, 'b'), (2, 'b')]
RespuestaC. [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]

Cuando una comprensión (内包表記) tiene dos cláusulas for, la que está escrita a la izquierda se convierte en el bucle exterior. Es exactamente el mismo orden que al escribir dos sentencias for ordinarias anidadas: x se fija en 1 mientras y recorre a y b, y luego x pasa a 2 y se repite lo mismo. Leer la cláusula for de la derecha como la exterior da un orden en el que x cambia primero. El contenido de cada par sigue el orden escrito en la expresión, (x, y), así que la letra nunca va primero.

Pregunta 20 | El argumento start

¿Cuál de las siguientes describe correctamente el argumento start, el segundo argumento de la función integrada enumerate?

  1. Especifica el número desde el que se empieza a contar; si se omite, se cuenta desde 0
  2. Especifica desde qué elemento se empieza a tomar; si se omite, se empieza desde el principio
  3. Especifica cuántos se saltan cada vez; si se omite, se avanza de uno en uno
  4. Especifica hasta cuántos se cuenta; si se omite, se cuenta hasta el final
RespuestaA. Especifica el número desde el que se empieza a contar; si se omite, se cuenta desde 0

El segundo argumento de enumerate, start, solo decide desde qué número se empieza a numerar. El valor predeterminado es 0, así que pasar 1 da una numeración correlativa más cómoda para las personas. Solo cambia la forma de asignar los números; el punto clave es que el rango y la cantidad de elementos extraídos no cambian. No tiene el efecto de limitar ni de saltar la cuenta, ni desplaza la posición inicial de la extracción. Todo eso corresponde a otras herramientas, como las rebanadas.

Pregunta 21 | El valor de retorno de sort

Se guardó en una variable el valor de retorno del método sort de una lista. ¿Cuál es la salida del siguiente código?

nums = [5, 3, 9]result = nums.sort()print(result)print(nums)
  1. Se muestran [3, 5, 9] y [3, 5, 9] en este orden
  2. Se muestran None y [5, 3, 9] en este orden
  3. Se muestran [3, 5, 9] y [5, 3, 9] en este orden
  4. Se muestran None y [3, 5, 9] en este orden
RespuestaD. Se muestran None y [3, 5, 9] en este orden

sort es un método que ordena una lista en el lugar (その場), y su valor de retorno es None. Por eso result contiene None, y el resultado ordenado queda en nums. Si se supone que se devuelve una nueva lista ordenada, se obtiene la forma en que result contiene una lista. Pasar por alto que sort cambia la lista original da la forma en que nums conserva su orden original. Cuando se quiere la lista ordenada conservando la original, se usa la función integrada (組み込み関数) sorted.

Pregunta 22 | La diferencia con sorted

¿Cuál de las siguientes describe correctamente la diferencia entre el método sort de una lista y la función integrada sorted?

  1. sort devuelve una nueva lista, y sorted ordena en el lugar y devuelve None
  2. sort ordena en el lugar y devuelve None, y sorted devuelve una nueva lista
  3. Ambos devuelven una nueva lista, y ninguna de las listas originales cambia
  4. Ambos ordenan en el lugar y además devuelven la lista ordenada
RespuestaB. sort ordena en el lugar y devuelve None, y sorted devuelve una nueva lista

sort es un método de las listas: ordena esa misma lista y devuelve None como valor de retorno. sorted es una función integrada (組み込み関数): devuelve una nueva lista ordenada sin cambiar en absoluto el orden original. Cuál elegir depende de si se quiere conservar la original. Intercambiar los papeles de ambos da la explicación según la cual sort devuelve una nueva lista. Inclinarse hacia uno u otro lado sobre si es destructivo (破壊的) da la explicación según la cual ambos ordenan en el lugar, o la de que ninguno cambia la original. Tenga en cuenta que sorted también puede recibir un iterable que no sea una lista, y su resultado es siempre una lista.

Pregunta 23 | La diferencia con append

Compare dos formas de añadir una lista a otra. ¿Cuál es la salida del siguiente código?

a = [1, 2]a.append([3, 4])b = [1, 2]b.extend([3, 4])print(a, b)
  1. [1, 2, [3, 4]] [1, 2, [3, 4]]
  2. [1, 2, 3, 4] [1, 2, [3, 4]]
  3. [1, 2, 3, 4] [1, 2, 3, 4]
  4. [1, 2, [3, 4]] [1, 2, 3, 4]
RespuestaD. [1, 2, [3, 4]] [1, 2, 3, 4]

append añade su argumento al final como un único elemento completo, así que, si se pasa una lista, queda anidada y la longitud aumenta en 1. extend añade uno a uno los valores obtenidos al recorrer su argumento, así que el contenido se desempaqueta y la longitud aumenta en 2. Intercambiar los papeles de ambos invierte los resultados de a y b. Suponer que ambos hacen lo mismo da la forma en que ambos quedan anidados o la forma en que ambos quedan aplanados. Ambos métodos tienen además None como valor de retorno, así que conviene recordar no guardar el resultado en una variable.

Pregunta 24 | Copia superficial

Se duplicó una lista anidada con una rebanada y se reescribió la parte interior. ¿Cuál es el resultado de ejecutar el siguiente código?

orig = [[1, 2], [3, 4]]copy1 = orig[:]copy1[0].append(9)print(orig)
  1. [[1, 2, 9], [3, 4, 9]]
  2. [[1, 2, 9], [3, 4]]
  3. [[1, 2], [3, 4]]
  4. [[1, 2], [3, 4], 9]
RespuestaB. [[1, 2, 9], [3, 4]]

La duplicación mediante una rebanada es una copia superficial (浅いコピー): la lista exterior se crea de nuevo, pero los elementos de su interior se comparten con los mismos objetos que el original. copy1[0] y orig[0] apuntan a la misma lista, así que lo que se añade a ella también se refleja en el original. Si se supone que están completamente separados, se obtiene la forma en que el original no cambia. Solo se reescribió la primera lista interior, así que no afecta al elemento posterior, y no se añadió nada a la lista exterior, así que el 9 tampoco acaba en la lista exterior. Para separar también las partes interiores, use copy.deepcopy (copia profunda, 深いコピー).

Pregunta 25 | Copia profunda

Compare la copia profunda y la copia superficial en un mismo fragmento de código. ¿En qué se convierte base después de ejecutarlo?

import copybase = [[1, 2], [3, 4]]d = copy.deepcopy(base)s = base[:]d[0].append(8)s[1].append(7)print(base)
  1. [[1, 2], [3, 4]]
  2. [[1, 2, 8], [3, 4, 7]]
  3. [[1, 2, 8], [3, 4]]
  4. [[1, 2], [3, 4, 7]]
RespuestaD. [[1, 2], [3, 4, 7]]

copy.deepcopy duplica hasta el fondo el contenido anidado (copia profunda, 深いコピー), así que d[0] pasa a ser una lista distinta de base[0], y lo que se añade a ella no llega a base. En cambio, s es una copia superficial (浅いコピー), así que s[1] y base[1] son la misma lista, y lo que se añade a ella sí se refleja también en base. Por lo tanto, solo se amplía el elemento posterior. Suponer que ambos llegan a base da la forma en que se amplían las dos listas interiores, y suponer que ninguno llega da la forma que queda sin cambios. Confundir la copia profunda con la superficial da la forma en que solo se amplía el elemento anterior.

Pregunta 26 | Una trampa de la multiplicación

Se intentó construir una tabla bidimensional con la multiplicación de listas. ¿Cuál es el resultado de ejecutar el siguiente código?

grid = [[0] * 3] * 2grid[0][1] = 5print(grid)
  1. [[0, 0, 0], [0, 5, 0]]
  2. [[5, 0, 0], [5, 0, 0]]
  3. [[0, 5, 0], [0, 0, 0]]
  4. [[0, 5, 0], [0, 5, 0]]
RespuestaD. [[0, 5, 0], [0, 5, 0]]

La multiplicación exterior no crea filas nuevas; solo coloca dos referencias (参照) a una misma lista. grid[0] y grid[1] son el mismo objeto, así que, al reescribir la posición del índice 1 en una, se ve cambiar la misma posición en la otra. Si se piensa que las filas son independientes, se obtiene la forma en que solo cambia una fila. Como la posición reescrita es la del índice 1, tampoco resulta la forma en que la primera posición pasa a ser 5. Para que cada fila sea independiente, escriba [[0] * 3 for _ in range(2)].

Pregunta 27 | Una tupla de un elemento

Compare el tipo de un valor simplemente encerrado entre paréntesis con el de un valor con una coma final. ¿Cuál es la salida del siguiente código?

x = (7)y = (7,)print(type(x).__name__, type(y).__name__)
  1. Se muestran int e int en este orden
  2. Se muestran tuple y tuple en este orden
  3. Se muestran tuple e int en este orden
  4. Se muestran int y tuple en este orden
RespuestaD. Se muestran int y tuple en este orden

Lo que define una tupla (タプル) no son los paréntesis, sino la coma. (7) es solo un entero encerrado entre paréntesis para indicar la precedencia del cálculo, así que su tipo es int, y solo (7,), con una coma final, se convierte en una tupla de un elemento. Si se supone que encerrar algo entre paréntesis lo convierte en tupla, se obtiene la forma en que ambos son tuple; confundir los dos da la forma con el orden invertido o la forma en que ambos son int. Tenga en cuenta que la tupla vacía es una excepción y se escribe (), sin coma.

Pregunta 28 | El contenido de una tupla

Se intentó añadir un elemento a una lista colocada dentro de una tupla. ¿Cuál es el resultado de ejecutar el siguiente código?

t = (1, [2, 3], 4)t[1].append(5)print(t)
  1. Se lanza un TypeError
  2. (1, [2, 3], 4, 5)
  3. (1, [2, 3, 5], 4)
  4. (1, [2, 3], 4)
RespuestaC. (1, [2, 3, 5], 4)

Lo que una tupla (タプル) congela es a qué objeto apunta cada posición, no el contenido de aquello a lo que apunta. t[1] es una lista, y esa lista en sí es mutable, así que se le puede hacer append. Escribir algo como t[1] = [], que asigna a la propia posición de la tupla, lanzaría TypeError, pero aquí no se reemplaza ninguna posición. Como lo que se amplió está dentro de la lista, la longitud de la tupla no aumenta, pero tampoco queda todo completamente sin cambios.

Pregunta 29 | Asignación a rebanadas

Se asignó una lista de longitud distinta a una rebanada de una lista. ¿Cuál es la salida del siguiente código?

x = [1, 2, 3, 4, 5]x[1:3] = [9]print(x)
  1. [1, 9, 4, 5]
  2. [1, 9, 3, 4, 5]
  3. [1, 9, 9, 4, 5]
  4. [1, 2, 9, 4, 5]
RespuestaA. [1, 9, 4, 5]

Asignar a una rebanada es una operación que reemplaza todo el rango especificado por el contenido del lado derecho. x[1:3] se refiere a los 2 elementos 2 y 3, así que se reemplazan por el único elemento 9, y la longitud total se reduce de 5 a 4. Si se piensa que solo se reemplaza un elemento, se obtiene la forma en que la longitud sigue siendo 5, y si se piensa que el lado derecho se estira para ajustarse al ancho, se obtiene la forma en que aparecen dos 9. Desplazar en uno el inicio del rango al leerlo da la forma en que queda el 2. Que el ancho del lado izquierdo y la longitud del lado derecho puedan ser distintos es la característica de la asignación a rebanadas (スライス代入).

Pregunta 30 | Inserción y eliminación

Se realizan una tras otra una asignación a una rebanada de ancho cero y un del. ¿Cuál es el resultado de ejecutar el siguiente código?

y = [1, 2, 3]y[1:1] = [7, 8]del y[0]print(y)
  1. [7, 8, 3]
  2. [1, 7, 8, 3]
  3. [7, 8, 2, 3]
  4. [2, 3, 7, 8]
RespuestaC. [7, 8, 2, 3]

y[1:1] es un rango de ancho cero, así que una asignación a él se convierte en una inserción sin eliminación, y la lista pasa a ser [1, 7, 8, 2, 3]. A continuación, del y[0] elimina el 1 inicial y queda [7, 8, 2, 3]. Si se lee como si durante la inserción también desapareciera uno de los elementos originales, se obtiene la forma 7 8 3, y si se piensa que del elimina otra posición, se obtiene la forma en que permanece el 1 inicial. Malinterpretarlo como si los valores se añadieran al final da la forma en que 2 y 3 van primero. También conviene tener presente que del es una sentencia, así que no tiene valor de retorno, y elimina sin extraer el valor.

Pregunta 31 | El valor predeterminado de get

Se buscó con get una clave que no está en el diccionario. ¿Qué se muestra al ejecutar el siguiente código?

d = {"a": 1, "b": 2}print(d.get("z"), d.get("z", 0))
  1. Se muestran None y 0 en este orden
  2. Se lanza un KeyError en el primero
  3. Se muestran None y None en este orden
  4. Se muestran 0 y 0 en este orden
RespuestaA. Se muestran None y 0 en este orden

get no lanza ninguna excepción cuando falta una clave; devuelve None si se omite el segundo argumento, o ese valor si se proporciona. Así, el primero es None y el segundo es 0. Si se piensa que se devuelve 0 incluso sin segundo argumento, se obtienen ambos como 0, y si se piensa que el segundo argumento se ignora, se obtienen ambos como None. Escribir d["z"] con corchetes daría un KeyError, y get es la herramienta para evitarlo.

Pregunta 32 | setdefault

Se llamó a setdefault tanto con una clave que ya existe como con una que no existe. ¿Cuál es la salida del siguiente código?

d = {"a": 1}print(d.setdefault("a", 99))print(d.setdefault("b", 99))print(d)
  1. Se muestran 99 y 99 y luego {'a': 99, 'b': 99}
  2. Se muestran 1 y 99 y luego {'a': 1, 'b': 99}
  3. Se muestran 1 y None y luego {'a': 1, 'b': None}
  4. Se muestran 1 y 99 y luego {'a': 1}
RespuestaB. Se muestran 1 y 99 y luego {'a': 1, 'b': 99}

setdefault simplemente devuelve el valor existente si la clave está presente, sin cambiar el diccionario. Si la clave falta, inserta el segundo argumento como valor y devuelve ese valor. Así, la primera llamada devuelve el 1 existente y el diccionario queda igual, y la segunda llamada inserta 99 y devuelve 99. Si se piensa que incluso el valor existente se sobrescribe, se obtienen ambos como 99, y si se piensa que no se produce ninguna inserción, se obtiene la forma en que el diccionario no crece. Omitir el segundo argumento hace que el valor insertado sea None, así que la forma con None insertado es el resultado de no escribir el segundo argumento.

Pregunta 33 | Lo que examina in

Compruebe qué examina el operador in en un diccionario. ¿Cuál es la salida del siguiente código?

d = {"x": 1, "y": 2}print("x" in d, 1 in d, 1 in d.values())
  1. Se muestra True False True en este orden
  2. Se muestra True True True en este orden
  3. Se muestra True False False en este orden
  4. Se muestra False True True en este orden
RespuestaA. Se muestra True False True en este orden

in aplicado a un diccionario solo comprueba las claves. "x" es una clave, así que es True; 1 existe como valor pero no es una clave, así que es False. Cuando se quiere comprobar los valores, se usa d.values() como objetivo, lo que aquí da True. Si se piensa que in también examina los valores, todo da True, y si se piensa que values() tampoco examina los valores, el último da False. Intercambiar los papeles de clave y valor da la forma en que el primero es False. Comprobar si una clave existe antes de consultarla con corchetes es el uso habitual.

Pregunta 34 | Claves duplicadas

Se escribió la misma clave dos veces en un literal de diccionario. ¿Cuál es el resultado de ejecutar el siguiente código?

d = {"a": 1, "b": 2, "a": 3}print(d)
  1. {'a': 3, 'b': 2}
  2. {'a': 1, 'b': 2}
  3. {'b': 2, 'a': 3}
  4. {'a': 3, 'b': 3}
RespuestaA. {'a': 3, 'b': 2}

Un literal de diccionario construye sus entradas en orden de izquierda a derecha, así que, si la misma clave aparece dos veces, el valor posterior sobrescribe al anterior. No se produce ningún error ni advertencia. Si se piensa que permanece el que se escribió primero, se obtiene el valor 1 para a. Además, un diccionario conserva el orden de inserción, y una sobrescritura no mueve la posición, así que a se queda en la posición en la que apareció primero. Por lo tanto, tampoco se intercambia el orden de las claves, ni cambia el valor de b como efecto secundario.

Pregunta 35 | Formas de construir un diccionario

Compare un diccionario construido con argumentos de palabra clave y otro construido a partir de una secuencia de pares. ¿Cuál es la salida del siguiente código?

d1 = dict(x=1, y=2)d2 = dict([("x", 1), ("y", 2)])print(d1 == d2)print(d1)
  1. Se muestra False y luego {'x': 1, 'y': 2}
  2. Se muestra True y luego {1: 'x', 2: 'y'}
  3. Se muestra True y luego {'x': 1, 'y': 2}
  4. Se muestra True y luego [('x', 1), ('y', 2)]
RespuestaC. Se muestra True y luego {'x': 1, 'y': 2}

dict puede construir un diccionario tanto a partir de argumentos de palabra clave (キーワード引数) como de una secuencia de pares (clave, valor). Cualquiera de las dos formas de escribirlo produce un diccionario con el mismo contenido, así que la comparación es True. Si se piensa que una forma distinta de construirlo produce algo distinto, la comparación da False. El nombre de un argumento de palabra clave se convierte tal cual en la cadena de la clave, así que la clave y el valor nunca se intercambian. Una vez que ha pasado por dict, ya es un diccionario, así que tampoco se queda como una secuencia de pares.

Pregunta 36 | Llaves vacías

Compare el tipo de unas llaves vacías con el de set(). ¿Cuáles son los dos nombres de tipo que se muestran al ejecutar el siguiente código?

a = {}b = set()print(type(a).__name__, type(b).__name__)
  1. Se muestran dict y dict en este orden
  2. Se muestran set y set en este orden
  3. Se muestran dict y set en este orden
  4. Se muestran set y dict en este orden
RespuestaC. Se muestran dict y set en este orden

{1, 2}, que tiene elementos, se convierte en un conjunto, pero cuando está vacío no se puede decidir si es un diccionario o un conjunto. Python trata este caso como un diccionario, así que {} es un diccionario vacío. Cuando se quiere un conjunto vacío, no queda más remedio que escribir set(). Si se piensa que las llaves siempre significan un conjunto, se obtienen ambos como set, y confundir los dos da el orden invertido. Pensar que incluso set() se convierte en un diccionario da ambos como dict. Como tanto los conjuntos como los diccionarios usan llaves, es fácil confundir esta distinción.

Pregunta 37 | Operaciones de conjuntos

Se realizaron una intersección y una diferencia simétrica sobre dos conjuntos. ¿Cuál es la salida del siguiente código?

s1 = {1, 2, 3, 4}s2 = {3, 4, 5}print(sorted(s1 & s2), sorted(s1 ^ s2))
  1. Se muestran [3, 4] y [1, 2, 3, 4, 5] en este orden
  2. Se muestran [1, 2, 5] y [3, 4] en este orden
  3. Se muestran [3, 4] y [1, 2] en este orden
  4. Se muestran [3, 4] y [1, 2, 5] en este orden
RespuestaD. Se muestran [3, 4] y [1, 2, 5] en este orden

El ampersand (&) es la intersección (積集合), así que quedan 3 y 4, que están en ambos. El acento circunflejo (^) es la diferencia simétrica (対称差), que reúne los elementos que están solo en uno u otro, así que quedan 1 y 2, que solo están en s1, y 5, que solo está en s2, mientras que los comunes 3 y 4 desaparecen. Confundir la diferencia simétrica con la diferencia (差集合) da la forma sin el 5, e intercambiar las dos operaciones invierte el orden de la salida. Confundir la diferencia simétrica con la unión (和集合) da la forma que también incluye 3 y 4. El orden en que se muestra un conjunto no es fijo, así que aquí se comprueba ordenando los resultados con sorted.

Pregunta 38 | Eliminar duplicados

Se pasó por un conjunto una lista con duplicados. ¿Cuál es la salida al ejecutar el siguiente código?

data = [3, 1, 3, 2, 1, 1]print(len(set(data)), sorted(set(data)))
  1. Se muestran 6 y [3, 1, 3, 2, 1, 1] en este orden
  2. Se muestran 6 y [1, 2, 3] en este orden
  3. Se muestran 3 y [3, 1, 2] en este orden
  4. Se muestran 3 y [1, 2, 3] en este orden
RespuestaD. Se muestran 3 y [1, 2, 3] en este orden

Pasar una lista a set elimina los duplicados y quedan los 3 valores distintos 1, 2, 3, así que la longitud es 3. Pasar un conjunto a sorted devuelve una nueva lista ordenada de forma ascendente. Si se piensa que los duplicados permanecen, se obtiene una cuenta de 6. sorted ordena por valor, de menor a mayor, no por el orden original de aparición, así que tampoco queda en el orden en que se vio cada valor por primera vez. El orden en que se muestra un conjunto no tiene significado, así que páselo por sorted cuando quiera tenerlo ordenado.

Pregunta 39 | Una condición para los elementos

Se intentó añadir a un conjunto una tupla y luego una lista, una tras otra. ¿Qué ocurre al ejecutar el siguiente código?

s = set()s.add((1, 2))s.add([3, 4])print(len(s))
  1. Se muestra 1 y la lista se convierte en una tupla
  2. Se lanza un TypeError, porque una lista no puede meterse en un conjunto
  3. Se lanza un ValueError, porque no se pueden mezclar tipos de elementos
  4. Se muestra 2 y ambos elementos entran en el conjunto
RespuestaB. Se lanza un TypeError, porque una lista no puede meterse en un conjunto

Los elementos de un conjunto, y las claves de un diccionario, deben ser hashables (ハッシュ可能). Una tupla (タプル) no puede cambiar su contenido, así que es hashable y puede añadirse, pero una lista puede cambiar su contenido más adelante, así que no es hashable, y se produce un TypeError con un mensaje sobre un tipo no hashable (unhashable type). Suponer que ambos entran da una salida de 2, y suponer que se convierte implícitamente en una tupla da una salida de 1. Mezclar tipos no es en sí un problema, así que el razonamiento de que se produciría un ValueError también es erróneo.

Pregunta 40 | Tres formas de extraer

¿Qué combinación es la adecuada para lo que devuelve cada uno de los métodos de diccionario keys, values e items?

  1. keys devuelve pares de valores, values devuelve pares de claves e items devuelve el número de elementos
  2. keys devuelve pares de claves y valores, values devuelve las claves e items devuelve los valores
  3. keys devuelve los valores, values devuelve las claves e items devuelve pares de valores
  4. keys devuelve las claves, values devuelve los valores e items devuelve pares de claves y valores
RespuestaD. keys devuelve las claves, values devuelve los valores e items devuelve pares de claves y valores

keys devuelve solo las claves, values devuelve solo los valores e items devuelve en orden tuplas (タプル) de (clave, valor). El patrón habitual al recorrer un diccionario es recibir dos variables, como en for k, v in d.items(). Intercambiar los papeles de los tres da explicaciones como que keys devuelve los valores. Lo que devuelve items es una secuencia de elementos, no una cuenta, así que la explicación de que devuelve el número de elementos también es errónea; use len cuando quiera saber la cantidad. Tenga en cuenta que pasar el propio diccionario directamente a for extrae las claves.

Práctica: responda las preguntas de esta página

Es una herramienta de práctica con preguntas en orden aleatorio (funciona si JavaScript está activado). Aun sin ella, puede leer todas las preguntas y explicaciones de arriba.

* Las explicaciones son información con fines de estudio. El contenido y el sistema de los exámenes cambian cada año, así que consulta siempre los anuncios oficiales de la entidad organizadora.

Esta página es una traducción del texto original en japonés. Si hay diferencias entre la traducción y el original, prevalece la versión en japonés. Esta traducción se ha hecho con IA y puede contener errores. Informar de un error de traducción Ver el original en japonés