0% encontró este documento útil (0 votos)
59 vistas

Python Tutorial r66

Este documento presenta una introducción al lenguaje de programación Python. Explica que Python es un potente lenguaje de programación fácil de aprender, con estructuras de datos eficientes y un sistema de programación orientado a objetos simple pero efectivo. También describe algunas de las ventajas de Python como su sintaxis elegante, tipado dinámico y naturaleza interpretada, lo que lo hace ideal para desarrollo rápido de aplicaciones. Finalmente, introduce los conceptos básicos de Python que se explicarán con más detalle en el resto del

Cargado por

nucleone20
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
59 vistas

Python Tutorial r66

Este documento presenta una introducción al lenguaje de programación Python. Explica que Python es un potente lenguaje de programación fácil de aprender, con estructuras de datos eficientes y un sistema de programación orientado a objetos simple pero efectivo. También describe algunas de las ventajas de Python como su sintaxis elegante, tipado dinámico y naturaleza interpretada, lo que lo hace ideal para desarrollo rápido de aplicaciones. Finalmente, introduce los conceptos básicos de Python que se explicarán con más detalle en el resto del

Cargado por

nucleone20
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 82

Introducción a la

Ingeniería en Computación
2021

Tutorial de Python
El oficial con ajustes

Nota del recopilador, ¡este no es el tutorial completo! Dejo afuera momentáneamente algunas
cosas para mantener bajo control el tamaño del apunte. Así como que hay algunas secciones
traducidas que no están presentes en el tutorial oficial. No es exactamente igual.
Las referencias cruzadas en su mayoría no funcionan, aunque el documento apunta mucho a la
documentación oficial del lenguaje.
Tomado casi todo de https://docs.python.org/es/3.7/tutorial/index.html
Python es un lenguaje de programación potente y fácil de aprender. Tiene estructuras de datos
de alto nivel eficientes y un simple pero efectivo sistema de programación orientado a objetos.
La elegante sintaxis de Python y su tipado dinámico, junto a su naturaleza interpretada lo
convierten en un lenguaje ideal para scripting y desarrollo rápido de aplicaciones en muchas
áreas, para la mayoría de plataformas.
El intérprete de Python y la extensiva librería estándar se encuentran disponibles libremente en
código fuente y forma binaria para la mayoría de plataformas desde la Web de Python,
https://www.python.org/, y se pueden distribuir libremente. El mismo sitio contiene
distribuciones y direcciones a muchos módulos de Python de terceras partes, programas,
herramientas y adicionalmente documentación.
Este tutorial no pretende ser exhaustivo y cubrir todas las funcionalidades, o siquiera las más
utilizadas. Solo pretende introducirlos a muchas de las funcionalidades más notables y dar una
idea del estilo y el tipo de lenguaje. Al completarlo, podrás leer y escribir módulos y programas
en Python y estarás listo para aprender sobre varias librerías y módulos descritos en The Python
Standard Library.

r66/2021(MrTín) Página 1 de 82
Introducción a la
Ingeniería en Computación
2021

Abriendo el apetito

Si trabajas mucho con ordenadores, en algún momento encontrarás que hay alguna tarea que
quieres automatizar. Por ejemplo, quizás quieres buscar y remplazar un texto en muchos
ficheros o renombrar y reordenar un montón de imágenes de forma complicada. Quizás lo que
quieres es escribir una pequeña base de datos personalizada, una interfaz gráfica o un juego
simple.
Si eres un desarrollador profesional, quizás quieres trabajar con varias librerías de C/C++/Java
pero encuentras el ciclo de escribir/compilar/probar/recompilar bastante lento. Quizás estás
escribiendo una serie de pruebas para éstas librerías y te parece tedioso escribir el código de
pruebas. O quizás has escrito un programa que puede utilizar un lenguaje como extensión y no
quieres diseñar e implementar un lenguaje entero para tu aplicación.
Python es justo el lenguaje para ti.
Podrías escribir un shell script de Unix o un fichero batch de Windows para alguna de estas
tareas pero los shell scripts son mejores para mover ficheros y cambiar texto no para
aplicaciones con interfaz gráfica o juegos. Podrías escribir un programa en C/C++/Java pero
puede llevar mucho tiempo de desarrollo incluso para tener el primer borrador. Python es más
simple de utilizar, disponible en los sistemas operativos Windows, Mac OS X y Unix y te ayudará
a realizar el trabajo de forma más rápida.
Python es fácil de utilizar siendo un lenguaje de programación real ofreciendo mucha más
estructura y soporte para programas grandes que la que ofrecen shell scripts o ficheros batch.
Por otro lado, Python también ofrece mayor comprobación de errores que C y siendo un
lenguaje de muy alto nivel tiene tipos de datos de alto nivel incorporados como listas flexibles y
diccionarios. Debido a sus tipos de datos más generales, Python es aplicable a más dominios
que Awk o Perl, aunque hay muchas cosas que son tan sencillas en Python como en esos
lenguajes.
Python te permite dividir tu programa en módulos que pueden reutilizarse en otros programas
de Python. Tiene una gran colección de módulos estándar que puedes utilizar como la base de
tus programas o como ejemplos para empezar a aprender Python. Algunos de estos módulos

r66/2021(MrTín) Página 2 de 82
Introducción a la
Ingeniería en Computación
2021

proporcionan cosas como entrada/salida de ficheros, llamadas a sistema, sockets e incluso


interfaces a herramientas de interfaz gráfica como Tk.
Python es un lenguaje interpretado, lo cual puede ahorrarte mucho tiempo durante el desarrollo
ya que no es necesario compilar ni enlazar. El intérprete puede usarse interactivamente, lo que
facilita experimentar con características del lenguaje, escribir programas desechables o probar
funciones cuando se hace desarrollo de programas de abajo hacia arriba. Es también una
calculadora de escritorio práctica.
Python permite escribir programas compactos y legibles. Los programas en Python son
típicamente más cortos que sus programas equivalentes en C, C++ o Java por varios motivos:
• los tipos de datos de alto nivel permiten expresar operaciones complejas en una sola
instrucción;
• la agrupación de instrucciones se hace mediante indentación en vez de llaves de
apertura y cierre;
• no es necesario declarar variables ni argumentos.

Python es extensible: si ya sabes programar en C es fácil añadir nuevas funciones o módulos al


intérprete, ya sea para realizar operaciones críticas a velocidad máxima, o para enlazar
programas de Python con bibliotecas que tal vez sólo estén disponibles de forma binaria (por
ejemplo bibliotecas gráficas específicas de un fabricante). Una vez estés realmente
entusiasmado, puedes enlazar el intérprete Python en una aplicación hecha en C y usarlo como
lenguaje de extensión o de comando para esa aplicación.
Por cierto, el lenguaje recibe su nombre del programa de televisión de la BBC «Monty Python’s
Flying Circus» y no tiene nada que ver con reptiles. Hacer referencias sobre Monty Python en la
documentación no sólo esta permitido, ¡sino que también está bien visto!
Ahora que estás emocionado con Python, querrás verlo en más detalle. Como la mejor forma de
aprender un lenguaje es usarlo, el tutorial te invita a que juegues con el intérprete de Python a
medida que vas leyendo.
En el próximo capítulo se explicará la mecánica de uso del intérprete. Esta es información
bastante mundana, pero es esencial para poder probar los ejemplos que aparecerán más
adelante.

r66/2021(MrTín) Página 3 de 82
Introducción a la
Ingeniería en Computación
2021

El resto del tutorial introduce varias características del lenguaje y el sistema Python a través de
ejemplos, empezando con expresiones, instrucciones y tipos de datos simples, pasando por
funciones y módulos, y finalmente tocando conceptos avanzados como excepciones y clases
definidas por el usuario.

r66/2021(MrTín) Página 4 de 82
Introducción a la
Ingeniería en Computación
2021

Una introducción informal a Python

En los siguientes ejemplos, la entrada y la salida se distinguen por la presencia o ausencia de


prompts (>>> y …): para repetir el ejemplo, escribe todo después del prompt, cuando aparece;
las líneas que no comienzan con un prompt son emitidas desde el intérprete. Ten en cuenta que
un prompt secundario solo en una linea de ejemplo significa que debes escribir una línea en
blanco. Esto se utiliza para finalizar un comando multilínea.
Muchos de los ejemplos de este manual, incluso aquellos ingresados en el prompt interactivo,
incluyen comentarios. Los comentarios en Python comienzan con el carácter numeral, #, y se
extienden hasta el final visible de la línea. Un comentario quizás aparezca al comienzo de la
línea o seguido de espacios en blanco o código, pero no dentro de una cadena de caracteres. Un
carácter numeral dentro de una cadena de caracteres es sólo un carácter numeral. Ya que los
comentarios son para aclarar código y no son interpretados por Python, pueden omitirse cuando
se escriben los ejemplos.
Algunos ejemplos:

# Este es el primer comentario


spam = 1 # y este el segundo
# ... ahora un tercero
text = "# Esto no es un comentario al estar entre comillas!."

Usando Python como una calculadora


Probemos algunos comandos simples de Python. Inicia el intérprete y espere el prompt primario,
>>>. (No debería tardar mucho.)

Números
El intérprete puede utilizarse como una simple calculadora; puedes introducir una expresión y
este escribirá los valores. La sintaxis es sencilla: los operadores +, -, * y /``funcionan
como en la mayoría de los lenguajes (por ejemplo, Pascal o
C); los paréntesis (``()) pueden ser usados para agrupar. Por ejemplo:

>>> 2 + 2

r66/2021(MrTín) Página 5 de 82
Introducción a la
Ingeniería en Computación
2021

4
>>> 50 - 5*6
20
>>> (50 - 5*6) / 4
5.0
>>> 8 / 5 # division always returns a floating point number
1.6

Los números enteros (ej. 2, 4, 20) tienen tipo int, los que tienen una parte fraccionaria (por
ejemplo 5.0, 1.6) tiene el tipo float. Vamos a ver más acerca de los tipos numéricos más
adelante en el tutorial.
La división (/) siempre devuelve un punto flotante. Para hacer floor division y obtener un
resultado entero (descartando cualquier resultado fraccionario) puede usarse el operador //;
para calcular el resto puedes usar %:

>>> 17 / 3 # classic division returns a float


5.666666666666667
>>>
>>> 17 // 3 # floor division discards the fractional part
5
>>> 17 % 3 # the % operator returns the remainder of the division
2
>>> 5 * 3 + 2 # result * divisor + remainder
17

Con Python, es posible usar el operador ** para calcular potencias

>>> 5 ** 2 # 5 squared
25
>>> 2 ** 7 # 2 to the power of 7
128

Debido a que ** tiene una prioridad mayor que `-, -3**2 se interpretará como
-(3**2), por lo tanto dará como resultado -9. Para evitar esto y obtener 9,
puedes usar (-3)**2.

El signo igual (=) se usa para asignar un valor a una variable. Ningún resultado se mostrará
antes del siguiente prompt interactivo:

>>> width = 20

r66/2021(MrTín) Página 6 de 82
Introducción a la
Ingeniería en Computación
2021

>>> height = 5 * 9
>>> width * height
900

Si una variable no está «definida» (no se le ha asignado un valor), al intentar usarla dará un
error:

>>> n # try to access an undefined variable


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined

Hay soporte completo de punto flotante; operadores con operando mezclados convertirán los
enteros a punto flotante:

>>> 4 * 3.75 - 1
14.0

En el modo interactivo, la última expresión impresa se asigna a la variable _. Esto significa que
cuando se está utilizando Python como calculadora, es más fácil seguir calculando, por ejemplo:

>>> tax = 12.5 / 100


>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06

Esta variable debe ser tratada como de sólo lectura por el usuario. No le asignes explícitamente
un valor; crearás una variable local independiente con el mismo nombre enmascarando la
variable con el comportamiento mágico.
Además de int y float, Python admite otros tipos de números, como Decimal y
Fraction. Python también tiene soporte incorporado para complex numbers, y usa el sufijo j
o J para indicar la parte imaginaria (por ejemplo, 3+5j).

r66/2021(MrTín) Página 7 de 82
Introducción a la
Ingeniería en Computación
2021

Cadenas de caracteres
Además de números, Python puede manipular cadenas de texto, las cuales pueden ser
expresadas de distintas formas. Pueden estar encerradas en comillas simples ('...') o
dobles ("...") con el mismo resultado. \ puede ser usado para escapar comillas:

>>> 'spam eggs' # single quotes


'spam eggs'
>>> 'doesn\'t' # use \' to escape the single quote...
"doesn't"
>>> "doesn't" # ...or use double quotes instead
"doesn't"
>>> '"Yes," they said.'
'"Yes," they said.'
>>> "\"Yes,\" they said."
'"Yes," they said.'
>>> '"Isn\'t," they said.'
'"Isn\'t," they said.'

A diferencia de otros lenguajes, caracteres especiales como \n tienen el mismo


significado con simple('...') y dobles ("...") comillas. La única diferencia
entre las dos es que dentro de las comillas simples no existe la necesidad de
escapar " (pero tienes que escapar \') y viceversa.

En el intérprete interactivo, la salida de caracteres está encerrada en comillas y los caracteres


especiales se escapan con barras invertidas. Aunque esto a veces se vea diferente de la
entrada (las comillas que encierran pueden cambiar), las dos cadenas son equivalentes. La
cadena se encierra en comillas dobles si la cadena contiene una comilla simple y ninguna doble,
de lo contrario es encerrada en comillas simples. La función print() produce una salida más
legible, omitiendo las comillas que la encierran e imprimiendo caracteres especiales y
escapados:

>>> '"Isn\'t," they said.'


'"Isn\'t," they said.'
>>> print('"Isn\'t," they said.')
"Isn't," they said.
>>> s = 'First line.\nSecond line.' # \n means newline
>>> s # without print(), \n is included in the output
'First line.\nSecond line.'
>>> print(s) # with print(), \n produces a new line
First line.

r66/2021(MrTín) Página 8 de 82
Introducción a la
Ingeniería en Computación
2021

Second line.

Si no quieres que los caracteres precedidos por \ se interpreten como caracteres especiales,
puedes usar cadenas sin formato agregando una r antes de la primera comilla:

>>> print('C:\some\name') # Acá \n significa linea nueva (!


C:\some
ame
>>> print(r'C:\some\name') # Observá la r antes de la comilla
C:\some\name

Las cadenas de texto literales pueden contener múltiples líneas. Una forma es usar triples
comillas: """...""" o '''...'''. Los fin de línea son incluidos automáticamente, pero
es posible prevenir esto agregando una \ al final de la línea. Por ejemplo:

print("""\
Uso: programita [OPTIONS]
-h Muestra este mensaje de ayuda
-H hostname Hostname al cual conectarse
""")

produce la siguiente salida (tened en cuenta que la línea inicial no está incluida):

Uso: programita [OPTIONS]


-h Muestra este mensaje de ayuda
-H hostname Hostname al cual conectarse

Las cadenas se pueden concatenar (pegar juntas) con el operador + y se pueden repetir con *:

>>> # 3 times 'un', seguido de'ium'


>>> 3 * 'un' + 'ium'
'unununium'

Dos o más cadenas literales (es decir, las encerradas entre comillas) una al lado de la otra se
concatenan automáticamente.

>>> 'Py' 'thon'


'Python'

Esta característica es particularmente útil cuando quieres dividir cadenas largas:

r66/2021(MrTín) Página 9 de 82
Introducción a la
Ingeniería en Computación
2021

>>> text = ('Usar varios strings entre paréntesis '


... 'para dejarlos unidos al final.')
>>> text
'Usar varios string entre paréntesis para dejarlos unidos al final.'

Esto solo funciona con dos literales, no con variables ni expresiones:

>>> prefix = 'Py'


>>> prefix 'thon'
# No es posible concatenar una variable y un literal de string
File "<stdin>", line 1
prefix 'thon'
^
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
File "<stdin>", line 1
('un' * 3) 'ium'
^
SyntaxError: invalid syntax

Si quieres concatenar variables o una variable y un literal, usa +:

>>> prefix + 'thon'


'Python'

Las cadenas de texto se pueden indexar (subíndices), el primer carácter de la cadena tiene el
índice 0. No hay un tipo de dato diferente para los caracteres; un carácter es simplemente una
cadena de longitud uno:

>>> word = 'Python'


>>> word[0] # character in position 0
'P'
>>> word[5] # character in position 5
'n'

Los índices quizás sean números negativos, para empezar a contar desde la derecha:

>>> word[-1] # last character


'n'
>>> word[-2] # second-last character
'o'
>>> word[-6]
'P'

Nota que -0 es lo mismo que 0, los índice negativos comienzan desde -1.

r66/2021(MrTín) Página 10 de 82
Introducción a la
Ingeniería en Computación
2021

Además de los índices, las rebanadas también están soportadas. Mientras que los índices se
utilizar para obtener caracteres individuales, las rebanadas te permiten obtener partes de las
cadenas de texto:

>>> word[0:2] # characters from position 0 (included) to 2 (excluded)


'Py'
>>> word[2:5] # characters from position 2 (included) to 5 (excluded)
'tho'

Nota cómo el inicio siempre se incluye y el final siempre se excluye. Esto asegura que s[:i]
+ s[i:] siempre sea igual a s:

>>> word[:2] + word[2:]


'Python'
>>> word[:4] + word[4:]
'Python'

Los índices de las rebanadas tienen valores por defecto útiles; el valor por defecto para el
primer índice es cero, el valor por defecto para el segundo índice es la longitud de la cadena a
rebanar.

>>> word[:2] # character from the beginning to position 2 (excluded)


'Py'
>>> word[4:] # characters from position 4 (included) to the end
'on'
>>> word[-2:] # characters from the second-last (included) to the end
'on'

Una forma de recordar cómo funcionan las rebanadas es pensar que los índices apuntan entre
caracteres, con el borde izquierdo del primer carácter numerado 0. Luego, el punto derecho del
último carácter de una cadena de n caracteres tiene un índice n, por ejemplo

+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1

La primera fila de números da la posición de los índices 0…6 en la cadena; La segunda fila da los
correspondientes indices negativos. La rebanada desde i hasta j consta de todos los caracteres
entre los bordes etiquetados i y j, respectivamente.

r66/2021(MrTín) Página 11 de 82
Introducción a la
Ingeniería en Computación
2021

Para índices no negativos, la longitud de la rebanada es la diferencia de los índices, si ambos


están dentro de los límites. Por ejemplo, la longitud de word[1:3] es 2.

Intentar usar un índice que es muy grande resultará en un error:

>>> word[42] # the word only has 6 characters


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range

Sin embargo, los índices de rebanadas fuera de rango se manejan satisfactoriamente cuando se
usan para rebanar:

>>> word[4:42]
'on'
>>> word[42:]
''

Las cadenas de Python no se pueden modificar, son immutable. Por eso, asignar a una posición
indexada de la cadena resulta en un error:

>>> word[0] = 'J'


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> word[2:] = 'py'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Si necesitas una cadena diferente, deberías crear una nueva:

>>> 'J' + word[1:]


'Jython'
>>> word[:2] + 'py'
'Pypy'

La función incorporada len() devuelve la longitud de una cadena:

>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34

Ver también

r66/2021(MrTín) Página 12 de 82
Introducción a la
Ingeniería en Computación
2021

Text Sequence Type — str

Las cadenas de texto son ejemplos de tipos secuencias y soportan las operaciones
comunes para esos tipos.
String Methods

Las cadenas de texto soportan una gran cantidad de métodos para transformaciones
básicas y búsqueda.
Formatted string literals

Literales de cadena que tienen expresiones embebidas.


Format String Syntax

Aquí se da información sobre formateo de cadenas de texto con str.format().


printf-style String Formatting

Aquí se describen con más detalle las antiguas operaciones para formateo utilizadas
cuando una cadena de texto está a la izquierda del operador %.

Listas
Python tiene varios tipos de datos compuestos, utilizados para agrupar otros valores. El más
versátil es la lista, la cual puede ser escrita como una lista de valores separados por coma
(ítems) entre corchetes. Las listas pueden contener ítems de diferentes tipos, pero usualmente
los ítems son del mismo tipo.

>>> squares = [1, 4, 9, 16, 25]


>>> squares
[1, 4, 9, 16, 25]

Al igual que las cadenas (y todas las demás tipos integrados sequence), las listas se pueden
indexar y segmentar:

>>> squares[0] # indexing returns the item


1
>>> squares[-1]
25
>>> squares[-3:] # slicing returns a new list
[9, 16, 25]

r66/2021(MrTín) Página 13 de 82
Introducción a la
Ingeniería en Computación
2021

Todas las operaciones de rebanado devuelven una nueva lista que contiene los elementos
pedidos. Esto significa que la siguiente rebanada devuelve una copia nueva (superficial) de la
lista:

>>> squares[:]
[1, 4, 9, 16, 25]

Las listas también admiten operaciones como concatenación:

>>> squares + [36, 49, 64, 81, 100]


[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

A diferencia de las cadenas, que son immutable, las listas son de tipo mutable, es decir, es
posible cambiar su contenido:

>>> cubes = [1, 8, 27, 65, 125] # something's wrong here


>>> 4 ** 3 # the cube of 4 is 64, not 65!
64
>>> cubes[3] = 64 # replace the wrong value
>>> cubes
[1, 8, 27, 64, 125]

También puede agregar nuevos elementos al final de la lista, utilizando el método append()
(vamos a ver más sobre los métodos luego):

>>> cubes.append(216) # add the cube of 6


>>> cubes.append(7 ** 3) # and the cube of 7
>>> cubes
[1, 8, 27, 64, 125, 216, 343]

También es posible asignar a una rebanada, y esto incluso puede cambiar la longitud de la lista
o vaciarla totalmente:

>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']


>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # replace some values
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # now remove them
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']

r66/2021(MrTín) Página 14 de 82
Introducción a la
Ingeniería en Computación
2021

>>> # clear the list by replacing all the elements with an empty list
>>> letters[:] = []
>>> letters
[]

La función predefinida len() también sirve para las listas

>>> letters = ['a', 'b', 'c', 'd']


>>> len(letters)
4

Es posible anidar listas (crear listas que contengan otras listas), por ejemplo:

>>> a = ['a', 'b', 'c']


>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'

Los primeros pasos hacia la programación


Por supuesto, podemos usar Python para tareas más complicadas que sumar dos y dos. Por
ejemplo, podemos escribir una parte inicial de la serie de Fibonacci
<https://en.wikipedia.org/wiki/Fibonacci_number>`_ así:

>>> # Fibonacci series:


... # the sum of two elements defines the next
... a, b = 0, 1
>>> while a < 10:
... print(a)
... a, b = b, a+b
...
0
1
1
2
3
5
8

Este ejemplo introduce varias características nuevas.

r66/2021(MrTín) Página 15 de 82
Introducción a la
Ingeniería en Computación
2021

• La primera línea contiene una asignación múltiple: las variables a y b obtienen


simultáneamente los nuevos valores 0 y 1. En la última línea esto se usa nuevamente,
demostrando que las expresiones de la derecha son evaluadas primero antes de que se
realice cualquiera de las asignaciones. Las expresiones del lado derecho se evalúan de
izquierda a derecha.
• El bucle while se ejecuta mientras la condición (aquí: a < 10) sea verdadera. En
Python, como en C, cualquier valor entero que no sea cero es verdadero; cero es falso. La
condición también puede ser una cadena de texto o una lista, de hecho, cualquier
secuencia; cualquier cosa con una longitud distinta de cero es verdadera, las secuencias
vacías son falsas. La prueba utilizada en el ejemplo es una comparación simple. Los
operadores de comparación estándar se escriben igual que en C: < (menor que), >
(mayor que), == (igual a), <= (menor que o igual a), >= (mayor que o igual a) y !=
(distinto a).
• El cuerpo del bucle está indentado: la indentación es la forma que usa Python para
agrupar declaraciones. En el intérprete interactivo debes teclear un tabulador o
espacio(s) para cada línea indentada. En la práctica vas a preparar entradas más
complicadas para Python con un editor de texto; todos los editores de texto modernos
tienen la facilidad de agregar la indentación automáticamente. Cuando se ingresa una
instrucción compuesta de forma interactiva, se debe finalizar con una línea en blanco
para indicar que está completa (ya que el analizador no puede adivinar cuando tecleaste
la última línea). Nota que cada línea de un bloque básico debe estar sangrada de la
misma forma.
• La función print() escribe el valor de los argumentos que se le dan. Difiere de
simplemente escribir la expresión que se quiere mostrar (como hicimos antes en los
ejemplos de la calculadora) en la forma en que maneja múltiples argumentos, cantidades
de punto flotante y cadenas. Las cadenas de texto son impresas sin comillas y un
espacio en blanco se inserta entre los elementos, así puedes formatear cosas de una
forma agradable:

>>> i = 256*256
>>> print('El valor de i es', i)
El valor de i es is 65536

r66/2021(MrTín) Página 16 de 82
Introducción a la
Ingeniería en Computación
2021

El parámetro nombrado end puede usarse para evitar el salto de linea al final de la salida,
o terminar la salida con una cadena diferente:

>>> a, b = 0, 1
>>> while a < 1000:
... print(a, end=',')
... a, b = b, a+b
...
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,

r66/2021(MrTín) Página 17 de 82
Introducción a la
Ingeniería en Computación
2021

Más herramientas para control de flujo

Ademas de la instrucción while que introdujimos recientemente, Python usa las sentencias de
control conocidas de otros lenguajes de programación pero con algunos giros.

La sentencia if
Tal vez el tipo más conocido de sentencia sea el if. Por ejemplo:

>>> x = int(input("Ingresa un numero entero: "))


Ingresa un numero entero: 42
>>> if x < 0:
... x = 0
... print('Negativo modificado a cero')
... elif x == 0:
... print('Zero')
... elif x == 1:
... print('Single')
... else:
... print('More')
...
More

Puede haber cero o más bloques elif, y el bloque else es opcional. La palabra reservada
“elif’es una abreviación de “else if”, y es útil para evitar un sangrado excesivo. Una secuencia
if … elif … elif … sustituye las sentencias switch o case encontradas en otros
lenguajes.

La sentencia for
La sentencia for en Python difiere un poco de lo que uno puede estar acostumbrado en
lenguajes como C o Pascal. En lugar de siempre iterar sobre una progresión aritmética de
números (como en Pascal) o darle al usuario la posibilidad de definir tanto el paso de la iteración
como la condición de fin (como en C), la sentencia for de Python itera sobre los ítems de
cualquier secuencia (una lista o una cadena de texto), en el orden que aparecen en la secuencia.
Por ejemplo:

>>> # A medir algunas strings:

r66/2021(MrTín) Página 18 de 82
Introducción a la
Ingeniería en Computación
2021

... words = ['cat', 'window', 'defenestrate']


>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12

Si necesitas modificar la secuencia sobre la que estás iterando mientras estás adentro del ciclo
(por ejemplo para borrar algunos ítems), se recomienda que hagas primero una copia. Iterar
sobre una secuencia no hace implícitamente una copia. La notación de rebanada es
especialmente conveniente para esto:

>>> for w in words[:]: # Loop over a slice copy of the entire list.
... if len(w) > 6:
... words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

Con for w in words:, el ejemplo intentaría crear una lista infinita, insertando
defenestrate una y otra vez.

La función range()
Si se necesita iterar sobre una secuencia de números, es apropiado utilizar la función integrada
range(), la cual genera progresiones aritméticas:

>>> for i in range(5):


... print(i)
...
0
1
2
3
4

El valor final dado nunca es parte de la secuencia; range(10) genera 10 valores, los índices
correspondientes para los ítems de una secuencia de longitud 10. Es posible hacer que el rango
empiece con otro número, o especificar un incremento diferente (incluso negativo; algunas
veces se lo llama “paso”):

r66/2021(MrTín) Página 19 de 82
Introducción a la
Ingeniería en Computación
2021

range(5, 10)
5, 6, 7, 8, 9

range(0, 10, 3)
0, 3, 6, 9

range(-10, -100, -30)


-10, -40, -70

Para iterar sobre los índices de una secuencia, puedes combinar range() y len() así:

>>> a = ['Mary', 'had', 'a', 'little', 'lamb']


>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb

En la mayoría de los casos, sin embargo, conviene usar la función enumerate(), mira
Técnicas de iteración.
Algo extraño sucede si muestras un ` range`:

>>> print(range(10))
range(0, 10)

De muchas maneras el objeto devuelto por range() se comporta como si fuera una lista, pero
no lo es. Es un objeto que devuelve los ítems sucesivos de la secuencia deseada cuando iteras
sobre él, pero realmente no construye la lista, ahorrando entonces espacio.
Decimos que tal objeto es iterable; esto es, que se lo puede usar en funciones y construcciones
que esperan algo de lo cual obtener ítems sucesivos hasta que se termine. Hemos visto que la
declaración for es un iterador en ese sentido. La función list() es otra; crea listas a partir
de iterables:

>>> list(range(5))
[0, 1, 2, 3, 4]

Más tarde veremos más funciones que devuelven iterables y que toman iterables como entrada.

r66/2021(MrTín) Página 20 de 82
Introducción a la
Ingeniería en Computación
2021

Las sentencias break, continue, y else en bucles


La sentencia break, como en C, termina el bucle for o while más anidado.

Las sentencias de bucle pueden tener una cláusula`!else` que es ejecutada cuando el lazo
termina, luego de agotar la lista (con for) o cuando la condición se hace falsa (con while),
pero no cuando el bucle se termina con la sentencia break. Se puede ver el ejemplo en el
siguiente bucle, que busca números primos:

>>> for n in range(2, 10):


... for x in range(2, n):
... if n % x == 0:
... print(n, 'equals', x, '*', n//x)
... break
... else:
... # loop fell through without finding a factor
... print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(Sí, este es el código correcto. Fíjate bien: el else pertenece al ciclo for, no al if.)

Cuando se usa con un ciclo, el else tiene más en común con el else de una declaración try
que con el de un if: el else de un try se ejecuta cuando no se genera ninguna excepción, y
el else de un ciclo se ejecuta cuando no hay ningún break. Para más sobre la declaración
try y excepciones, mira Gestionando Excepciones.

La declaración continue, también tomada de C, continua con la siguiente iteración del ciclo:

>>> for num in range(2, 10):


... if num % 2 == 0:
... print("Found an even number", num)
... continue
... print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5

r66/2021(MrTín) Página 21 de 82
Introducción a la
Ingeniería en Computación
2021

Found an even number 6


Found a number 7
Found an even number 8
Found a number 9

La sentencia pass
La sentencia pass no hace nada. Se puede usar cuando una sentencia es requerida por la
sintaxis pero el programa no requiere ninguna acción. Por ejemplo:

>>> while True:


... pass # Busy-wait for keyboard interrupt (Ctrl+C)
...

Se usa normalmente para crear clases en su mínima expresión:

>>> class MyEmptyClass:


... pass
...

Otro lugar donde se puede usar pass es como una marca de lugar para una función o un
cuerpo condicional cuando estás trabajando en código nuevo, lo cual te permite pensar a un
nivel de abstracción mayor. El pass se ignora silenciosamente:

>>> def initlog(*args):


... pass # Remember to implement this!
...

Definiendo funciones
Podemos crear una función que escriba la serie de Fibonacci hasta un límite determinado:

>>> def fib(n): # write Fibonacci series up to n


... """Print a Fibonacci series up to n."""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Now call the function we just defined:
... fib(2000)

r66/2021(MrTín) Página 22 de 82
Introducción a la
Ingeniería en Computación
2021

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

La palabra reservada def se usa para definir funciones. Debe seguirle el nombre de la función y
la lista de parámetros formales entre paréntesis. Las sentencias que forman el cuerpo de la
función empiezan en la línea siguiente, y deben estar con sangría.
La primera sentencia del cuerpo de la función puede ser opcionalmente una cadena de texto
literal; esta es la cadena de texto de documentación de la función, o docstring. (Puedes
encontrar más acerca de docstrings en la sección Cadenas de texto de documentación.).
Existen herramientas que usan las docstrings para producir documentación imprimible o
disponible en línea, o para dejar que los usuarios busquen interactivamente a través del código;
es una buena práctica incluir docstrings en el código que escribes, y hacerlo un buen
hábito.
La ejecución de una función introduce una nueva tabla de símbolos utilizada para las variables
locales de la función. Más precisamente, todas las asignaciones de variables en una función
almacenan el valor en la tabla de símbolos local; mientras que las referencias de variables
primero buscan en la tabla de símbolos local, luego en las tablas de símbolos locales de las
funciones adjuntas, luego en la tabla de símbolos global y finalmente en la tabla de nombres
incorporados. Por lo tanto, a las variables globales y a las variables de funciones adjuntas no se
les puede asignar directamente un valor dentro de una función (a menos que, para variables
globales, se mencionen en una declaración global o, para variables de funciones adjuntas,
que se mencionen en una declaración nonlocal ), aunque pueden ser referenciado.

Los parámetros reales (argumentos) de una función se introducen en la tabla de símbolos local
de la función llamada cuando esta es ejecutada; así, los argumentos son pasados por valor
(dónde el valor es siempre una referencia a un objeto, no el valor del objeto).

En realidad, llamadas por referencia de objeto sería una mejor descripción, ya que
si se pasa un objeto mutable, quien realiza la llamada verá cualquier cambio que
se realice sobre el mismo (por ejemplo ítems insertados en una lista).

Cuando una función llama a otra función, una nueva tabla de símbolos local es creada para esa
llamada.

r66/2021(MrTín) Página 23 de 82
Introducción a la
Ingeniería en Computación
2021

La definición de una función introduce el nombre de la función en la tabla de símbolos actual. El


valor del nombre de la función tiene un tipo que es reconocido por el interprete como una
función definida por el usuario. Este valor puede ser asignado a otro nombre que luego puede
ser usado como una función. Esto sirve como un mecanismo general para renombrar:

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

Viniendo de otros lenguajes, puedes objetar que fib no es una función, sino un procedimiento,
porque no devuelve un valor. De hecho, técnicamente hablando, los procedimientos sin
return sí retornan un valor, aunque uno aburrido. Este valor se llama None (es un nombre
predefinido). El intérprete por lo general no escribe el valor None si va a ser el único valor
escrito. Si realmente se quiere, se puede verlo usando la función print()

>>> fib(0)
>>> print(fib(0))
None

Es simple escribir una función que retorne una lista con los números de la serie de Fibonacci en
lugar de imprimirlos:

>>> def fib2(n): # return Fibonacci series up to n


... """Return a list containing the Fibonacci series up to n."""
... result = []
... a, b = 0, 1
... while a < n:
... result.append(a) # see below
... a, b = b, a+b
... return result
...
>>> f100 = fib2(100) # call it
>>> f100 # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

Este ejemplo, como es usual, demuestra algunas características más de Python:


• La sentencia return devuelve un valor en una función. return sin una expresión
como argumento retorna None. Si se alcanza el final de una función, también se retorna
None.

r66/2021(MrTín) Página 24 de 82
Introducción a la
Ingeniería en Computación
2021

• La sentencia result.append(a) llama a un método del objeto lista result. Un


método es una función que “pertenece” a un objeto y se nombra obj.methodname,
dónde obj es algún objeto (puede ser una expresión), y methodname es el nombre del
método que está definido por el tipo del objeto. Distintos tipos definen distintos métodos.
Métodos de diferentes tipos pueden tener el mismo nombre sin causar ambigüedad. (Es
posible definir tipos de objetos propios, y métodos, usando clases, mira Clases). El
método append() mostrado en el ejemplo está definido para objetos lista; añade un
nuevo elemento al final de la lista. En este ejemplo es equivalente a result =
result + [a], pero más eficiente.

Más sobre definición de funciones


También es posible definir funciones con un número variable de argumentos. Hay tres formas
que pueden ser combinadas.

Argumentos con valores por omisión


La forma más útil es especificar un valor por omisión para uno o más argumentos. Esto crea una
función que puede ser llamada con menos argumentos que los que permite. Por ejemplo:

def ask_ok(prompt, retries=4, reminder='Please try again!'):


while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries < 0:
raise ValueError('invalid user response')
print(reminder)

Esta función puede ser llamada de distintas maneras:


• pasando sólo el argumento obligatorio: ask_ok('Do you really want to
quit?')

• pasando uno de los argumentos opcionales: ask_ok('OK to overwrite the


file?', 2)

r66/2021(MrTín) Página 25 de 82
Introducción a la
Ingeniería en Computación
2021

• o pasando todos los argumentos: ask_ok('OK to overwrite the file?',


2, 'Come on, only yes or no!')

Este ejemplo también introduce la palabra reservada in, la cual prueba si una secuencia
contiene o no un determinado valor.
Los valores por omisión son evaluados en el momento de la definición de la función, en el
ámbito de la definición, entonces:

i = 5

def f(arg=i):
print(arg)

i = 6
f()

…imprimirá `5.

Advertencia importante: El valor por omisión es evaluado solo una vez. Existe una diferencia
cuando el valor por omisión es un objeto mutable como una lista, diccionario, o instancia de la
mayoría de las clases. Por ejemplo, la siguiente función acumula los argumentos que se le
pasan en subsiguientes llamadas:

def f(a, L=[]):


L.append(a)
return L

print(f(1))
print(f(2))
print(f(3))

Imprimirá
[1]
[1, 2]
[1, 2, 3]
Si no se quiere que el valor por omisión sea compartido entre subsiguientes llamadas, se
pueden escribir la función así:

def f(a, L=None):


if L is None:
L = []
L.append(a)

r66/2021(MrTín) Página 26 de 82
Introducción a la
Ingeniería en Computación
2021

return L

Palabras claves como argumentos


Las funciones también puede ser llamadas usando argumentos de palabras clave (o
argumentos nombrados) de la forma kwarg=value. Por ejemplo, la siguiente función:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):


print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")

…acepta un argumento obligatorio (voltage)) y tres argumentos opcionales (state,


action, y type). Esta función puede llamarse de cualquiera de las siguientes maneras:

parrot(1000) # 1 positional argument


parrot(voltage=1000) # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump') # 3 positional
arguments
parrot('a thousand', state='pushing up the daisies') # 1 positional, 1
keyword

…pero estas otras llamadas serían todas inválidas:

parrot() # required argument missing


parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
parrot(110, voltage=220) # duplicate value for the same argument
parrot(actor='John Cleese') # unknown keyword argument

En una llamada a una función, los argumentos nombrados deben seguir a los argumentos
posicionales. Cada uno de los argumentos nombrados pasados deben coincidir con un
argumento aceptado por la función (por ejemplo, actor no es un argumento válido para la
función parrot), y el orden de los mismos no es importante. Esto también se aplica a los
argumentos obligatorios (por ejemplo, parrot(voltage=1000) también es válido).
Ningún argumento puede recibir más de un valor al mismo tiempo. Aquí hay un ejemplo que falla
debido a esta restricción:

>>> def function(a):

r66/2021(MrTín) Página 27 de 82
Introducción a la
Ingeniería en Computación
2021

... pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for keyword argument 'a'

Cuando un parámetro formal final en la forma **name está presente, recibe un diccionario (ver
Mapping Types — dict) conteniendo todos los argumento de palabra clave excepto aquellos que
correspondan al argumento formal. Esto puede ser combinado con el parámetro formal del tipo
*name (descrito en la siguiente sección) el cual recibe una tuple conteniendo los argumentos
posicionales mas alla de la lista de parámetros formal (*name debe estar antes que **name.).
Por ejemplo, si definimos una función de la siguiente manera:

def cheeseshop(kind, *arguments, **keywords):


print("-- Do you have any", kind, "?")
print("-- I'm sorry, we're all out of", kind)
for arg in arguments:
print(arg)
print("-" * 40)
for kw in keywords:
print(kw, ":", keywords[kw])

Puede ser llamada así:

cheeseshop("Limburger", "It's very runny, sir.",


"It's really very, VERY runny, sir.",
shopkeeper="Michael Palin",
client="John Cleese",
sketch="Cheese Shop Sketch")

…Que luego imprimirá:

-- Do you have any Limburger ?


-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch

Se debe notar que el orden en el cual los argumentos nombrados son impresos está garantizado
para coincidir con el orden en el cual fueron provistos en la llamada a la función.

r66/2021(MrTín) Página 28 de 82
Introducción a la
Ingeniería en Computación
2021

Listas de argumentos arbitrarios


Finalmente, la opción menos frecuentemente usada es especificar que una función puede ser
llamada con un número arbitrario de argumentos. Estos argumentos serán organizados en una
tupla (mira Tuplas y secuencias). Antes del número variable de argumentos, cero o más
argumentos normales pueden estar presentes.:

def write_multiple_items(file, separator, *args):


file.write(separator.join(args))

Normalmente estos argumentos de cantidad variables son los últimos en la lista de parámetros
formales, porque toman todo el remanente de argumentos que se pasan a la función. Cualquier
parámetro que suceda luego del *args será “sólo nombrado”, o sea que sólo se pueden usar
como argumentos nombrados y no como posicionales.:

>>> def concat(*args, sep="/"):


... return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'

Desempaquetando una lista de argumentos


La situación inversa ocurre cuando los argumentos ya están en una lista o tupla pero necesitan
ser desempaquetados para llamar a una función que requiere argumentos posicionales
separados. Por ejemplo, la función predefinida range() espera los argumentos inicio y fin. Si
no están disponibles en forma separada, se puede escribir la llamada a la función con el
operador * para desempaquetar argumentos desde una lista o una tupla

>>> list(range(3, 6)) # normal call with separate arguments


[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args)) # call with arguments unpacked from a list
[3, 4, 5]

Del mismo modo, los diccionarios pueden entregar argumentos nombrados con el operador **:

>>> def parrot(voltage, state='a stiff', action='voom'):


... print("-- This parrot wouldn't", action, end=' ')

r66/2021(MrTín) Página 29 de 82
Introducción a la
Ingeniería en Computación
2021

... print("if you put", voltage, "volts through it.", end=' ')
... print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action":
"VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's
bleedin' demised !

Expresiones lambda
Pequeñas funciones anónimas pueden ser creadas con la palabra reservada lambda. Esta
función retorna la suma de sus dos argumentos: lambda a, b: a+b Las funciones
Lambda pueden ser usadas en cualquier lugar donde sea requerido un objeto de tipo función.
Están sintácticamente restringidas a una sola expresión. Semánticamente, son solo azúcar
sintáctica para definiciones normales de funciones. Al igual que las funciones anidadas, las
funciones lambda pueden hacer referencia a variables desde el ámbito que la contiene:

>>> def make_incrementor(n):


... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

El ejemplo anterior muestra el uso de una expresión lambda para retornar una función. Otro uso
es para pasar pequeñas funciones como argumentos

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

Cadenas de texto de documentación (docstrings)


Acá hay algunas convenciones sobre el contenido y formato de las cadenas de texto de
documentación.
La primera línea debe ser siempre un resumen corto y conciso del propósito del objeto. Para ser
breve, no se debe mencionar explícitamente el nombre o tipo del objeto, ya que estos están

r66/2021(MrTín) Página 30 de 82
Introducción a la
Ingeniería en Computación
2021

disponibles de otros modos (excepto si el nombre es un verbo que describe el funcionamiento


de la función). Esta línea debe empezar con una letra mayúscula y terminar con un punto.
Si hay más líneas en la cadena de texto de documentación, la segunda línea debe estar en
blanco, separando visualmente el resumen del resto de la descripción. Las líneas siguientes
deben ser uno o más párrafos describiendo las convenciones para llamar al objeto, efectos
secundarios, etc.
El analizador de Python no quita el sangrado de las cadenas de texto literales multi-líneas,
entonces las herramientas que procesan documentación tienen que quitarlo si así lo desean.
Esto se hace mediante la siguiente convención. La primera línea que no está en blanco
siguiente a la primer línea de la cadena determina la cantidad de sangría para toda la cadena de
documentación. (No podemos usar la primer línea ya que generalmente es adyacente a las
comillas de apertura de la cadena y el sangrado no se nota en la cadena de texto). Los espacios
en blanco «equivalentes» a este sangrado son luego quitados del comienzo de cada línea en la
cadena. No deberían haber líneas con una sangría menor, pero si las hay todos los espacios en
blanco del comienzo deben ser quitados. La equivalencia de espacios en blanco debe ser
verificada luego de la expansión de tabuladores (a 8 espacios, normalmente).
Este es un ejemplo de un docstring multi-línea:

>>> def my_function():


... """Do nothing, but document it.
...
... No, really, it doesn't do anything.
... """
... pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.

No, really, it doesn't do anything.

Anotación de funciones
Las anotaciones de funciones son información completamente opcional sobre los tipos usadas
en funciones definidas por el usuario (ver PEP 484 para más información).
Las anotaciones se almacenan en el atributo __annotations__ de la función como un
diccionario y no tienen efecto en ninguna otra parte de la función. Las anotaciones de los
parámetros se definen luego de dos puntos después del nombre del parámetro, seguido de una

r66/2021(MrTín) Página 31 de 82
Introducción a la
Ingeniería en Computación
2021

expresión que evalúa al valor de la anotación. Las anotaciones de retorno son definidas por el
literal ->, seguidas de una expresión, entre la lista de parámetros y los dos puntos que marcan el
final de la declaración def. El siguiente ejemplo tiene un argumento posicional, uno nombrado,
y el valor de retorno anotado:

>>> def f(ham: str, eggs: str = 'eggs') -> str:


... print("Annotations:", f.__annotations__)
... print("Arguments:", ham, eggs)
... return ham + ' and ' + eggs
...
>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class
'str'>}
Arguments: spam eggs
'spam and eggs'

Intermezzo: Estilo de codificación


Ahora que estás a punto de escribir piezas de Python más largas y complejas, es un buen
momento para hablar sobre estilo de codificación. La mayoría de los lenguajes pueden ser
escritos (o mejor dicho, formateados) con diferentes estilos; algunos son mas fáciles de leer que
otros. Hacer que tu código sea más fácil de leer por otros es siempre una buena idea, y adoptar
un buen estilo de codificación ayuda tremendamente a lograrlo.
Para Python, PEP 8 se erigió como la guía de estilo a la que más proyectos adhirieron; promueve
un estilo de codificación fácil de leer y visualmente agradable. Todos los desarrolladores Python
deben leerlo en algún momento; aquí están extraídos los puntos más importantes:
• Usar sangrías de 4 espacios, no tabuladores.

4 espacios son un buen compromiso entre una sangría pequeña (permite mayor nivel de
sangrado)y una sangría grande (más fácil de leer). Los tabuladores introducen confusión
y es mejor dejarlos de lado.
• Recortar las líneas para que no superen los 79 caracteres.

Esto ayuda a los usuarios con pantallas pequeñas y hace posible tener varios archivos de
código abiertos, uno al lado del otro, en pantallas grandes.
• Usar líneas en blanco para separar funciones y clases, y bloques grandes de código
dentro de funciones.

r66/2021(MrTín) Página 32 de 82
Introducción a la
Ingeniería en Computación
2021

• Cuando sea posible, poner comentarios en una sola línea.

• Usar docstrings.

• Usar espacios alrededor de operadores y luego de las comas, pero no directamente


dentro de paréntesis: a = f(1, 2) + g(3, 4).

• Name your classes and functions consistently; the convention is to use


UpperCamelCase for classes and lowercase_with_underscores for
functions and methods. Always use self as the name for the first method argument
(see Un primer vistazo a las clases for more on classes and methods).
• No uses codificaciones estrafalarias si esperas usar el código en entornos
internacionales. El default de Python, UTF-8, o incluso ASCII plano funcionan bien en la
mayoría de los casos.
• De la misma manera, no uses caracteres no-ASCII en los identificadores si hay incluso
una pequeñísima chance de que gente que hable otro idioma tenga que leer o mantener
el código.

r66/2021(MrTín) Página 33 de 82
Introducción a la
Ingeniería en Computación
2021

Estructuras de datos

Este capítulo describe algunas cosas que ya has aprendido en más detalle y agrega algunas
cosas nuevas también.

Más sobre listas


El tipo de dato lista tiene algunos métodos más. Aquí están todos los métodos de los objetos
lista:

list.append(x)

Agrega un ítem al final de la lista. Equivale a a[len(a):] = [x].

list.extend(iterable)

Extiende la lista agregándole todos los ítems del iterable. Equivale a a[len(a):] =
iterable.

list.insert(i, x)

Inserta un ítem en una posición dada. El primer argumento es el índice del ítem delante del
cual se insertará, por lo tanto a.insert(0, x) inserta al principio de la lista y
a.insert(len(a), x) equivale a a.append(x).

list.remove(x)

Quita el primer ítem de la lista cuyo valor sea x. Lanza un ValueError si no existe tal
ítem.

list.pop([i])

Quita el ítem en la posición dada de la lista y lo devuelve. Si no se especifica un índice,


a.pop() quita y devuelve el último elemento de la lista. (Los corchetes que encierran a i
en la firma del método denotan que el parámetro es opcional, no que deberías escribir
corchetes en esa posición. Verás esta notación con frecuencia en la Referencia de la
Biblioteca de Python.)

r66/2021(MrTín) Página 34 de 82
Introducción a la
Ingeniería en Computación
2021

list.clear()

Elimina todos los elementos de la lista. Equivalente a del a[:].

list.index(x[, start[, end]])

Devuelve el índice basado en cero del primer elemento cuyo valor sea igual a x. Lanza una
excepción ValueError si no existe tal elemento.
Los argumentos opcionales start y end son interpretados como la notación de rebanadas y
se usan para limitar la búsqueda a un segmento particular de la lista. El índice devuelto se
calcula de manera relativa al inicio de la secuencia completa en lugar de con respecto al
argumento start.

list.count(x)

Devuelve el número de veces que x aparece en la lista.

list.sort(key=None, reverse=False)

Ordena los elementos de la lista in situ (los argumentos pueden ser usados para
personalizar el orden de la lista, ver sorted() para su explicación).

list.reverse()

Invierte los elementos de la lista in situ.

list.copy()

Devuelve una copia superficial de la lista. Equivalente a a[:].


Un ejemplo que usa la mayoría de los métodos de la lista:

>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']


>>> fruits.count('apple')
2
>>> fruits.count('tangerine')
0
>>> fruits.index('banana')
3
>>> fruits.index('banana', 4) # Find next banana starting a position 4
6
>>> fruits.reverse()

r66/2021(MrTín) Página 35 de 82
Introducción a la
Ingeniería en Computación
2021

>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits
['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits
['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop()
'pear'

Quizás hayas notado que métodos como insert`, remove o sort que únicamente modifican
la lista no tienen impreso un valor de retorno – devuelven el valor por defecto None.

Otros lenguajes podrían devolver un objeto mutado, que permite encadenamiento


de métodos como d->insert("a")->remove("b")->sort();.

Esto es un principio de diseño para todas las estructuras de datos mutables en Python.

Usando listas como pilas


Los métodos de lista hacen que resulte muy fácil usar una lista como una pila, donde el último
elemento añadido es el primer elemento retirado («último en entrar, primero en salir»). Para
agregar un elemento a la cima de la pila, utiliza append(). Para retirar un elemento de la cima
de la pila, utiliza pop() sin un índice explícito. Por ejemplo:

>>> stack = [3, 4, 5]


>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]

r66/2021(MrTín) Página 36 de 82
Introducción a la
Ingeniería en Computación
2021

Usando listas como colas


También es posible usar una lista como una cola, donde el primer elemento añadido es el primer
elemento retirado («primero en entrar, primero en salir»); sin embargo, las listas no son
eficientes para este propósito. Agregar y sacar del final de la lista es rápido, pero insertar o sacar
del comienzo de una lista es lento (porque todos los otros elementos tienen que ser
desplazados por uno).
Para implementar una cola, utiliza collections.deque el cual fue diseñado para añadir y
quitar de ambas puntas de forma rápida. Por ejemplo:

>>> from collections import deque


>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])

Comprensión de listas
Las comprensiones de listas ofrecen una manera concisa de crear listas. Sus usos comunes son
para hacer nuevas listas donde cada elemento es el resultado de algunas operaciones aplicadas
a cada miembro de otra secuencia o iterable, o para crear un segmento de la secuencia de esos
elementos para satisfacer una condición determinada.
Por ejemplo, asumamos que queremos crear una lista de cuadrados, como:

>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Nota que esto crea (o sobreescribe) una variable llamada x que sigue existiendo luego de que el
bucle haya terminado. Podemos calcular la lista de cuadrados sin ningun efecto secundario
haciendo:

r66/2021(MrTín) Página 37 de 82
Introducción a la
Ingeniería en Computación
2021

squares = list(map(lambda x: x**2, range(10)))

o, un equivalente:

squares = [x**2 for x in range(10)]

que es más conciso y legible.


Una lista de comprensión consiste de corchetes rodeando una expresión seguida de la
declaración for y luego cero o más declaraciones for o if. El resultado será una nueva lista
que sale de evaluar la expresión en el contexto de los for o if que le siguen. Por ejemplo, esta
lista de comprensión combina los elementos de dos listas si no son iguales:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]


[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

y es equivalente a:

>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Notá como el orden de los for y if es el mismo en ambos pedacitos de código.

Si la expresión es una tupla (como el (x, y) en el ejemplo anterior), debe estar entre
paréntesis.

>>> vec = [-4, -2, 0, 2, 4]


>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']

r66/2021(MrTín) Página 38 de 82
Introducción a la
Ingeniería en Computación
2021

>>> [weapon.strip() for weapon in freshfruit]


['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
File "<stdin>", line 1, in <module>
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Las comprensiones de listas pueden contener expresiones complejas y funciones anidadas:

>>> from math import pi


>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

Listas por comprensión anidadas


La expresión inicial de una comprensión de listas puede ser cualquier expresión arbitraria,
incluyendo otra comprensión de listas.
Considerá el siguiente ejemplo de una matriz de 3x4 implementada como una lista de tres listas
de largo 4:

>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]

La siguiente comprensión de lista transpondrá las filas y columnas:

>>> [[row[i] for row in matrix] for i in range(4)]


[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

Como vimos en la sección anterior, la lista de comprensión anidada se evalua en el contexto del
for que lo sigue, por lo que este ejemplo equivale a:

r66/2021(MrTín) Página 39 de 82
Introducción a la
Ingeniería en Computación
2021

>>> transposed = []
>>> for i in range(4):
... transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

el cual, a la vez, es lo mismo que:

>>> transposed = []
>>> for i in range(4):
... # the following 3 lines implement the nested listcomp
... transposed_row = []
... for row in matrix:
... transposed_row.append(row[i])
... transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

En el mundo real, deberías preferir funciones predefinidas a declaraciones con flujo complejo. La
función zip() haría un buen trabajo para este caso de uso:

>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

Ver Desempaquetando una lista de argumentos para detalles en el asterisco de esta línea.

La instrucción del
Hay una manera de quitar un ítem de una lista dado su índice en lugar de su valor: la instrucción
del. Esta es diferente del método pop(), el cual devuelve un valor. La instrucción del
también puede usarse para quitar secciones de una lista o vaciar la lista completa (lo que
hacíamos antes asignando una lista vacía a la sección). Por ejemplo:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]


>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a

r66/2021(MrTín) Página 40 de 82
Introducción a la
Ingeniería en Computación
2021

[]

del puede usarse también para eliminar variables:

>>> del a

Hacer referencia al nombre a de aquí en más es un error (al menos hasta que se le asigne otro
valor). Veremos otros usos para del más adelante.

Tuplas y secuencias
Vimos que las listas y cadenas tienen propiedades en común, como el indizado y las
operaciones de seccionado. Estas son dos ejemplos de datos de tipo secuencia (ver Sequence
Types — list, tuple, range). Como Python es un lenguaje en evolución, otros datos de tipo
secuencia pueden agregarse. Existe otro dato de tipo secuencia estándar: la tupla.
Una tupla consiste de un número de valores separados por comas, por ejemplo:

>>> t = 12345, 54321, 'hello!'


>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

Como puedes ver, en la salida las tuplas siempre se encierran entre paréntesis, para que las
tuplas anidadas puedan interpretarse correctamente; pueden ingresarse con o sin paréntesis,
aunque a menudo los paréntesis son necesarios de todas formas (si la tupla es parte de una
expresión más grande). No es posible asignar a los ítems individuales de una tupla, pero sin
embargo sí se puede crear tuplas que contengan objetos mutables, como las listas.

r66/2021(MrTín) Página 41 de 82
Introducción a la
Ingeniería en Computación
2021

A pesar de que las tuplas puedan parecerse a las listas, frecuentemente se utilizan en distintas
situaciones y para distintos propósitos. Las tuplas son inmutables y normalmente contienen una
secuencia heterogénea de elementos que son accedidos al desempaquetar (ver más adelante
en esta sección) o indizar (o incluso acceder por atributo en el caso de las namedtuples).
Las listas son mutables, y sus elementos son normalmente homogéneos y se acceden iterando
a la lista.
Un problema particular es la construcción de tuplas que contengan 0 o 1 ítem: la sintaxis
presenta algunas peculiaridades para estos casos. Las tuplas vacías se construyen mediante un
par de paréntesis vacío; una tupla con un ítem se construye poniendo una coma a continuación
del valor (no alcanza con encerrar un único valor entre paréntesis). Feo, pero efectivo. Por
ejemplo:

>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)

La declaración t = 12345, 54321, 'hola!' es un ejemplo de empaquetado de


tuplas: los valores 12345, 54321 y 'hola!' se empaquetan juntos en una tupla. La
operación inversa también es posible:
>>> x, y, z = t

Esto se llama, apropiadamente, desempaquetado de secuencias, y funciona para cualquier


secuencia en el lado derecho del igual. El desempaquetado de secuencias requiere que la
cantidad de variables a la izquierda del signo igual sea el tamaño de la secuencia. Notá que la
asignación múltiple es en realidad sólo una combinación de empaquetado de tuplas y
desempaquetado de secuencias.

r66/2021(MrTín) Página 42 de 82
Introducción a la
Ingeniería en Computación
2021

Conjuntos
Python también incluye un tipo de dato para conjuntos. Un conjunto es una colección no
ordenada y sin elementos repetidos. Los usos básicos de éstos incluyen verificación de
pertenencia y eliminación de entradas duplicadas. Los conjuntos también soportan operaciones
matemáticas como la unión, intersección, diferencia, y diferencia simétrica.
Las llaves o la función set() pueden usarse para crear conjuntos. Notá que para crear un
conjunto vacío tenés que usar set(), no {}; esto último crea un diccionario vacío, una
estructura de datos que discutiremos en la sección siguiente.
Una pequeña demostración:

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}


>>> print(basket) # show that duplicates have been
removed
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket # fast membership testing
True
>>> 'crabgrass' in basket
False

>>> # Demonstrate set operations on unique letters from two words


...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # letters in both a and b
{'a', 'c'}
>>> a ^ b # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}

De forma similar a las comprensiones de listas, está también soportada la comprensión de


conjuntos:

>>> a = {x for x in 'abracadabra' if x not in 'abc'}


>>> a
{'r', 'd'}

r66/2021(MrTín) Página 43 de 82
Introducción a la
Ingeniería en Computación
2021

Diccionarios
Otro tipo de dato útil incluído en Python es el diccionario (ver Mapping Types — dict). Los
diccionarios se encuentran a veces en otros lenguajes como «memorias asociativas» o
«arreglos asociativos». A diferencia de las secuencias, que se indexan mediante un rango
numérico, los diccionarios se indexan con claves, que pueden ser cualquier tipo inmutable; las
cadenas y números siempre pueden ser claves. Las tuplas pueden usarse como claves si
solamente contienen cadenas, números o tuplas; si una tupla contiene cualquier objeto mutable
directa o indirectamente, no puede usarse como clave. No podés usar listas como claves, ya que
las listas pueden modificarse usando asignación por índice, asignación por sección, o métodos
como append() y extend().

Es mejor pensar en un diccionario como un conjunto de pares clave:valor con el requerimiento


de que las claves sean únicas (dentro de un diccionario). Un par de llaves crean un diccionario
vacío: {}. Colocar una lista de pares clave:valor separada por comas dentro de las llaves
agrega, de inicio, pares clave:valor al diccionario; esta es, también, la forma en que los
diccionarios se muestran en la salida.
Las operaciones principales sobre un diccionario son guardar un valor con una clave y extraer
ese valor dada la clave. También es posible borrar un par clave:valor con del. Si usás una clave
que ya está en uso para guardar un valor, el valor que estaba asociado con esa clave se pierde.
Es un error extraer un valor usando una clave no existente.
Ejecutando list(d) en un diccionario devolverá una lista con todas las claves usadas en el
diccionario, en el oden de inserción (si deseas que esté ordenada simplemente usa
sorted(d) en su lugar). Para comprobar si una clave está en el diccionario usa la palabra
clave in.

Un pequeño ejemplo de uso de un diccionario:

>>> tel = {'jack': 4098, 'sape': 4139}


>>> tel['guido'] = 4127
>>> tel
{'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'jack': 4098, 'guido': 4127, 'irv': 4127}

r66/2021(MrTín) Página 44 de 82
Introducción a la
Ingeniería en Computación
2021

>>> list(tel)
['jack', 'guido', 'irv']
>>> sorted(tel)
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False

El constructor dict() crea un diccionario directamente desde secuencias de pares clave-


valor:

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])


{'sape': 4139, 'guido': 4127, 'jack': 4098}

Además, las comprensiones de diccionarios se pueden usar para crear diccionarios desde
expresiones arbitrarias de clave y valor:

>>> {x: x**2 for x in (2, 4, 6)}


{2: 4, 4: 16, 6: 36}

Cuando las claves son cadenas simples, a veces resulta más fácil especificar los pares usando
argumentos por palabra clave:

>>> dict(sape=4139, guido=4127, jack=4098)


{'sape': 4139, 'guido': 4127, 'jack': 4098}

Técnicas de iteración
Cuando iteramos sobre diccionarios, se pueden obtener al mismo tiempo la clave y su valor
correspondiente usando el método items().

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}


>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave

Cuando se itera sobre una secuencia, se puede obtener el índice de posición junto a su valor
correspondiente usando la función enumerate().

r66/2021(MrTín) Página 45 de 82
Introducción a la
Ingeniería en Computación
2021

>>> for i, v in enumerate(['tic', 'tac', 'toe']):


... print(i, v)
...
0 tic
1 tac
2 toe

Para iterar sobre dos o más secuencias al mismo tiempo, los valores pueden emparejarse con la
función zip().

>>> questions = ['name', 'quest', 'favorite color']


>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print('What is your {0}? It is {1}.'.format(q, a))
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.

Para iterar sobre una secuencia en orden inverso, se especifica primero la secuencia al derecho
y luego se llama a la función reversed().

>>> for i in reversed(range(1, 10, 2)):


... print(i)
...
9
7
5
3
1

Para iterar sobre una secuencia ordenada, se utiliza la función sorted() la cual devuelve una
nueva lista ordenada dejando a la original intacta.

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']


>>> for f in sorted(set(basket)):
... print(f)
...
apple
banana
orange
pear

A veces uno intenta cambiar una lista mientras la está iterando; sin embargo, a menudo es más
simple y seguro crear una nueva lista:

r66/2021(MrTín) Página 46 de 82
Introducción a la
Ingeniería en Computación
2021

>>> import math


>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
... if not math.isnan(value):
... filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]

Más acerca de condiciones


Las condiciones usadas en las instrucciones while e if pueden contener cualquier operador,
no sólo comparaciones.
Los operadores de comparación in y not in verifican si un valor está (o no está) en una
secuencia. Los operadores is e is not comparan si dos objetos son realmente el mismo
objeto; esto es significativo sólo para objetos mutables como las listas. Todos los operadores de
comparación tienen la misma prioridad, la cual es menor que la de todos los operadores
numéricos.
Las comparaciones pueden encadenarse. Por ejemplo, a < b == c verifica si a es menor
que b y además si b es igual a c.

Las comparaciones pueden combinarse mediante los operadores booleanos and y or, y el
resultado de una comparación (o de cualquier otra expresión booleana) puede negarse con
not. Estos tienen prioridades menores que los operadores de comparación; entre ellos not
tiene la mayor prioridad y or la menor, o sea que A and not B or C equivale a (A and
(not B)) or C. Como siempre, los paréntesis pueden usarse para expresar la composición
deseada.
Los operadores booleanos and y or son los llamados operadores cortocircuito: sus
argumentos se evalúan de izquierda a derecha, y la evaluación se detiene en el momento en que
se determina su resultado. Por ejemplo, si A y C son verdaderas pero B es falsa, en A and B
and C no se evalúa la expresión C. Cuando se usa como un valor general y no como un
booleano, el valor devuelto de un operador cortocircuito es el último argumento evaluado.
Es posible asignar el resultado de una comparación u otra expresión booleana a una variable.
Por ejemplo,

r66/2021(MrTín) Página 47 de 82
Introducción a la
Ingeniería en Computación
2021

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'


>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'

Notá que en Python, a diferencia de C, la asignación no puede ocurrir dentro de expresiones. Los
programadores de C pueden renegar por esto, pero es algo que evita un tipo de problema
común encontrado en programas en C: escribir = en una expresión cuando lo que se quiere
escribir es ==.

Comparando secuencias y otros tipos


Las secuencias pueden compararse con otros objetos del mismo tipo de secuencia. La
comparación usa orden lexicográfico: primero se comparan los dos primeros ítems, si son
diferentes esto ya determina el resultado de la comparación; si son iguales, se comparan los
siguientes dos ítems, y así sucesivamente hasta llegar al final de alguna de las secuencias. Si
dos ítems a comparar son ambos secuencias del mismo tipo, la comparación lexicográfica es
recursiva. Si todos los ítems de dos secuencias resultan iguales, se considera que las
secuencias son iguales.

(1, 2, 3) < (1, 2, 4)


[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)

Observá que comparar objetos de diferentes tipos con < o > es legal siempre y cuando los
objetas tenga los métodos de comparación apropiados. Por ejemplo, los tipos de números
mezclados son comparados de acuerdo a su valor numérico, o sea 0 es igual a 0.0, etc. Si no es
el caso, en lugar de proveer un ordenamiento arbitrario, el intérprete generará una excepción
TypeError.

r66/2021(MrTín) Página 48 de 82
Introducción a la
Ingeniería en Computación
2021

Errores y excepciones

Hasta ahora los mensajes de error apenas habían sido mencionados, pero si has probado los
ejemplos anteriores probablemente hayas visto algunos. Hay (al menos) dos tipos diferentes de
errores: errores de sintaxis y excepciones.

Errores de sintaxis
Los errores de sintaxis, también conocidos como errores de interpretación, son quizás el tipo de
queja más común que tenés cuando todavía estás aprendiendo Python:

>>> while True print('Hello world')


File "<stdin>", line 1
while True print('Hello world')
^
SyntaxError: invalid syntax

El intérprete reproduce la línea responsable del error y muestra una pequeña “flecha” que
apunta al primer lugar donde se detectó el error. El error ha sido provocado (o al menos
detectado) en el elemento que precede a la flecha: en el ejemplo, el error se detecta en la
función print(), ya que faltan dos puntos (':') antes del mismo. Se muestran el nombre del
archivo y el número de línea para que sepas dónde mirar en caso de que la entrada venga de un
programa.

Excepciones
Incluso si una declaración o expresión es sintácticamente correcta, puede generar un error
cuando se intenta ejecutar. Los errores detectados durante la ejecución se llaman excepciones,
y no son incondicionalmente fatales: pronto aprenderás a gestionarlos en programas Python. Sin
embargo, la mayoría de las excepciones no son gestionadas por el código, y resultan en
mensajes de error como los mostrados aquí:

>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4 + spam*3

r66/2021(MrTín) Página 49 de 82
Introducción a la
Ingeniería en Computación
2021

Traceback (most recent call last):


File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly

La última línea de los mensajes de error indica qué ha sucedido. Hay excepciones de diferentes
tipos, y el tipo se imprime como parte del mensaje: los tipos en el ejemplo son:
ZeroDivisionError, NameError y TypeError. La cadena mostrada como tipo de la
excepción es el nombre de la excepción predefinida que ha ocurrido. Esto es válido para todas
las excepciones predefinidas del intérprete, pero no tiene por que ser así para excepciones
definidas por el usuario (aunque es una convención útil). Los nombres de las excepciones
estándar son identificadores incorporados al intérprete (no son palabras clave reservadas).
El resto de la línea provee información basado en el tipo de la excepción y qué la causó.
La parte anterior del mensaje de error muestra el contexto donde ha sucedido la excepción, en
formato de traza de error. En general, contiene una traza de error que lista líneas de código
fuente; sin embargo, no mostrará líneas leídas desde la entrada estándar.
Built-in Exceptions lista las excepciones predefinidas y sus significados.

Gestionando Excepciones
Es posible escribir programas que gestionen determinadas excepciones. Mirá el siguiente
ejemplo, que le pide al usuario una entrada hasta que ingrese un entero válido, pero permite al
usuario interrumpir el programa (usando Control-C o lo que sea que el sistema operativo
soporte); notá que una interrupción generada por el usuario se señaliza generando la excepción
KeyboardInterrupt.

>>> while True:


... try:
... x = int(input("Please enter a number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
...

La declaración try funciona de la siguiente manera:

r66/2021(MrTín) Página 50 de 82
Introducción a la
Ingeniería en Computación
2021

• Primero, se ejecuta la cláusula try (la(s) linea(s) entre las palabras reservadas try y la
except).

• Si no ocurre ninguna excepción, la cláusula except se omite y la ejecución de la cláusula


try finaliza.

• Si ocurre una excepción durante la ejecución de la cláusula try el resto de la cláusula se


omite. Entonces, si el tipo de excepción coincide con la excepción indicada después de la
except, la cláusula except se ejecuta, y la ejecución continua después de la try.

• Si ocurre una excepción que no coincide con la indicada en la cláusula except se pasa a
los try más externos; si no se encuentra un gestor, se genera una unhandled exception
(excepción no gestionada) y la ejecución se interrumpen con un mensaje como el que se
muestra arriba.
Una declaración try puede tener más de un except, para especificar gestores para distintas
excepciones. A lo sumo un bloque será ejecutado. Sólo se gestionarán excepciones que ocurren
en el correspondiente try, no en otros bloques del mismo try. Un except puede nombrar
múltiples excepciones usando paréntesis, por ejemplo:

... except (RuntimeError, TypeError, NameError):


... pass

Una clase en una cláusula except es compatible con una excepción si la misma está en la
misma clase o una clase base de la misma (pero no de la otra manera — una clausula except
listando una clase derivada no es compatible con una clase base). Por ejemplo, el siguiente
código imprimirá B, C y D, en ese orden:

class B(Exception):
pass

class C(B):
pass

class D(C):
pass

for cls in [B, C, D]:


try:
raise cls()
except D:

r66/2021(MrTín) Página 51 de 82
Introducción a la
Ingeniería en Computación
2021

print("D")
except C:
print("C")
except B:
print("B")

Nótese que si las cláusulas except estuvieran invertidas (con except B primero), habría
impreso B, B, B — se usa la primera cláusula except coincidente.
El último except puede omitir el nombre de la excepción capturada y servir como comodín.
Usá esto con extremo cuidado, ya que de esta manera es fácil ocultar un error real de
programación. También puede usarse para mostrar un mensaje de error y luego re-generar la
excepción (permitiéndole al que llama, gestionar también la excepción):

import sys

try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise

Las declaraciones try … except tienen un bloque else opcional, el cual, cuando está
presente, debe seguir a los except. Es útil para aquel código que debe ejecutarse si el bloque try
no genera una excepción. Por ejemplo:

for arg in sys.argv[1:]:


try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()

El uso de la cláusula else es mejor que agregar código adicional en la cláusula try porque
evita capturar accidentalmente una excepción que no fue generada por el código que está
protegido por la declaración try … except.

r66/2021(MrTín) Página 52 de 82
Introducción a la
Ingeniería en Computación
2021

Cuando ocurre una excepción, puede tener un valor asociado, también conocido como el
argumento de la excepción. La presencia y el tipo de argumento depende del tipo de excepción.
El except puede especificar una variable luego del nombre de excepción. La variable se
vincula a una instancia de excepción con los argumentos almacenados en instance.args.
Por conveniencia, la instancia de excepción define __str__() para que se pueda mostrar los
argumentos directamente, sin necesidad de hacer referencia a .args. También se puede
instanciar la excepción primero, antes de generarla, y agregarle los atributos que se desee:

>>> try:
... raise Exception('spam', 'eggs')
... except Exception as inst:
... print(type(inst)) # the exception instance
... print(inst.args) # arguments stored in .args
... print(inst) # __str__ allows args to be printed directly,
... # but may be overridden in exception subclasses
... x, y = inst.args # unpack args
... print('x =', x)
... print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

Si una excepción tiene argumentos, estos se imprimen como en la parte final (el “detalle”) del
mensaje para las excepciones no gestionadas (“Unhandled exception”).
Los gestores de excepciones no gestionan solamente las excepciones que ocurren en el bloque
try, también gestionan las excepciones que ocurren dentro de las funciones que se llaman
(inclusive indirectamente) dentro del bloque try. Por ejemplo:

>>> def this_fails():


... x = 1/0
...
>>> try:
... this_fails()
... except ZeroDivisionError as err:
... print('Handling run-time error:', err)
...
Handling run-time error: division by zero

r66/2021(MrTín) Página 53 de 82
Introducción a la
Ingeniería en Computación
2021

Lanzando excepciones
La declaración raise permite al programador forzar a que ocurra una excepción específica.
Por ejemplo:

>>> raise NameError('HiThere')


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: HiThere

El único argumento de raise indica la excepción a generarse. Tiene que ser o una instancia de
excepción, o una clase de excepción (una clase que hereda de Exception). Si se pasa una
clase de excepción, la misma será instanciada implícitamente llamando a su constructor sin
argumentos:
raise ValueError # shorthand for 'raise ValueError()'

Si necesitás determinar si una excepción fue lanzada pero no querés gestionarla, una versión
simplificada de la instrucción raise te permite relanzarla:

>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
... raise
...
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
NameError: HiThere

Encadenando Excepciones
La sentencia raise permite un opcional from que permite encadenar excepciones: Por
ejemplo:

# exc debe ser una instancia de Exception o None.


raise RuntimeError from exc

Esto es útil cuando estamos transformando excepciones, por ejemplo:

>>> def func():

r66/2021(MrTín) Página 54 de 82
Introducción a la
Ingeniería en Computación
2021

... raise IOError


...
>>> try:
... func()
... except IOError as exc:
... raise RuntimeError('Failed to open database') from exc
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in func
OSError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):


File "<stdin>", line 4, in <module>
RuntimeError: Failed to open database

El encadenamiento de excepciones ocurre automaticamente cuando una excepcion es lanzada


dentro de un bloque except o finally. Este comportamiento se puede desactivar
utilizando la convención from None:

try:
open('database.sqlite')
except IOError:
raise RuntimeError from None
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError

Para más información acerca de las mecánicas de encadenamiento de excepciones, ver


Excepciones incorporadas.

Excepciones definidas por el usuario


Los programas pueden nombrar sus propias excepciones creando una nueva clase excepción
(mirá Clases para más información sobre las clases de Python). Las excepciones, típicamente,
deberán derivar de la clase Exception, directa o indirectamente.

Las clases de Excepción pueden ser definidas de la misma forma que cualquier otra clase, pero
es habitual mantenerlas lo más simples posible, a menudo ofreciendo solo un número de
atributos con información sobre el error que leerán los gestores de la excepción. Al crear un
módulo que puede lanzar varios errores distintos, una práctica común es crear una clase base

r66/2021(MrTín) Página 55 de 82
Introducción a la
Ingeniería en Computación
2021

para excepciones definidas en ese módulo y extenderla para crear clases excepciones
específicas para distintas condiciones de error:

class Error(Exception):
"""Base class for exceptions in this module."""
pass

class InputError(Error):
"""Exception raised for errors in the input.

Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""

def __init__(self, expression, message):


self.expression = expression
self.message = message

class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.

Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""

def __init__(self, previous, next, message):


self.previous = previous
self.next = next
self.message = message

La mayoría de las excepciones se definen con nombres acabados en «Error», de manera similar
a la nomenclatura de las excepciones estándar.
Muchos módulos estándar definen sus propias excepciones para reportar errores que pueden
ocurrir en funciones propias. Se puede encontrar más información sobre clases en el capítulo
Clases.

Definiendo Acciones de Limpieza


La declaración try tiene otra cláusula opcional cuyo propósito es definir acciones de limpieza
que serán ejecutadas bajo ciertas circunstancias. Por ejemplo:

r66/2021(MrTín) Página 56 de 82
Introducción a la
Ingeniería en Computación
2021

>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
KeyboardInterrupt
Traceback (most recent call last):
File "<stdin>", line 2, in <module>

Si la clausula finally esta presente, esta se ejecutará inmediatamente antes del bloque
try. La clausula finally se ejecuta antes de try por esta necesita generar una excepcion
o relanzarla.
Aquí algunos casos mas complejos de cuando se puede generar una excpcion:
• Si se lanza una excepción dentro del bloque try, la excepcion puede ser gestionada por
un bloque except. Pero si la misma no es tratada por un bloque except, la
excepción es vuelta a lanzar luego de que el bloque finally ha sido ejecutado.

• Es posible que se produzca una excepcion dentro de los bloques except o else.
Nuevamente, la excepción es vuelta a lanzar luego de que el bloque finally ha sido
ejecutado.
• Si el bloque try alcanza una instrucción break, continue o return, el bloque
finally se ejecutará inmediatamente antes que dichas instrucciones.

• Si una clasula finally incluye un return, el valor retornado será el que se encuentre
generado por el return del bloque finally y no el valor del return del bloque
try.

Por ejemplo:

>>> def bool_return():


... try:
... return True
... finally:
... return False
...
>>> bool_return()
False

Y un ejemplo más complejo:

r66/2021(MrTín) Página 57 de 82
Introducción a la
Ingeniería en Computación
2021

>>> def divide(x, y):


... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

Como se puede ver, la cláusula finally siempre se ejecuta. La excepción TypeError


lanzada al dividir dos cadenas de texto no es gestionado por la cláusula except y por lo tanto
es relanzada luego de que se ejecuta la cláusula finally.

En aplicaciones reales, la cláusula finally es útil para liberar recursos externos (como
archivos o conexiones de red), sin importar si el uso del recurso fue exitoso.

Acciones predefinidas de limpieza


Algunos objetos definen acciones de limpieza estándar para llevar a cabo cuando el objeto ya no
necesario, independientemente de que las operaciones sobre el objeto hayan sido exitosas o no.
Véase el siguiente ejemplo, que intenta abrir un archivo e imprimir su contenido en la pantalla.

for line in open("myfile.txt"):


print(line, end="")

El problema con este código es que deja el archivo abierto por un periodo de tiempo
indeterminado luego de que esta parte termine de ejecutarse. Esto no es un problema en
scripts simples, pero puede ser un problema en aplicaciones más grandes. La declaración with
permite que los objetos como archivos sean usados de una forma que asegure que siempre se
los libera rápido y en forma correcta.:

r66/2021(MrTín) Página 58 de 82
Introducción a la
Ingeniería en Computación
2021

with open("myfile.txt") as f:
for line in f:
print(line, end="")

Una vez que la declaración se ejecuta, el fichero f siempre se cierra, incluso si aparece algún
error durante el procesado de las líneas. Los objetos que, como los ficheros, posean acciones
predefinidas de limpieza lo indicarán en su documentación.

r66/2021(MrTín) Página 59 de 82
Introducción a la
Ingeniería en Computación
2021

Glosario

>>>
El prompt en el shell interactivo de Python por omisión. Frecuentemente vistos en
ejemplos de código que pueden ser ejecutados interactivamente en el intérprete.
...
El prompth por defecto en un shell interactivo de Python cuando se está ingresando
código en un bloque con sangría (con indentación), cuando está dentro de un par de
delimitadores izquierdo y derecho coincidentes (paréntesis, corchetes, llaves o comillas
triples), o después de especificar un decorador.
2to3
Una herramienta que intenta convertir código de Python 2.x a Python 3.x arreglando la
mayoría de las incompatibilidades que pueden ser detectadas analizando el código y
recorriendo el árbol de análisis sintáctico.
2to3 está disponible en la biblioteca estándar como lib2to3; un punto de entrada
independiente es provisto como Tools/scripts/2to3. Vea 2to3 - Automated
Python 2 to 3 code translation.
clase base abstracta
Las clases base abstractas (ABC, por sus siglas en inglés Abstract Base Class)
complementan al duck-typing brindando un forma de definir interfaces con técnicas como
hasattr() que serían confusas o sutilmente erróneas (por ejemplo con magic
methods). Las ABC introduce subclases virtuales, las cuales son clases que no heredan
desde una clase pero aún así son reconocidas por isinstance() y
issubclass(); vea la documentación del módulo abc. Python viene con muchas ABC
incorporadas para las estructuras de datos( en el módulo collections.abc),
números (en el módulo numbers ) , flujos de datos (en el módulo io ) , buscadores y
cargadores de importaciones (en el módulo importlib.abc ) . Puede crear sus
propios ABCs con el módulo abc.
anotación
Una etiqueta asociada a una variable, atributo de clase, parámetro de función o valor de
retorno, usado por convención como un type hint.
Las anotaciones de variables no pueden ser accedidas en tiempo de ejecución, pero las
anotaciones de variables globales, atributos de clase, y funciones son almacenadas en el
atributo especial __annotations__ de módulos, clases y funciones,
respectivamente.

r66/2021(MrTín) Página 60 de 82
Introducción a la
Ingeniería en Computación
2021

Vea variable annotation, function annotation, PEP 484 y PEP 526, los cuales describen
esta funcionalidad.
argumento
Un valor pasado a una function (o method) cuando se llama a la función. Hay dos clases
de argumentos:
• argumento nombrado: es un argumento precedido por un identificador (por ejemplo,
nombre=) en una llamada a una función o pasado como valor en un diccionario
precedido por **. Por ejemplo 3 y 5 son argumentos nombrados en las llamadas a
complex():

complex(real=3, imag=5)
complex(**{'real': 3, 'imag': 5})

• argumento posicional son aquellos que no son nombrados. Los argumentos


posicionales deben aparecer al principio de una lista de argumentos o ser pasados
como elementos de un iterable precedido por *. Por ejemplo, 3 y 5 son argumentos
posicionales en las siguientes llamadas:

complex(3, 5)
complex(*(3, 5))

Los argumentos son asignados a las variables locales en el cuerpo de la función. Vea en la
sección Calls las reglas que rigen estas asignaciones. Sintácticamente, cualquier
expresión puede ser usada para representar un argumento; el valor evaluado es asignado
a la variable local.
Vea también el parameter en el glosario, la pregunta frecuente la diferencia entre
argumentos y parámetros, y PEP 362.
administrador asincrónico de contexto
Un objeto que controla el entorno visible en un sentencia async with al definir los
métodos __aenter__() __aexit__(). Introducido por PEP 492.
generador asincrónico
Una función que retorna un asynchronous generator iterator. Es similar a una función
corrutina definida con async def excepto que contiene expresiones yield para
producir series de variables usadas en un ciclo async for.
Usualmente se refiere a una función generadora asincrónica, pero puede referirse a un
iterador generador asincrónico en ciertos contextos. En aquellos casos en los que el
significado no está claro, usar los términos completos evita la ambigüedad.

r66/2021(MrTín) Página 61 de 82
Introducción a la
Ingeniería en Computación
2021

Una función generadora asincrónica puede contener expresiones await así como
sentencias async for, y async with.
iterador generador asincrónico
Un objeto creado por una función asynchronous generator.
Este es un asynchronous iterator el cual cuando es llamado usa el método
__anext__() retornando un objeto aguardable el cual ejecutará el cuerpo de la
función generadora asincrónica hasta la siguiente expresión yield.
Cada yield suspende temporalmente el procesamiento, recordando el estado local de
ejecución (incluyendo a las variables locales y las sentencias try pendientes). Cuando el
iterador del generador asincrónico vuelve efectivamente con otro aguardable retornado
por el método __anext__(), retoma donde lo dejó. Vea PEP 492 y PEP 525.
iterable asincrónico
Un objeto, que puede ser usado en una sentencia async for. Debe retornar un
asynchronous iterator de su método __aiter__(). Introducido por PEP 492.
iterador asincrónico
Un objeto que implementa los métodos meth:__aiter__ y __anext__(). __anext__
debe retornar un objeto awaitable. async for resuelve los esperables retornados por
un método de iterador asincrónico __anext__() hasta que lanza una excepción
StopAsyncIteration. Introducido por PEP 492.
atributo
Un valor asociado a un objeto que es referencias por el nombre usado expresiones de
punto. Por ejemplo, si un objeto o tiene un atributo a sería referenciado como o.a.
aguardable
Es un objeto que puede ser usado en una expresión await. Puede ser una coroutine o un
objeto con un método __await__(). Vea también pep:492.
BDFL
Sigla de Benevolent Dictator For Life, Benevolente dictador vitalicio, es decir Guido van
Rossum, el creador de Python.
archivo binario
Un file object capaz de leer y escribir objetos tipo binarios. Ejemplos de archivos binarios
son los abiertos en modo binario ('rb', 'wb' o 'rb+'), sys.stdin.buffer,
sys.stdout.buffer, e instancias de io.BytesIO y de gzip.GzipFile.
Vea también text file para un objeto archivo capaz de leer y escribir objetos str.
objetos tipo binarios

r66/2021(MrTín) Página 62 de 82
Introducción a la
Ingeniería en Computación
2021

Un objeto que soporta Buffer Protocol y puede exportar un buffer C-contiguous. Esto
incluye todas los objetos bytes, bytearray, y array.array, así como muchos
objetos comunes memoryview. Los objetos tipo binarios pueden ser usados para varias
operaciones que usan datos binarios; éstas incluyen compresión, salvar a archivos
binarios, y enviarlos a través de un socket.
Algunas operaciones necesitan que los datos binarios sean mutables. La documentación
frecuentemente se refiere a éstos como «objetos tipo binario de lectura y escritura».
Ejemplos de objetos de buffer mutables incluyen a bytearray y memoryview de la
bytearray. Otras operaciones que requieren datos binarios almacenados en objetos
inmutables («objetos tipo binario de sólo lectura»); ejemplos de éstos incluyen bytes y
memoryview del objeto bytes.
bytecode
El código fuente Python es compilado en bytecode, la representación interna de un
programa python en el intérprete CPython. El bytecode también es guardado en caché en
los archivos .pyc de tal forma que ejecutar el mismo archivo es más fácil la segunda vez
(la recompilación desde el código fuente a bytecode puede ser evitada). Este «lenguaje
intermedio» deberá corren en una virtual machine que ejecute el código de máquina
correspondiente a cada bytecode. Note que los bytecodes no tienen como requisito
trabajar en las diversas máquina virtuales de Python, ni de ser estable entre versiones
Python.
Una lista de las instrucciones en bytecode está disponible en la documentación de el
módulo dis.
clase
Una plantilla para crear objetos definidos por el usuario. Las definiciones de clase
normalmente contienen definiciones de métodos que operan una instancia de la clase.
variable de clase
Una variable definida en una clase y prevista para ser modificada sólo a nivel de clase (es
decir, no en una instancia de la clase).
coerción
La conversión implícita de una instancia de un tipo en otra durante una operación que
involucra dos argumentos del mismo tipo. Por ejemplo, int(3.15) convierte el número
de punto flotante al entero 3, pero en 3 + 4.5, cada argumento es de un tipo diferente
(uno entero, otro flotante), y ambos deben ser convertidos al mismo tipo antes de que
puedan ser sumados o emitiría un TypeError. Sin coerción, todos los argumentos,
incluso de tipos compatibles, deberían ser normalizados al mismo tipo por el programador,
por ejemplo float(3)+4.5 en lugar de 3+4.5.
número complejo

r66/2021(MrTín) Página 63 de 82
Introducción a la
Ingeniería en Computación
2021

Una extensión del sistema familiar de número reales en el cual los números son
expresados como la suma de una parte real y una parte imaginaria. Los números
imaginarios son múltiplos de la unidad imaginaria (la raíz cuadrada de -1), usualmente
escrita como i en matemáticas o j en ingeniería. Python tiene soporte incorporado para
números complejos, los cuales son escritos con la notación mencionada al final.; la parte
imaginaria es escrita con un sufijo j, por ejemplo, 3+1j. Para tener acceso a los
equivalentes complejos del módulo math module, use :mod:`cmath. El uso de números
complejos es matemática bastante avanzada. Si no le parecen necesarios, puede
ignorarlos sin inconvenientes.
administrador de contextos
Un objeto que controla el entorno en la sentencia with definiendo __enter__() y
__exit__() methods. Vea PEP 343.
context variable
A variable which can have different values depending on its context. This is similar to
Thread-Local Storage in which each execution thread may have a different value for a
variable. However, with context variables, there may be several contexts in one execution
thread and the main usage for context variables is to keep track of variables in concurrent
asynchronous tasks. See contextvars.
contiguo
Un buffer es considerado contiguo con precisión si es C-contíguo o Fortran contiguo. Los
buffers cero dimensionales con C y Fortran contiguos. En los arreglos unidimensionales,
los ítems deben ser dispuestos en memoria uno siguiente al otro, ordenados por índices
que comienzan en cero. En arreglos unidimensionales C-contíguos, el último índice varía
más velozmente en el orden de las direcciones de memoria. Sin embargo, en arreglos
Fortran contiguos, el primer índice vería más rápidamente.
corrutina
Coroutines are a more generalized form of subroutines. Subroutines are entered at one
point and exited at another point. Coroutines can be entered, exited, and resumed at many
different points. They can be implemented with the async def statement. See also PEP
492.
función corrutina
Un función que retorna un objeto coroutine . Una función corrutina puede ser definida con
la sentencia async def, y puede contener las palabras claves await, async for, y
async with. Las mismas son introducidas en PEP 492.
CPython

r66/2021(MrTín) Página 64 de 82
Introducción a la
Ingeniería en Computación
2021

La implementación canónica del lenguaje de programación Python, como se distribuye en


python.org. El término «CPython» es usado cuando es necesario distinguir esta
implementación de otras como Jython o IronPython.
decorador
Una función que retorna otra función, usualmente aplicada como una función de
transformación empleando la sintaxis @envoltorio. Ejemplos comunes de
decoradores son classmethod() y func:staticmethod.
La sintaxis del decorador es meramente azúcar sintáctico, las definiciones de las
siguientes dos funciones son semánticamente equivalentes:

def f(...):
...
f = staticmethod(f)

@staticmethod
def f(...):
...

El mismo concepto existe para clases, pero son menos usadas. Vea la documentación de
function definitions y class definitions para mayor detalle sobre decoradores.
descriptor
Cualquier objeto que define los métodos __get__(), __set__(), o
__delete__(). Cuando un atributo de clase es un descriptor, su conducta enlazada
especial es disparada durante la búsqueda del atributo. Normalmente, usando a.b para
consultar, establecer o borrar un atributo busca el objeto llamado b en el diccionario de
clase de a, pero si b es un descriptor, el respectivo método descriptor es llamado. Entender
descriptores es clave para lograr una comprensión profunda de Python porque son la base
de muchas de las capacidades incluyendo funciones, métodos, propiedades, métodos de
clase, métodos estáticos, y referencia a súper clases.
Para más información sobre métodos descriptores, vea Implementing Descriptors.
diccionario
Un arreglo asociativo, con claves arbitrarias que son asociadas a valores. Las claves
pueden ser cualquier objeto con los métodos __hash__() y __eq__() . Son llamadas
hash en Perl.
vista de diccionario
Los objetos retornados por los métodos dict.keys(), dict.values(), y
dict.items() son llamados vistas de diccionarios. Proveen una vista dinámica de las
entradas de un diccionario, lo que significa que cuando el diccionario cambia, la vista

r66/2021(MrTín) Página 65 de 82
Introducción a la
Ingeniería en Computación
2021

refleja éstos cambios. Para forzar a la vista de diccionario a convertirse en una lista
completa, use list(dictview). Vea Dictionary view objects.
docstring
Una cadena de caracteres literal que aparece como la primera expresión en una clase,
función o módulo. Aunque es ignorada cuando se ejecuta, es reconocida por el compilador
y puesta en el atributo __doc__ de la clase, función o módulo comprendida. Como está
disponible mediante introspección, es el lugar canónico para ubicar la documentación del
objeto.
tipado de pato
Un estilo de programación que no revisa el tipo del objeto para determinar si tiene la
interfaz correcta; en vez de ello, el método o atributo es simplemente llamado o usado («Si
se ve como un pato y grazna como un pato, debe ser un pato»). Enfatizando las interfaces
en vez de hacerlo con los tipos específicos, un código bien diseñado pues tener mayor
flexibilidad permitiendo la sustitución polimórfica. El tipado de pato duck-typing evita usar
pruebas llamando a type() o isinstance(). (Nota: si embargo, el tipado de pato
puede ser complementado con abstract base classes. En su lugar, generalmente emplea
hasattr() tests o EAFP.
EAFP
Del inglés «Easier to ask for forgiveness than permission», es más fácil pedir perdón que
pedir permiso. Este estilo de codificación común en Python asume la existencia de claves
o atributos válidos y atrapa las excepciones si esta suposición resulta falsa. Este estilo
rápido y limpio está caracterizado por muchas sentencias try y except. Esta técnica
contrasta con estilo LBYL usual en otros lenguajes como C.
expresión
Una construcción sintáctica que puede ser evaluada, hasta dar un valor. En otras palabras,
una expresión es una acumulación de elementos de expresión tales como literales,
nombres, accesos a atributos, operadores o llamadas a funciones, todos ellos retornando
valor. A diferencia de otros lenguajes, no toda la sintaxis del lenguaje son expresiones.
También hay statements que no pueden ser usadas como expresiones, como la while.
Las asignaciones también son sentencias, no expresiones.
módulo de extensión
Un módulo escrito en C o C++, usando la API para C de Python para interactuar con el
núcleo y el código del usuario.
f-string
Son llamadas «f-strings» las cadenas literales que usan el prefijo 'f' o 'F', que es una
abreviatura para cadenas literales formateadas. Vea también PEP 498.

r66/2021(MrTín) Página 66 de 82
Introducción a la
Ingeniería en Computación
2021

objeto archivo
Un objeto que expone una API orientada a archivos (con métodos como read() o
write()) al objeto subyacente. Dependiendo de la forma en la que fue creado, un objeto
archivo, puede mediar el acceso a un archivo real en el disco u otro tipo de dispositivo de
almacenamiento o de comunicación (por ejemplo, entrada/salida estándar, buffer de
memoria, sockets, pipes, etc.). Los objetos archivo son también denominados objetos tipo
archivo o flujos.
Existen tres categorías de objetos archivo: crudos raw archivos binarios, con buffer
archivos binarios y archivos de texto. Sus interfaces son definidas en el módulo io. La
forma canónica de crear objetos archivo es usando la función open().
objetos tipo archivo
Un sinónimo de file object.
buscador
Un objeto que trata de encontrar el loader para el módulo que está siendo importado.
Desde la versión 3.3 de Python, existen dos tipos de buscadores: meta buscadores de ruta
para usar con sys.meta_path, y buscadores de entradas de rutas para usar con
sys.path_hooks.
Vea PEP 302, PEP 420 y PEP 451 para mayores detalles.
división entera
Una división matemática que se redondea hacia el entero menor más cercano. El operador
de la división entera es //. Por ejemplo, la expresión 11 // 4 evalúa 2 a diferencia del
2.75 retornado por la verdadera división de números flotantes. Note que (-11) // 4
es -3 porque es -2.75 redondeado para abajo. Ver PEP 238.
función
Una serie de sentencias que retornan un valor al que las llama. También se le puede pasar
cero o más argumentos los cuales pueden ser usados en la ejecución de la misma. Vea
también parameter, method, y la sección Function definitions.
anotación de función
Una annotation del parámetro de una función o un valor de retorno.
Las anotaciones de funciones son usadas frecuentemente para type hint`s , por ejemplo,
se espera que una función tome dos argumentos de clase :class:`int y también se espera
que devuelva dos valores int:

def sum_two_numbers(a: int, b: int) -> int:


return a + b

r66/2021(MrTín) Página 67 de 82
Introducción a la
Ingeniería en Computación
2021

La sintaxis de las anotaciones de funciones son explicadas en la sección Function


definitions.
Vea variable annotation y PEP 484, que describen esta funcionalidad.
__future__
Un pseudo-módulo que los programadores pueden usar para habilitar nuevas capacidades
del lenguaje que no son compatibles con el intérprete actual.
Al importar el módulo __future__ y evaluar sus variables, puede verse cuándo las
nuevas capacidades fueron agregadas por primera vez al lenguaje y cuando se quedaron
establecidas por defecto:

>>> import __future__


>>> __future__.division
_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)

recolección de basura
El proceso de liberar la memoria de lo que ya no está en uso. Python realiza recolección de
basura (garbage collection) llevando la cuenta de las referencias, y el recogedor de basura
cíclico es capaz de detectar y romper las referencias cíclicas. El recogedor de basura
puede ser controlado mediante el módulo gc .
generador
Una función que retorna un generator iterator. Luce como una función normal excepto que
contiene la expresión yield para producir series de valores utilizables en un bucle for o
que pueden ser obtenidas una por una con la función next().
Usualmente se refiere a una función generadora, pero puede referirse a un iterador
generador en ciertos contextos. En aquellos casos en los que el significado no está claro,
usar los términos completos evita la ambigüedad.
iterador generador
Un objeto creado por una función generator.
Cada yield suspende temporalmente el procesamiento, recordando el estado de
ejecución local (incluyendo las variables locales y las sentencias try pendientes). Cuando
el «iterador generado» vuelve, retoma donde ha dejado, a diferencia de lo que ocurre con
las funciones que comienzan nuevamente con cada invocación.
expresión generadora
Una expresión que retorna un iterador. Luce como una expresión normal seguida por la
cláusula for definiendo así una variable de bucle, un rango y una cláusula opcional if.
La expresión combinada genera valores para la función contenedora:

>>> sum(i*i for i in range(10)) # sum of squares 0, 1, 4, ... 81

r66/2021(MrTín) Página 68 de 82
Introducción a la
Ingeniería en Computación
2021

285

función genérica
Una función compuesta de muchas funciones que implementan la misma operación para
diferentes tipos. Qué implementación deberá ser usada durante la llamada a la misma es
determinado por el algoritmo de despacho.
Vea también la entrada de glosario single dispatch, el decorador
functools.singledispatch(), y PEP 443.
GIL
Vea global interpreter lock.
bloqueo global del intérprete
Mecanismo empleado por el intérprete CPython para asegurar que sólo un hilo ejecute el
bytecode Python por vez. Esto simplifica la implementación de CPython haciendo que el
modelo de objetos (incluyendo algunos críticos como dict) están implícitamente a salvo
de acceso concurrente. Bloqueando el intérprete completo se simplifica hacerlo multi-
hilos, a costa de mucho del paralelismo ofrecido por las máquinas con múltiples
procesadores.
Sin embargo, algunos módulos de extensión, tanto estándar como de terceros, están
diseñados para liberar el GIL cuando se realizan tareas computacionalmente intensivas
como la compresión o el hashing. Además, el GIL siempre es liberado cuando se hace
entrada/salida.
Esfuerzos previos hechos para crear un intérprete «sin hilos» (uno que bloquee los datos
compartidos con una granularidad mucho más fina) no han sido exitosos debido a que el
rendimiento sufrió para el caso más común de un solo procesador. Se cree que superar
este problema de rendimiento haría la implementación mucho más compleja y por tanto,
más costosa de mantener.
hash-based pyc
Un archivo cache de bytecode que usa el hash en vez de usar el tiempo de la última
modificación del archivo fuente correspondiente para determinar su validez. Vea Cached
bytecode invalidation.
Hashable (o hasheable)
Un objeto es hashable si tiene un valor de hash que nunca cambiará durante su tiempo de
vida (necesita un método __hash__() ), y puede ser comparado con otro objeto
(necesita el método __eq__() ). Los objetos hashables que se comparan iguales deben
tener el mismo número hash.
La hashabilidad hace a un objeto empleable como clave de un diccionario y miembro de un
set, porque éstas estructuras de datos usan los valores de hash internamente.

r66/2021(MrTín) Página 69 de 82
Introducción a la
Ingeniería en Computación
2021

La mayoría de los objetos inmutables built-in son hashables, mientras que los
contenedores como listas y diccionarios (que son mutables) no lo son. Los contenedores
inmutables, como tuplas y frozensets son solo hashables cuando sus elementos
contenidos son hashables también.
Los objetos que son instancias de clases definidas por el usuario hasheables por defecto.
Todos compara desiguales, excepto a si mismos. Y su valor de hash está derivado de su
id().
IDLE
El entorno integrado de desarrollo de Python, o «Integrated Development Environment for
Python». IDLE es un editor básico y un entorno de intérprete que se incluye con la
distribución estándar de Python.
inmutable
Un objeto con un valor fijo. Los objetos inmutables son números, cadenas y tuplas. Éstos
objetos no pueden ser alterados. Un nuevo objeto debe ser creado si un valor diferente ha
de ser guardado. Juegan un rol importante en lugares donde es necesario un valor de hash
constante, por ejemplo como claves de un diccionario.
ruta de importación
Una lista de las ubicaciones (o entradas de ruta) que son revisadas por path based finder
al importar módulos. Durante la importación, ésta lista de localizaciones usualmente viene
de sys.path, pero para los subpaquetes también puede incluir al atributo __path__
del paquete padre.
importar
El proceso mediante el cual el código Python dentro de un módulo se hace alcanzable
desde otro código Python en otro módulo.
importador
Un objeto que buscan y lee un módulo; un objeto que es tanto finder como loader.
interactivo
Python tiene un intérprete interactivo, lo que significa que puede ingresar sentencias y
expresiones en el prompt del intérprete, ejecutarlos de inmediato y ver sus resultados.
Sólo ejecute python sin argumentos (podría seleccionarlo desde el menú principal de su
computadora). Es una forma muy potente de probar nuevas ideas o inspeccionar módulos
y paquetes (recuerde help(x)).
interpretado
Python es un lenguaje interpretado, a diferencia de uno compilado, a pesar de que la
distinción puede ser difusa debido al compilador a bytecode. Esto significa que los
archivos fuente pueden ser corridos directamente, sin crear explícitamente un ejecutable

r66/2021(MrTín) Página 70 de 82
Introducción a la
Ingeniería en Computación
2021

que es corrido luego. Los lenguajes interpretados típicamente tienen ciclos de desarrollo y
depuración más cortos que los compilados, sin embargo sus programas suelen correr más
lentamente. Vea también interactive.
apagado del intérprete
Cuando se le solicita apagarse, el intérprete Python ingresa a un fase especial en la cual
gradualmente libera todos los recursos reservados, como módulos y varias estructuras
internas críticas. También hace varias llamadas al recolector de basura. Esto puede
disparar la ejecución de código de destructores definidos por el usuario o «weakref
callbacks». El código ejecutado durante la fase de apagado puede encontrar varias
excepciones debido a que los recursos que necesita pueden no funcionar más (ejemplos
comunes son los módulos de bibliotecas o los artefactos de advertencias «warnings
machinery»)
La principal razón para el apagado del intérpreter es que el módulo __main__ o el script
que estaba corriendo termine su ejecución.
iterable
Un objeto capaz de retornar sus miembros uno por vez. Ejemplos de iterables son todos
los tipos de secuencias (como list, str, y tuple) y algunos de tipos no secuenciales,
como dict, objeto archivo, y objetos de cualquier clase que defina con los métodos
__iter__() o con un método __getitem__() que implementen la semántica de
Sequence.
Los iterables pueden ser usados en el bucle for y en muchos otros sitios donde una
secuencia es necesaria (zip(), map(), …). Cuando un objeto iterable es pasado como
argumento a la función incorporada iter(), retorna un iterador para el objeto. Este
iterador pasa así el conjunto de valores. Cuando se usan iterables, normalmente no es
necesario llamar a la función iter() o tratar con los objetos iteradores usted mismo. La
sentencia for lo hace automáticamente por usted, creando un variable temporal sin
nombre para mantener el iterador mientras dura el bucle. Vea también iterator, sequence, y
generator.
iterador
Un objeto que representa un flujo de datos. Llamadas repetidas al método __next__()
del iterador (o al pasar la función incorporada next()) retorna ítems sucesivos del flujo.
Cuando no hay más datos disponibles, una excepción StopIteration es disparada.
En este momento, el objeto iterador está exhausto y cualquier llamada posterior al método
__next__() sólo dispara otra vez StopIteration. Los iteradores necesitan tener
un método:meth:__iter__ que retorna el objeto iterador mismo así cada iterador es también
un iterable y puede ser usado en casi todos los lugares donde los iterables son aceptados.
Una excepción importante es el código que intenta múltiples pases de iteración. Un objeto
contenedor (como la list) produce un nuevo iterador cada vez que las pasa a una

r66/2021(MrTín) Página 71 de 82
Introducción a la
Ingeniería en Computación
2021

función iter() o la usa en un blucle for. Intentar ésto con un iterador simplemente
retornaría el mismo objeto iterador exhausto usado en previas iteraciones, haciéndolo
aparecer como un contenedor vacío.
Puede encontrar más información en Iterator Types.
función clave
Una función clave o una función de colación es un invocable que retorna un valor usado
para el ordenamiento o clasificación. Por ejemplo, locale.strxfrm() es usada para
producir claves de ordenamiento que se adaptan a las convenciones específicas de
ordenamiento de un locale.
Cierta cantidad de herramientas de Python aceptan funciones clave para controlar como
los elementos son ordenados o agrupados. Incluyendo a min(), max(), sorted(),
list.sort(), heapq.merge(), heapq.nsmallest(),
heapq.nlargest(), y itertools.groupby().
Hay varias formas de crear una función clave. Por ejemplo, el método str.lower()
puede servir como función clave para ordenamientos que no distingan mayúsculas de
minúsculas. Como alternativa, una función clave puede ser realizada con una expresión
lambda como lambda r: (r[0], r[2]). También, el módulo operator
provee tres constructores de funciones clave: attrgetter(), itemgetter(), y
methodcaller(). Vea en Sorting HOW TO ejemplos de cómo crear y usar funciones
clave.
argumento nombrado
Vea argument.
lambda
Una función anónima de una línea consistente en un sola expression que es evaluada
cuando la función es llamada. La sintaxis para crear una función lambda es lambda
[parameters]: expression
LBYL
Del inglés «Look before you leap», «mira antes de saltar». Es un estilo de codificación que
prueba explícitamente las condiciones previas antes de hacer llamadas o búsquedas. Este
estilo contrasta con la manera EAFP y está caracterizado por la presencia de muchas
sentencias if.
En entornos multi-hilos, el método LBYL tiene el riesgo de introducir condiciones de
carrera entre los hilos que están «mirando» y los que están «saltando». Por ejemplo, el
código, if key in mapping: return mapping[key]` puede fallar si otro hilo remueve key de
mapping después del test, pero antes de retornar el valor. Este problema puede ser
resuelto usando bloqueos o empleando el método EAFP.
lista

r66/2021(MrTín) Página 72 de 82
Introducción a la
Ingeniería en Computación
2021

Es una sequence Python incorporada. A pesar de su nombre es más similar a un arreglo en


otros lenguajes que a una lista enlazada porque el acceso a los elementos es O(1).
comprensión de listas
Una forma compacta de procesar todos o parte de los elementos en una secuencia y
retornar una lista como resultado. result = ['{:#04x}'.format(x) for x
in range(256) if x % 2 == 0] genera una lista de cadenas conteniendo
números hexadecimales (0x..) entre 0 y 255. La cláusula if es opcional. Si es omitida,
todos los elementos en range(256) son procesados.
cargador
Un objeto que carga un módulo. Debe definir el método llamado load_module(). Un
cargador es normalmente retornados por un finder. Vea PEP 302 para detalles y
importlib.abc.Loader para una abstract base class.
método mágico
Una manera informal de llamar a un special method.
mapeado
Un objeto contenedor que permite recupero de claves arbitrarias y que implementa los
métodos especificados en la Mapping o MutableMapping abstract base classes.
Por ejemplo, dict, collections.defaultdict,
collections.OrderedDict y collections.Counter.
meta buscadores de ruta
Un finder retornado por una búsqueda de sys.meta_path. Los meta buscadores de
ruta están relacionados a buscadores de entradas de rutas, pero son algo diferente.
Vea en importlib.abc.MetaPathFinder los métodos que los meta buscadores
de ruta implementan.
metaclase
La clase de una clase. Las definiciones de clases crean nombres de clase, un diccionario
de clase, y una lista de clases base. Las metaclases son responsables de tomar estos tres
argumentos y crear la clase. La mayoría de los objetos de un lenguaje de programación
orientado a objetos provienen de una implementación por defecto. Lo que hace a Python
especial que es posible crear metaclases a medida. La mayoría de los usuario nunca
necesitarán esta herramienta, pero cuando la necesidad surge, las metaclases pueden
brindar soluciones poderosas y elegantes. Han sido usadas para loggear acceso de
atributos, agregar seguridad a hilos, rastrear la creación de objetos, implementar
singletons, y muchas otras tareas.
Más información hallará en Metaclasses.
método

r66/2021(MrTín) Página 73 de 82
Introducción a la
Ingeniería en Computación
2021

Una función que es definida dentro del cuerpo de una clase. Si es llamada como un
atributo de una instancia de otra clase, el método tomará el objeto instanciado como su
primer argument (el cual es usualmente denominado self). Vea function y nested scope.
orden de resolución de métodos
Orden de resolución de métodos es el orden en el cual una clase base es buscada por un
miembro durante la búsqueda. Mire en The Python 2.3 Method Resolution Order los
detalles del algoritmo usado por el intérprete Python desde la versión 2.3.
módulo
Un objeto que sirve como unidad de organización del código Python. Los módulos tienen
espacios de nombres conteniendo objetos Python arbitrarios. Los módulos son cargados
en Python por el proceso de importing.
Vea también package.
especificador de módulo
Un espacio de nombres que contiene la información relacionada a la importación usada al
leer un módulo. Una instancia de importlib.machinery.ModuleSpec.
MRO
Vea method resolution order.
mutable
Los objetos mutables pueden cambiar su valor pero mantener su id(). Vea también
immutable.
tupla nombrada
El termino «tupla nombrada» aplica a cualquier tipo o clase que hereda de tupla y cuyos
elementos indexables son también accesibles por medio de atributos con nombre.
Asimismo, dicho tipo o clase tal vez tenga funcionalidad adicional
Varios tipos built-in son tuplas nombradas, incluyendo los valores retornados por
time.localtime() y os.stat(). Otro ejemplo es sys.float_info:

>>> sys.float_info[1] # indexed access


1024
>>> sys.float_info.max_exp # named field access
1024
>>> isinstance(sys.float_info, tuple) # kind of tuple
True

Algunas tuplas con nombre son de tipos built-in, como los ejemplos anteriores. Pero
también es posible crear una a partir de una definicion de clases normal heredando de
tuple y definiendo los campos nombrados. Dicha clase puede ser desarrollada
puntualmente y a mano o puede ser creada a partir de la función fabrica

r66/2021(MrTín) Página 74 de 82
Introducción a la
Ingeniería en Computación
2021

collections.namedtuple() Que simplifica la creacion de estas clases y agrega


métodos adicionales comunes que tal vez no se encuentren en tuplas nombradas creadas
ad-hoc.
espacio de nombres
El lugar donde la variable es almacenada. Los espacios de nombres son implementados
como diccionarios. Hay espacio de nombre local, global, e incorporado así como espacios
de nombres anidados en objetos (en métodos). Los espacios de nombres soportan
modularidad previniendo conflictos de nombramiento. Por ejemplo, las funciones
builtins.open y os.open() se distinguen por su espacio de nombres. Los
espacios de nombres también ayuda a la legibilidad y mantenibilidad dejando claro qué
módulo implementa una función. Por ejemplo, escribiendo random.seed() o
itertools.islice() queda claro que éstas funciones están implementadas en los
módulos random y itertools, respectivamente.
paquete de espacios de nombres
Un PEP 420 package que sirve sólo para contener subpaquetes. Los paquetes de espacios
de nombres pueden no tener representación física, y específicamente se diferencian de
los regular package porque no tienen un archivo __init__.py.
Vea también module.
alcances anidados
La habilidad de referirse a una variable dentro de una definición encerrada. Por ejemplo,
una función definida dentro de otra función puede referir a variables en la función externa.
Note que los alcances anidados por defecto sólo funcionan para referencia y no para
asignación. Las variables locales leen y escriben sólo en el alcance más interno. De
manera semejante, las variables globales pueden leer y escribir en el espacio de nombres
global. Con nonlocal se puede escribir en alcances exteriores.
clase de nuevo estilo
Vieja denominación usada para el estilo de clases ahora empleado en todos los objetos de
clase. En versiones más tempranas de Python, sólo las nuevas clases podían usar
capacidades nuevas y versátiles de Python como __slots__, descriptores,
propiedades, __getattribute__(), métodos de clase y métodos estáticos.
objeto
Cualquier dato con estado (atributo o valor) y comportamiento definido (métodos). También
es la más básica clase base para cualquier new-style class.
paquete
Un module Python que puede contener submódulos o recursivamente, subpaquetes.
Técnicamente, un paquete es un módulo Python con un atributo __path__.

r66/2021(MrTín) Página 75 de 82
Introducción a la
Ingeniería en Computación
2021

Vea también regular package y namespace package.


parámetro
Una entidad nombrada en una definición de una function (o método) que especifica un
argument (o en algunos casos, varios argumentos) que la función puede aceptar. Existen
cinco tipos de argumentos:
• posicional o nombrado: especifica un argumento que puede ser pasado tanto como
posicional o como nombrado. Este es el tipo por defecto de parámetro, como foo y
bar en el siguiente ejemplo:
def func(foo, bar=None): ...
• sólo posicional: especifica un argumento que puede ser pasado sólo por posición.
Python no tiene una sintaxis específica para los parámetros que son sólo por
posición. Sin embargo, algunas funciones tienen parámetros sólo por posición (por
ejemplo abs()).
• sólo nombrado: especifica un argumento que sólo puede ser pasado por nombre.
Los parámetros sólo por nombre pueden ser definidos incluyendo un parámetro
posicional de una sola variable o un mero *` antes de ellos en la lista de
parámetros en la definición de la función, como kw_only1 y kw_only2 en el ejemplo
siguiente:
def func(arg, *, kw_only1, kw_only2): ...
• variable posicional: especifica una secuencia arbitraria de argumentos posicionales
que pueden ser brindados (además de cualquier argumento posicional aceptado
por otros parámetros). Este parámetro puede ser definido anteponiendo al nombre
del parámetro *, como a args en el siguiente ejemplo:
def func(*args, **kwargs): ...
• variable nombrado: especifica que arbitrariamente muchos argumentos nombrados
pueden ser brindados (además de cualquier argumento nombrado ya aceptado por
cualquier otro parámetro). Este parámetro puede ser definido anteponiendo al
nombre del parámetro con **, como kwargs en el ejemplo más arriba.
Los parámetros puede especificar tanto argumentos opcionales como requeridos, así
como valores por defecto para algunos argumentos opcionales.
Vea también el glosario de argument, la pregunta respondida en la diferencia entre
argumentos y parámetros, la clase inspect.Parameter, la sección Function
definitions , y PEP 362.
entrada de ruta
Una ubicación única en el import path que el path based finder consulta para encontrar los
módulos a importar.
buscador de entradas de ruta

r66/2021(MrTín) Página 76 de 82
Introducción a la
Ingeniería en Computación
2021

Un finder retornado por un invocable en sys.path_hooks (esto es, un path entry


hook) que sabe cómo localizar módulos dada una path entry.
Vea en importlib.abc.PathEntryFinder los métodos que los buscadores de
entradas de paths implementan.
gancho a entrada de ruta
Un invocable en la lista sys.path_hook que retorna un path entry finder si éste sabe
cómo encontrar módulos en un path entry específico.
buscador basado en ruta
Uno de los meta buscadores de ruta por defecto que busca un import path para los
módulos.
objeto tipo ruta
Un objeto que representa una ruta del sistema de archivos. Un objeto tipo ruta puede ser
tanto una str como un bytes representando una ruta, o un objeto que implementa el
protocolo os.PathLike. Un objeto que soporta el protocolo os.PathLike puede
ser convertido a ruta del sistema de archivo de clase str o bytes usando la función
os.fspath(); os.fsdecode() os.fsencode() pueden emplearse para
garantizar que retorne respectivamente str o bytes. Introducido por PEP 519.
PEP
Propuesta de mejora de Python, del inglés «Python Enhancement Proposal». Un PEP es un
documento de diseño que brinda información a la comunidad Python, o describe una
nueva capacidad para Python, sus procesos o entorno. Los PEPs deberían dar una
especificación técnica concisa y una fundamentación para las capacidades propuestas.
Los PEPs tienen como propósito ser los mecanismos primarios para proponer nuevas y
mayores capacidad, para recoger la opinión de la comunidad sobre un tema, y para
documentar las decisiones de diseño que se han hecho en Python. El autor del PEP es el
responsable de lograr consenso con la comunidad y documentar las opiniones disidentes.
Vea PEP 1.
porción
Un conjunto de archivos en un único directorio (posiblemente guardo en un archivo
comprimido zip) que contribuye a un espacio de nombres de paquete, como está definido
en PEP 420.
argumento posicional
Vea argument.
API provisoria
Una API provisoria es aquella que deliberadamente fue excluida de las garantías de
compatibilidad hacia atrás de la biblioteca estándar. Aunque no se esperan cambios

r66/2021(MrTín) Página 77 de 82
Introducción a la
Ingeniería en Computación
2021

fundamentales en dichas interfaces, como están marcadas como provisionales, los


cambios incompatibles hacia atrás (incluso remover la misma interfaz) podrían ocurrir si
los desarrolladores principales lo estiman. Estos cambios no se hacen gratuitamente –
solo ocurrirán si fallas fundamentales y serias son descubiertas que no fueron vistas
antes de la inclusión de la API.
Incluso para APIs provisorias, los cambios incompatibles hacia atrás son vistos como una
«solución de último recurso» - se intentará todo para encontrar una solución compatible
hacia atrás para los problemas identificados.
Este proceso permite que la biblioteca estándar continúe evolucionando con el tiempo, sin
bloquearse por errores de diseño problemáticos por períodos extensos de tiempo.
Vea :pep`241` para más detalles.
paquete provisorio
Vea provisional API.
Python 3000
Apodo para la fecha de lanzamiento de Python 3.x (acuñada en un tiempo cuando llegar a
la versión 3 era algo distante en el futuro.) También se lo abrevió como «Py3k».
Pythónico
Una idea o pieza de código que sigue ajustadamente la convenciones idiomáticas
comunes del lenguaje Python, en vez de implementar código usando conceptos comunes
a otros lenguajes. Por ejemplo, una convención común en Python es hacer bucles sobre
todos los elementos de un iterable con la sentencia for. Muchos otros lenguajes no
tienen este tipo de construcción, así que los que no están familiarizados con Python
podrían usar contadores numéricos:

for i in range(len(food)):
print(food[i])

En contraste, un método Pythónico más limpio:

for piece in food:


print(piece)

nombre calificado
Un nombre con puntos mostrando la ruta desde el alcance global del módulo a la clase,
función o método definido en dicho módulo, como se define en PEP 3155. Para las
funciones o clases de más alto nivel, el nombre calificado es el igual al nombre del objeto:

>>> class C:
... class D:

r66/2021(MrTín) Página 78 de 82
Introducción a la
Ingeniería en Computación
2021

... def meth(self):


... pass
...
>>> C.__qualname__
'C'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__qualname__
'C.D.meth'

Cuando es usado para referirse a los módulos, nombre completamente calificado significa
la ruta con puntos completo al módulo, incluyendo cualquier paquete padre, por ejemplo,
email.mime.text`:

>>> import email.mime.text


>>> email.mime.text.__name__
'email.mime.text'

contador de referencias
El número de referencias a un objeto. Cuando el contador de referencias de un objeto cae
hasta cero, éste es desalojable. En conteo de referencias no suele ser visible en el código
de Python, pero es un elemento clave para la implementación de CPython. El módulo sys
define la getrefcount() que los programadores pueden emplear para retornar el
conteo de referencias de un objeto en particular.
paquete regular
Un package tradicional, como aquellos con un directorio conteniendo el archivo
__init__.py.
Vea también namespace package.
__slots__
Es una declaración dentro de una clase que ahorra memoria pre declarando espacio para
las atributos de la instancia y eliminando diccionarios de la instancia. Aunque es popular,
esta técnica es algo dificultosa de lograr correctamente y es mejor reservarla para los
casos raros en los que existen grandes cantidades de instancias en aplicaciones con uso
crítico de memoria.
secuencia
Un iterable que logra un acceso eficiente a los elementos usando índices enteros a través
del método especial __getitem__() y que define un método __len__() que
devuelve la longitud de la secuencia. Algunas de las secuencias incorporadas son list,
str, tuple, y bytes. Observe que dict también soporta __getitem__() y
__len__(), pero es considerada un mapeo más que una secuencia porque las
búsquedas son por claves arbitraria immutable y no por enteros.

r66/2021(MrTín) Página 79 de 82
Introducción a la
Ingeniería en Computación
2021

La clase base abstracta collections.abc.Sequence define una interfaz mucho


más rica que va más allá de sólo __getitem__() y __len__(), agregando
count(), index(), __contains__(), y __reversed__(). Los tipos que
implementan esta interfaz expandida pueden ser registrados explícitamente usando
register().
despacho único
Una forma de despacho de una generic function donde la implementación es elegida a
partir del tipo de un sólo argumento.
rebanada
Un objeto que contiene una porción de una sequence. Una rebanada es creada usando la
notación de suscripto, [] con dos puntos entre los números cuando se ponen varios,
como en nombre_variable[1:3:5]. La notación con corchete (suscrito) usa
internamente objetos slice.
método especial
Un método que es llamado implícitamente por Python cuando ejecuta ciertas operaciones
en un tipo, como la adición. Estos métodos tienen nombres que comienzan y terminan con
doble barra baja. Los métodos especiales están documentados en Special method names.
sentencia
Una sentencia es parte de un conjunto (un «bloque» de código). Una sentencia tanto es
una expression como alguna de las varias sintaxis usando una palabra clave, como if,
while o for.
codificación de texto
Un códec que codifica las cadenas Unicode a bytes.
archivo de texto
Un file object capaz de leer y escribir objetos str. Frecuentemente, un archivo de texto
también accede a un flujo de datos binario y maneja automáticamente el text encoding.
Ejemplos de archivos de texto que son abiertos en modo texto ('r' o 'w'),
sys.stdin, sys.stdout, y las instancias de io.StringIO.
Vea también binary file por objeto de archivos capaces de leer y escribir objeto tipo binario.
cadena con triple comilla
Una cadena que está enmarcada por tres instancias de comillas («) o apostrofes (“).
Aunque no brindan ninguna funcionalidad que no está disponible usando cadenas con
comillas simple, son útiles por varias razones. Permiten incluir comillas simples o dobles
sin escapar dentro de las cadenas y pueden abarcar múltiples líneas sin el uso de
caracteres de continuación, haciéndolas particularmente útiles para escribir docstrings.

r66/2021(MrTín) Página 80 de 82
Introducción a la
Ingeniería en Computación
2021

tipo
El tipo de un objeto Python determina qué tipo de objeto es; cada objeto tiene un tipo. El
tipo de un objeto puede ser accedido por su atributo __class__ o puede ser
conseguido usando type(obj).
alias de tipos
Un sinónimo para un tipo, creado al asignar un tipo a un identificador.
Los alias de tipos son útiles para simplificar los indicadores de tipo. Por ejemplo:

from typing import List, Tuple

def remove_gray_shades(
colors: List[Tuple[int, int, int]]) -> List[Tuple[int, int, int]]:
pass

podría ser más legible así:

from typing import List, Tuple

Color = Tuple[int, int, int]

def remove_gray_shades(colors: List[Color]) -> List[Color]:


pass

Vea typing y PEP 484, que describen esta funcionalidad.


indicador de tipo
Una annotation que especifica el tipo esperado para una variable, un atributo de clase, un
parámetro para una función o un valor de retorno.
Los indicadores de tipo son opcionales y no son obligados por Python pero son útiles para
las herramientas de análisis de tipos estático, y ayuda a las IDE en el completado del
código y la refactorización.
Los indicadores de tipo de las variables globales, atributos de clase, y funciones, no de
variables locales, pueden ser accedidos usando typing.get_type_hints().
Vea typing y PEP 484, que describen esta funcionalidad.
saltos de líneas universales
Una manera de interpretar flujos de texto en la cual son reconocidos como finales de línea
todas siguientes formas: la convención de Unix para fin de línea '\n', la convención de
Windows '\r\n', y la vieja convención de Macintosh '\r'. Vea PEP 278 y PEP 3116,
además de:func:bytes.splitlines para usos adicionales.
anotación de variable
Una annotation de una variable o un atributo de clase.

r66/2021(MrTín) Página 81 de 82
Introducción a la
Ingeniería en Computación
2021

Cuando se anota una variable o un atributo de clase, la asignación es opcional:

class C:
field: 'annotation'

Las anotaciones de variables son frecuentemente usadas para type hints: por ejemplo, se
espera que esta variable tenga valores de clase int:

count: int = 0

La sintaxis de la anotación de variables está explicada en la sección Annotated


assignment statements.
Vea function annotation, PEP 484 y PEP 526, los cuales describen esta funcionalidad.
entorno virtual
Un entorno cooperativamente aislado de ejecución que permite a los usuarios de Python y
a las aplicaciones instalar y actualizar paquetes de distribución de Python sin interferir con
el comportamiento de otras aplicaciones de Python en el mismo sistema.
Vea también venv.
máquina virtual
Una computadora definida enteramente por software. La máquina virtual de Python
ejecuta el bytecode generado por el compilador de bytecode.
Zen de Python
Un listado de los principios de diseño y la filosofía de Python que son útiles para entender
y usar el lenguaje. El listado puede encontrarse ingresando «import this» en la
consola interactiva.

r66/2021(MrTín) Página 82 de 82

También podría gustarte