Manual Básico de Python
Manual Básico de Python
DE PYTHON
Federico Garay
Introducción:
Python es un lenguaje de programación potente y versátil, amado tanto por programadores principiantes
como por profesionales. Python se caracteriza por su sintaxis clara y su enfoque orientado a objetos, lo que
lo hace ideal para una variedad de aplicaciones, desde desarrollo web hasta ciencia de datos. En este
manual, exploraremos los conceptos fundamentales de Python, comenzando por su naturaleza como
lenguaje de Programación Orientada a Objetos (OOP) y avanzando hacia estructuras de datos más
complejas y funciones. Nuestro objetivo es proporcionar una comprensión sólida de los aspectos básicos
para que puedas comenzar a programar con confianza y eficiencia.
A lo largo del manual, abordaremos los siguientes temas en detalle:
Fundamentos de Python
Este manual está diseñado para guiarte a través de los fundamentos de Python, equipándote con el
conocimiento necesario para comenzar a construir tus propios programas en Python.
Siguiendo estos temas, estarás bien preparado para enfrentar desafíos más avanzados y utilizar Python de
manera efectiva en tus proyectos futuros.
En Python todo es un objeto.
¿Por qué esto es importante? Porque si pierdes de vista el concepto de que todo en Python
tanto, el número 1 es un
objeto: El objeto 1.
In [2]: 1
Out[2]: 1
Con el 1, al igual que con todos los objetos de tipo número, en Python, puedo realizar operaciones
matemáticas. Entonces puedo decir que si tomo el objeto 1, y le sumo otro objeto numérico, como el
número 2, lo que obtengo es otro objeto, que es el objeto 3.
In [1]: 1 + 2
Out[1]: 3
Tipos de Objetos
Ya vamos a ver más adelante que los números son solamente uno de los tantos TIPOS de objetos
que existen en Python: el TIPO de objetos numérico.
Python trabaja con objetos, y por lo tanto es uno de los tantos lenguajes de programación que están
estructurados según el paradigma llamado Programación Orientada a Objetos, que en inglés se
abrevia como OOP.
Si bien aún es temprano para explicar este concepto en profundidad, quiero que sepas que Python
se corresponde a ese paradigma, porque básicamente todo lo que haremos cuando escribamos
código Python será construir, manipular, interactuar y eliminar objetos.
La razón por la que te cuento esto antes de comenzar a trabajar con Python, es porque si bien
vamos a explicar este concepto mucho más en profundidad en su debido momento, te prometo que
si mantienes estos conceptos siempre a la vista desde el inicio, le podrás sacar aún más provecho de
este intuitivo y poderoso lenguaje de programación:
In [1]: 1
Out[1]: 1
Pero también tenemos la posibilidad de ponerle una etiqueta a ese objeto, y de referirnos a ese
objeto de ahora en más no por su nombre original (1), sino por el nombre que le pongamos a la
etiqueta.
In [2]: miNumero = 1
In [3]: miNumero
Out[3]: 1
Entonces hasta el momento, Python ha creado dos objetos en nuestro entorno: el objeto 1, y el
objeto "miNumero". Y al mismo tiempo ha usado el operador "=" para relacionar ambos objetos
en la memoria.
La palabra miNumero a partir de ahora es una variable. Es decir: es una etiqueta que podemos
usar para decir "1".
In [4]: miNumero + 2
Out[4]: 3
In [5]: otroNumero = 2
In [6]: otroNumero
Out[6]: 2
Ahora puedo hacer una operación llamando a estas dos variables, en lugar de a los valores que
representan.
Out[7]: 3
Si usas la misma variable (es decir: la misma etiqueta) para asignarle un valor distinto, ahora esa
variable será asignada a un nuevo valor.
In [8]: miNumero = 3
De ahora en más cuando escribas miNumero ya no estarás diciendo 1, sino que estarás
diciendo 3. Por eso se llaman "variables": porque los valores que representan… pueden variar. Su
valor es variable.
Si en python digo 1, siempre estaré diciendo 1. Pero si digo miNumero, lo que estoy diciendo
depende del estado de la memoria en ese momento. Antes valía 1 y ahora vale 3. miNumero
tiene un valor variable.
In [9]: miNumero
Out[9]: 3
Ahora veamos que sucede si creo una nueva variable, pero le asigno un valor que ya ha sido
asignado a otra variable.
In [10]: nuevoNumero = 3
A partir de ahora tenemos dos variables con el mismo valor ¿esto significa que python ha
creado dos objetos 3 en mi entorno?
En realidad no. No se crea un nuevo objeto 3, sino que es el mismo objeto (el mismo número 3),
al que se le han adherido 2 etiquetas: miNumero y nuevoNumero.
Veamos qué sucede si llamamos a ese mismo objeto en una sola operación, usando sus dos
etiquetas:
Out[11]: 6
Si bien en mi entorno existe un solo numero 3, lo puedo invocar de dos maneras distintas.
Por otro lado, las variables tambien pueden reasignarse dinámicamente. Mira esto:
In [13]: miNumero
Out[13]: 4
Variables de Texto
En la mayoría de los lenguajes de programación, al dato de tipo texto, se lo denomina como string.
String en inglés significa cadena, y es por eso que al texto se lo llama string, porque es interpretado por el
código como una cadena de texto. Es decir, como una secuencia de caracteres que forman un texto, y esto
es muy importante porque luego vamos a ver que se pueden hacer muchas cosas con los objetos de tipo
texto, y que esas cosas se pueden hacer gracias a que el texto no es interpretado por el código como un
bloque homogéneo, sino como una cadena de unidades de texto, llamadas caracteres.
Por empezar, los strings deben escribirse siempre entre comillas (dobles o simples):
Si quieres que tus strings contengan comillas internas, ya que forman parte del texto, debes usar el tipo de
comillas diferente al que usaste para encerrar el string.
In [6]: print(miFrase)
Hola Mundo
A través de la siguiente demostración, vamos comprobar que el uso de comillas dobles o simples, es
indistinto para determinar el valor del contenido del string.
Out[8]: True
Función Type()
En esta lección te voy a enseñar una función incorporada en Python, a la que la
mayoría de los instructores no le dan la gran importancia que tiene, y es la
función type().
Las funciones son métodos que python tiene definidos para trabajar con los
objetos. Podríamos decir que las funciones sirven para que los objetos de Python
hagan cosas.
¿Y qué cosas hace la función type? La función type hace que los objetos nos digan
qué tipo de datos son.
In [1]: a = 1
b = "1"
In [2]: a
Out[2]: 1
In [3]: b
Out[3]: '1'
In [4]: print(b)
In [5]: type(a)
Out[5]: int
In [6]: type(b)
Out[6]: str
Puede que en este momento estés diciendo, ***"Bueno Fede, parece que Type
es una función muy simpática, pero no parece que fuera tan importante como
dices"***. Y la verdad es que entiendo si piensas eso, y de hecho es la
razón por la que muchas personas menosprecian a esta función.
Pero ten en cuenta que hasta ahora solo hemos conocido dos tipos de datos: los
numeros enteros (int), y el texto (strings). Pero a medida que avancemos con el
curso vas a ver que hay muchísimos tipos de datos: * los que python ya trae
incorporados * los que provienen de las herramientas que usaremos más adelante
para hacer data science, como pandas o matplotlib, que también tienen sus
propios tipos de datos * y a eso agrégale los que vas a ir creando tu mismo
cuando programes
Esto hace que la cantidad de tipos de datos existente sea infinita. Y encima de
todo eso, los tipos de datos pueden llegar a transformarse en otro tipo de datos
durante la ejecución de tu código, por diversas razones. Pero eso no es todo. La
De hecho, uno de mis maestros me hizo pensar esto: ***todos creen que la
programación se trata de funciones fantásticas. No, me dijo él, la
programación se trata de tipos de datos***. En ese momento pensé que estaba
In [ ]:
Números
En python existen 3 tipos de datos numéricos: * Enteros (int) * Decimales
(float) * Complejos (complex)
Los números que hemos usado hasta ahora, son los números enteros. A este
tipo de datos en python se lo denomina int, y este tipo de datos incluye a
todos los números enteros, ya sean positivos o negativos, y también al cero.
In [1]: type(23)
Out[1]: int
In [2]: type(-6)
Out[2]: int
In [3]: type(0)
Out[3]: int
In [4]: type(3.12)
Out[4]: float
In [5]: print(type(-2.5))
print(type(0.0000001))
print(type(246.598745215))
<class 'float'>
<class 'float'>
<class 'float'>
El tercer tipo de datos, son los números complejos, a los que en python se
denimina como complex. Este tipo de datos numéricos tienen dos
dimensiones: una parte real y una parte imaginaria.
In [6]: 3 + 4J
Out[6]: (3+4j)
In [7]: -5.2 - 5J
Out[7]: (-5.2-5j)
Out[8]: complex
In [9]: complex(3, 2)
Out[9]: (3+2j)
In [10]: a = complex(3, 2)
In [11]: a
Out[11]: (3+2j)
In [12]: type(a)
Out[12]: complex
Símbolo Operación
+ Suma
- Resta
* Multiplicación
/ División
// División al piso
% Módulo
1. Suma
In [1]: 2 + 2
Out[1]: 4
2. Resta
In [2]: 8.5 - 1.5
Out[2]: 7.0
3. Multiplicación
In [3]: 2 * 3.5
Out[3]: 7.0
4. División
In [4]: 10 / 3
Out[4]: 3.3333333333333335
5. División al Piso
In [5]: 10 // 3
Out[5]: 3
6. Módulo
In [6]: 10 % 3
Out[6]: 1
7. Potencia
In [7]: 5 ** 2
Out[7]: 25
8. Raíz Cuadrada
In [8]: 25 ** 0.5
Out[8]: 5.0
9. Raíz Cúbica
In [9]: 25 ** (1/3)
Out[9]: 2.924017738212866
Operaciones con números complejos
In [10]: a = 3 + 5J b = 2 + 2J
In [11]: a + b
Out[11]: (5+7j)
Out[13]: '11'
Out[14]: 'federico'
In [15]: 1 + int(num)
Out[15]: 2
Strings
Ya vimos que los strings son un tipo de dato, y que son
tratados por python como una secuencia de caracteres.
In [2]: type(palabra)
Out[2]: str
In [3]: palabra
Out[3]: 'manzana'
los
caracteres alfabéticos del string a mayúsculas.
In [4]: palabra.upper()
Out[4]: 'MANZANA'
Pero es importante tener en cuenta que los strings son
inmutables, es decir que no los puedes modificar.
In [5]: palabra
Out[5]: 'manzana'
debemos
aplicar el método al guardar la copia en una nueva variable.
In [7]: palabra
Out[7]: 'manzana'
In [8]: palabraMay
Out[8]: 'MANZANA'
In [9]: dir(palabra)
Out[9]: ['__add__',
'__class__',
'__contains__',
'__delattr__',
'__dir__',
'__doc__', '__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getnewargs__',
'__getstate__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__', '__len__',
'__lt__', '__mod__',
'__mul__', '__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rmod__',
'__rmul__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'capitalize',
'casefold',
'center', 'count',
'encode',
'endswith',
'expandtabs',
'find',
'format',
'format_map',
'index',
'isalnum',
'isalpha',
'isascii',
'isdecimal',
'isdigit',
'isidentifier',
'islower',
'isnumeric',
'isprintable',
'isspace',
'istitle',
'isupper',
'join',
'ljust',
'lower',
'lstrip',
'maketrans',
'partition',
'removeprefix',
'removesuffix',
'replace',
'rfind',
'rindex',
'rjust',
'rpartition',
'rsplit',
'rstrip',
'split',
'splitlines',
'startswith',
'strip',
'swapcase',
'title',
'translate',
'upper',
'zfill']
Por ejemplo, tomemos de la lista el método capitalize() y
veamos qué hace.
In [10]: palabra.capitalize()
Out[10]: 'Manzana'
In [11]: help(palabra.capitalize)
[tipo de dato].[método]([objeto])
In [12]: str.capitalize(palabra)
Out[12]: 'Manzana'
Indexar Strings
Otra cosa que podemos hacer con los strings, es indexarlos.
ÍNDICE CARACTER
0 m
1 a
2 n
3 z
4 a
5 n
6 a
In [2]: palabra[0]
Out[2]: 'm'
In [3]: palabra[1]
Out[3]: 'a'
Si reasigno el valor de la variable, al volver a consultar los mismos índices voy a recibir
valores diferentes.
c
i
In [6]: palabra[-1]
Out[6]: 'a'
In [7]: palabra[-2]
Out[7]: 'l'
También puedo usar la indexación para recibir segmentos del string en lugar de caracteres
únicos. Para esto, dentro de las llaves debo proveer dos índices separados por dos puntos (:).
In [8]: palabra[0:4]
Out[8]: 'ciru'
Si vas a comenzar por el índice 0, puedes obviarlo, ya que ese es el valor que viene por
defecto
In [9]: palabra[:4]
Out[9]: 'ciru'
In [10]: palabra[4:7]
Out[10]: 'ela'
Observa que si bien 'ciruela' llega hasta el índice 6, tuve que poner el número posterior (7)
aunque ese índice no existe en mi string, pero de otro modo hubiese llegado hasta el
caracter anterior.
De hecho, puedes excederte todo lo que quieras, y aún así no va a dar error
In [11]: palabra[4:30]
Out[11]: 'ela'
Otra manera de incluir los caracteres finales, es no colocar nada en ese lugar, ya que por
defecto python indexará hasta el último caracter del string.
In [12]: palabra[4:]
Out[12]: 'ela'
También puedo tomar un segmento que vaya saltando tantos lugares como le indique, si
agrego un tercer parámetro dentro de las llaves:
In [13]: palabra[0:5:2]
Out[13]: 'cre'
In [14]: palabra[::3]
Out[14]: 'cua'
Finalmente, ten en cuenta que sin importar cuanto indexes o segmentes tu string, siempre
podrás aplicar todos los métodos de string a los resultados que obtengas.
In [15]: palabra[0:4].upper()
Out[15]: 'CIRU'
Filtrar Strings
Supongamos que quiero conocer cuantas veces aparece la letra "a" en mi string. Te presento
al método count():
Out[1]: 3
También puedo usar el mismo método para contar los espacios en blanco de un string.
Out[2]: 5
Genial. Entonces también puedo aprovechar este método para contar la cantidad de
palabras que hay en un string, siempre y cuando agregue una unidad al final para contar la
palabra que aparece luego del último espacio.
El problema se presentaría si por error mi string tuviese espacios extra ya sea al comienzo o
al final, ya que eso desvirtuaría la cuenta, y no representaría la cantidad de palabras.
Esto se puede resolver con el método strip() que sirve para eliminar los espacios vacíos al
comienzo o al final de un string.
¿Y si lo que quiero no es saber cuantas palabras hay en un string, sino conocer cuáles son las
palabras que contiene? La solución es utilizar el método split() que se encarga de separar al
string en múltiples substrings, tomando como separador al caracter que tu elijas. Entonces si
le pedimos que lo separe en base a los espacios vacíos, recibiremos la lista de substrings que
corresponde a las palabras completas.
In [1]: input()
Hola Mundo
Out[1]: 'Hola Mundo'
Si escribes una instrucción dentro de los paréntesis, el usuario recibirá ese mensaje antes de
ingresar su información
Dime tu edad:48
Out[2]: '48'
Para poder almacenar el ingreso del usuario (lo que te permitirá luego poder manipular esa
información), debes guardar el input dentro de una variable:
Los ingresos de usuario siempre serán almacenados como strings, aunque el usuario ingrese
números
Dime tu edad:48
In [5]: type(edad)
Out[5]: str
Si necesitas que ese ingreso sea tratado como número para poder operaciones con él,
recuerda que cuentas con el método int()
Dime tu edad:48
In [7]: type(edad)
Out[7]: int
Una manera alternativa de hacer lo mismo (más extensa pero más legible), sería la siguiente:
Dime tu edad:48
In [9]: type(edad)
Out[9]: int
Y ahora le demos una aplicación práctica a lo que hemos aprendido. Vamos a crear un
pequeño código que le pida dos números al usuario, y le devuelva la suma de esos números.
También vimos que si queremos mostrar valores numéricos en nuestros strings, primero
debemos cambiar su tipo de dato
In [2]: edad = 30
In [3]: frase = saludo + " " + nombre + ", tienes " + str(edad) + " años"
frase
Pero existe un método que hace que este trabajo sea aún más sencillo y fácil de leer: el
método format(), que consiste en dejar llaves curvas en los lugares donde deberían ir
determinados valores clave, y luego colocar esos valores (en orden) dentro de los
parámetros de format.
A pesar de que esta es una forma mucho más sencilla de formatear cadenas, python ha
desarrollado una versión reducida de format() que hace que los strings compuestos sean
aún más fáciles de leer.
Consiste en colocar la letra f (de format) antes del string, y luego colocar los valores clave
directamente dentro de las llaves curvas.
Observa que con ambos abordajes de format() no es necesario modificar los valores
numéricos para integrarlos a nuestros strings.
Listas
Las listas son otro tipo de datos propio de python. Lo primero que hay que saber sobre las
listas es que una lista es una colección de objetos. Vamos a crear una lista vacía.
In [1]: frutas = []
In [2]: type(frutas)
Out[2]: list
Ahora reescribamos nuestra lista, para asignarle tres elementos de tipo string
In [4]: type(frutas)
Out[4]: list
Out[5]: list
Las listas pueden contener todo tipo de datos, incluso puedes crear listas que contengan...
listas
In [6]: misListas = [[10, 20, 30], ["a", "b", "c"], ["Pablo", "Micaela", "Milena"]]
type(misListas)
Out[6]: list
In [8]: type(a)
Out[8]: list
Sin embargo, esta es una muy mala práctica que en casi ningún caso va a tener utilidad
precisa, y que siempre es conveniente evitar. A medida que avancemos descubrirás por qué.
Avancemos. Veamos cómo acceder a los elementos de una lista. Lo hacemos de la misma
manera que accedemos a los índices de un string
In [9]: frutas[0]
Out[9]: 'banana'
¿Y en el caso de una lista de listas? ¿Como accedo a un elemento que se encuentra dentro
de una lista que a su vez se encuentra dentro de otra lista?
Primero creas un juego de llaves con el índice de la lista que contiene tu elemento buscado,
e inmediatamente agregas otro juego de llaves con el índice del elemento buscado dentro
de la lista que lo contiene directamente.
In [10]: misListas[2][1]
Out[10]: 'Micaela'
Para modicificar un elemento individual dentro de una lista, primero accedes a él con el
índice, y le reasignas un contenido con el operador =, seguido del nuevo valor.
In [12]: frutas.append("mango")
frutas
El método sort() sirve para ordenar alfabéticamente (o en órden numérico ascendente) los
elementos de tu lista.
In [13]: frutas.sort()
frutas
In [14]: frutas.sort(reverse=True)
frutas
In [15]: frutas.remove("manzana")
frutas
In [16]: frutas.reverse()
frutas
El método len() permite conocer el largo de la lista (es decir: cuántos elementos contiene).
In [17]: len(frutas)
Out[17]: 3
Este es uno de los tantos mpetodos que no son exclusivos de las listas, sino que es aplicable
a todos los objetos que contienen secuencias de elementos. Podemos aplicarlo, por ejemplo,
con un string.
In [18]: len("federico")
Out[18]: 8
Out[19]: [1, 2, 3, 4, 5, 6]
In [20]: type(combinada)
Out[20]: list
Podemos multiplicar el contenido de una lista, haciendo que se repita tantas veces como
necesitemos, con el operador *.
Out[21]: [1, 2, 3, 1, 2, 3, 1, 2, 3]
Y finalmente podemos crear una nueva lista a partir de un segmento de otra lista.
Out[22]: [2, 3, 4]
Tuplas
Las tuplas (o tuples, o tapls... no hay consenso sobre cómo pronunciar esto), también son
una estructura de datos, es decir que son una colección de objetos, al igual que las listas.
En pocas palabras una tupla es una colección de elementos ordenados y no modificables.
Se parece a una lista, pero la diferencia principal es que la tupla, una vez creada, no puede
cambiar sus elementos ni su tamaño.
Entonces: * las listas son colecciones mutables * las tuplas son coleciones inmutables.
In [1]: t = 1, 2
type(t)
Out[1]: tuple
In [2]: tt = (1, 2)
type(tt)
Out[2]: tuple
En las tuplas sí tiene sentido agrupar elementos de diferentes tipos, ya que su principal uso
suele ser el de agrupar información diversa sobre un mismo objeto.
Out[3]: tuple
Al igual que en las listas puedo acceder a sus objetos individuales con las reglas de
indexación.
Out[4]: 3
Out[5]: (2, 3)
Como dijimos al comienzo, las tuplas no pueden modificarse (son inmutables), por lo tanto,
si intento reasignarle un nuevo valor a alguno de sus componentes, voy a obtener un error
de tipo (TypeError)
In [6]: mi_tupla[1] = 8
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[6], line 1
----> 1 mi_tupla[1] = 8
¿Qué cosas sí puedo hacer con las tuplas? Bueno, todo lo que nos permitan hacer sus
métodos.
In [7]: dir(mi_tupla)
Out[7]: ['__add__',
'__class__',
'__class_getitem__',
'__contains__',
'__delattr__',
'__dir__',
'__doc__', '__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getnewargs__',
'__getstate__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__', '__len__',
'__lt__', '__mul__',
'__ne__', '__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rmul__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'count', 'index']
In [8]: mi_tupla.count(2)
Out[8]: 3
In [9]: mi_tupla.index(3)
Out[9]: 2
Out[10]: 3
Esto no te lo expliqué antes, pero también puedes hacerlo con las listas
Out[11]: 3
En este punto podrías estar pensando que si la única diferencia entre listas y tuplas es que las
tuplas no pueden modificarse, entonces ¿para qué queremos las tuplas si son iguales a las
listas pero más limitadas?
Bueno, justamente esa limitación es lo que las hace ser muy útiles para ciertas circunstancias.
Puntualmente para aquellas situaciones en las que quieres almacenar información de un
modo seguro y que no se modifique nunca. Un ejemplo sencillo y cotidiano del uso de tuplas
La tupla es perfecta para esto porque una vez que defines una fecha de cumpleaños, ya no
necesitas cambiarla. La inmutabilidad de las tuplas asegura que los datos de la fecha
permanezcan constantes.
cliente1
In [14]: cliente1[0][1]
Out[14]: 'Pérez'
Una ventaja de las tuplas es que son computacionalmente más rápidas que las listas,
porque las tuplas se almacenan en un solo bloque de memoria, por lo que crear una nueva
tupla implica, en el peor de los casos, una única llamada para asignar memoria. Y al ser
inmutables significa que el intérprete de python puede usar una estructura de datos más
ligera y rápida, en comparación con las listas.
Quiero mostrarte una cosa más, y es que Python tiene una característica de asignación de
tuplas muy poderosa que permite una tupla de variables.
Out[17]: ('fiesta', 5)
Obviamente, para que esto no de error, tiene que haber siempre la misma cantidad de
variables que de elementos en el taple.
Diccionarios
Los diccionarios son otros tipo de datos en Python, y también, al igual que las listas y las
tuplas, son un tipo de datos que se caracteriza por ser una colección de elementos. Es decir
que los diccionarios también son una secuencia de elementos. Ya veremos en qué se
diferencia de las listas y las tuplas.
Para declarar un diccionario usamos llaves curvas (o corchetes). Este es un diccionario vacío:
In [1]: dic = {}
type(dic)
Out[1]: dict
Los diccionarios en python, al igual que los diccionarios en la vida real, tienen una serie de
elementos que se componen, cada uno, de una clave y un valor.
Así como los diccionarios de la vida real tienen elementos que se componen de una palabra
y su definición, los elementos de los diccionarios de python tienen una clave, y un valor.
Un tema importante sobre los diccionarios, es que las claves tienen que ser únicas. No
puedes repetir el nombre de las claves, para que de ese modo luego sea posible buscar
los elementos de los diccionarios a partir de sus claves.
Este límite no aplica para los valores, ya que los valores pueden repetirse tantas veces
como necesites.
Al igual que a otras colecciones puedo aplicarle el método len() para conocer su tamaño.
In [3]: len(edades)
Out[3]: 2
Una cosa que podríamos sentirnos tentados de hacer, es indexarlos usando la sitaxis...
edades[0]
Pero este abordaje te devolvería un error, ya que no podemos invocar al índice de los
diccionarios, simplemente porque los diccionarios no son secuencias ordenadas de
elementos. Esto significa que sus elementos internos no tienen ningún orden específico. La
idea de los diccionarios es que sus elementos sean hallados por su clave, y no de otra
manera.
Si yo quiero obtener la edad de Juan, en vez de llamar a edades[0] lo hago a través de su
clave
In [4]: edades["Juan"]
Out[4]: 25
Si quiero reasignar a Juan una nueva edad (es decir, un nuevo valor)
In [5]: edades["Juan"] = 26
edades
In [6]: edades["Laura"] = 28
edades
Veamos qué métodos disponemos para hacer cosas con los diccionarios!
In [7]: dir(edades)
Out[7]: ['__class__',
'__class_getitem__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getstate__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__ior__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__ne__',
'__new__',
'__or__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__reversed__',
'__ror__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'clear',
'copy',
'fromkeys',
'get',
'items',
'keys',
'pop',
'popitem',
'setdefault',
'update',
'values']
Puedes jugar con esa lista de métodos consultando la ayuda para cada uno. Estos son los
más comunes:
In [8]: edades.keys()
Out[8]: dict_keys(['Juan', 'María', 'Laura'])
In [9]: edades.values()
In [10]: edades.items()
In [11]: edades.get("Juan")
Out[11]: 26
In [12]: edades.update({"Juan":27})
edades
Cuando digo que son muy simples, es porque un dato de tipo booleano solo puede tener
dos valores posibles: Verdadero, o Falso… pero en inglés (True o False).
Podemos crear variables de tipo booleano asignandoles directamente los valores booleanos:
In [1]: a = True
type(a)
Out[1]: bool
In [2]: b = False
type(b)
Out[2]: bool
Pero también podemos crear variables booleanas de manera indirecta, que consiste en
asignarles como valor una comparación cuyo resultado solo pueda ser True o False:
In [3]: x = 2
y = 5
x == y
Out[3]: False
In [4]: comparar = x == y
comparar
Out[4]: False
In [5]: type(comparar)
Out[5]: bool
Operador Significado
== Igual
< Menor
> Mayor
!= Distinto
Out[6]: True
Además de poder hacer comparaciones con todos los operadores lógicos de la tabla
anterior, también podemos hacer comparaciones múltiples.
Puedes hacer comparaciones múltiples verificando más de una comparación a la vez,
utilizando los operadores booleanos de la siguiente tabla.
Operador Significado
and "y"
or "ó"
not "no"
Para ver estos operadores en acción, primero vamos a crear una variable adicional
In [7]: z = 8
Y ahora sí, verifiquemos dos comparaciones al mismo tiempo, con el operador and que nos
permite verificar si la comparación 1 Y la comparación 2 son verdaderas.
Out[8]: True
Esta variable tiene valor True porque es verdadero que ambas comparaciones son
verdaderas.
Out[14]: False
Out[10]: True
En Python, el operador not se utiliza para negar una expresión booleana, pero debe ser
aplicado directamente a una única expresión booleana, no entre dos variables como en x not
z.
Out[11]: False
Out[15]: False
Comencemos por el elemento esencial de las estructuras de control que es la palabra *if*
(que en inglés significa si, pero no el sí afirmativo, sino el si condicional).
La sintaxis de if es la siguiente:
if [condición]:
[código a ejecutar]
In [1]: temperatura = 22
Hace calor
En el ejemplo anterior, la condición se cumple (es verdadera), y por eso se ejecuta la línea
condicional.
In [2]: temperatura = 15
¿Lo hacemos aún más interesante? También podemos aprovechar las estructuras de control
para que el programa se comporte de acuerdo a la información que ingrese el usuario:
Dime la temperatura:21
El clima es agradable
Otra opción es usar las estructuras de control para verificar si un determinado elemento se
encuentra en una colección (como por ejemplo una lista), usando la declaración in que
significa en.
if nombre in amigos:
print(f"{nombre} está en mi grupo de amigos")
Dime un nombre:Gabriel
Básicamente if verifica que una condición sea verdadera, por lo que si escribo el valor True
(directa o indirectamente), no necesito hacer una comparación.
if temperatura:
print("Hace calor")
Hace calor
In [12]: if True:
print("Hace calor")
Hace calor
No quiero terminar esta lección sin destacar la importancia de indentar adecuadamente las
lineas de código. El espacio que ponemos en las lineas que estén luego de la declaración if,
deben tener una sangría creada ya sea con el tabulador (tecla TAB) o con 4 espacios en
blanco.
Linea IF:
Linea condicional 1
Linea condicional 2
Esta manera de estructurar la ubicación de las líneas genera una jerarquía de líneas, que
permite que python sepa cuál es el código que debe ejecutarse si se cumple la condición.
Observa este ejemplo:
In [13]: if 10 > 5:
print("Esta linea está dentro del if")
print("Esta linea también está dentro del if")
print("Esta linea está fuera del if y se va a imprimir siempre")
Se imprimieron todas las líneas porque la condición era verdadera. ¿Pero qué lineas se
imprimirpian si la condicion fuera falsa?
Pero también existen otras 2 declaraciones que se complementan con if, para determinar no
sólo si un bloque de código se ejecuta o no, sino también para determinar qué hacer en
caso de que la condición no se cumpla.
Veamos la estructura de control else, que en inglés significa si no, y que utilizamos a para
decir, "si no se cumple la condición, haz lo siguiente".
Y el otro elemento que agregamos a este trío de estructuras de control, es la palabra elif,
que es una abreviatura de la expresión else if, y que significa si no se cumple la condición
anterior, verifica si se cumple la siguiente condición:
Tus estructuras de control pueden seguir complejizándose, ya que puedes seguir agregando
tantos elifs como quieras.
Desafío
Crea un código que le pida 3 números distintos al usuario (vamos a asumir que el usuario no
ingresa números repetidos, para no hacerlo tan complicado). Luego aplica las estructuras de
control para identificar cuál es el mayor de los 3.
Te dejo la siguiente celda vacía para que hagas el intento
In [ ]:
if x1 > x2:
if x1 > x3:
maximo = x1
else:
maximo = x3
elif x2 > x3:
maximo = x2
else:
maximo = x3
print(maximo)
Loop For
¿Qué es un loop?
Los loops son otro de esos conceptos en los que tu cabeza se tiene que preparar para algo
completamente nuevo, y divertido.
En inglés la palabra loop significa bucle o rulo, y hace referencia a algo que, cuando
termina, vuelve a comenzar una y otra vez.
Si llevamos este concepto a la programación, un loop es un bloque de código que se
ejecuta, y al finalizar, se vuelve a ejecutar otra vez, y otra vez, y otra vez, hasta que se
active alguna condición que lo detenga.
La razón por la que existen los loops es para evitar que tengamos que escribir código
repetido cuando necesitamos que una acción se ejecute más de una vez.
En python existen distintos tipos de loops, y vamos a ver los dos más importantes: el loop
for, y el loop while.
Loop For
El loop for es un bucle que se va a repetir tantas veces como elementos encuentre dentro
de una secuencia.
Esta es la sintaxis del loop for:
Esta instrucción le está diciendo a python que tome una colección de datos (o secuencia),
como puede ser una lista, y le dice que por cada uno de sus elementos, ejecute el código
que le pasemos.
Entonces el loop no se va a repetir hasta el infinito, sino hasta que se agote la cantidad de
elementos de la secuencia.
Podemos hacer esto con cualquier tipo de colección como listas, diccionarios, tuplas, e
incluso strings, que son una colección de caracteres. A todos estos tipos de datos, también
los llamamos iterables, porque los loops pueden iterar por cada uno de sus elementos.
Veamos un ejemplo con un string:
In [ ]: for letra in "python":
print(letra)
for p in paises:
largo = len(p)
print(f"{p} tiene {largo} letras")
Lo interesante de este ejercicio es que en cada ciclo del loop la variable largo se sobrescribe
con el valor correspondiente al país que corresponda en cada iteración, y por eso puede
devolver información distinta en cada impresión.
Otro ejercicio interesante sería aplicar una estructura de control dentro del loop, para que
haga comprobaciones en cada ciclo, y arroje resultados diferentes según el valor de cada
iteración.
In [ ]: for p in paises:
if len(p) > 6:
print(f"{p} tiene nombre largo")
else:
print(f"{p} tiene nombre corto")
Y para terminar hagamos un pequeño juego extra. Vamos a anidar loops, es decir que
vamos a poner un loop dentro de otro, e intentaremos comprender cómo se comportan
estos artefactos.
Voy a crear una estructura de dos loops anidados, para que se impriman todas las
combinaciones posibles de los elementos que dispongo en dos listas diferentes:
por favor, tómate unps minutos para analizar lo que ha sucedido en cada iteración del loop.
Piensa en el valor que tienen las variables color y prenda en cada iteración, y cómo eso
determina lo que se imprime en cada línea.
Esta comprensión es crucial para asimilar luego con facilidad el uso de los loops.
Función Range()
En esta lección quiero explicarte la funcion Range (o Rango) y mostrarte cómo podemos
usarla en los loops.
La función range devuelve un rango de números ¿qué rango de números? El que
especifiquemos en sus parámetros.
Si le pedimos que nos pase hasta el 7, nos va a crear un rango de números que comienza en
cero, y que llega hasta 6, porque al igual que con la segmentación, el número que pidamos
como límite superior no va a ser inclusivo.
In [ ]: miRango = range(7)
Para ver cada uno de los números que contiene mi rango, podemos iterar en el con un loop
for
In [ ]: for n in miRango:
print(n)
Entonces aquí ya estamos viendo un uso que podemos darle a los rangos. Cuando
necesitamos que un loop for itere un determinado número de veces, pero no tenemos una
colección con esa cantidad de elementos, simplemente creamos un rango con el solo fin de
tener la cantidad de elementos necesarios para decirle al loop "quiero que iteres 5 veces", o
las que sean necesarias.
Entonces si ponemos un solo número en range vamos a obtener los números que van
desde cero hasta su inmediato anterior, ascendiendo de uno en uno.
Pero si escribimos dos números, separados por coma, nuestra serie de números ahora va a
comenzar por el primer número y a terminar, como antes, en el inmediato anterior del
segundo número.
for n in miRango:
print(n)
Y si agrego un tercer elemento, le estaré indicando a range qué tan largo deben ser los
pasos que debe dar. En este ejemplo, va a crecer de 2 en 2.
for n in miRango:
print(n)
Y por supuesto que podemos reemplazar los parámetros de range por variables, en el caso
de que necesitemos que nuestros rangos sean de largo variable. Mira este ejemplo:
In [ ]: palabra = "python"
for n in range(len(palabra)):
print(n)
Loop While
La principal diferencia del loop while con el loop for, es que while no se va a repetir un
número predeterminado de veces, sino que se va a repetir constantemente, y solo se va a
detener cuando una condición deje de cumplirse.
Por eso se llama loop while, porque en inglés while significa mientras. Entonces el loop while
se va a seguir repitiendo mientras que la condición sea verdadera.
In [ ]: contador = 0
Debes ser muy cuidadoso al escribir loops while, porque si no has configurado
adecuadamente la condición de corte, tu loop se va a repetir hasta el infinito (o mejor dicho,
hasta que tu ordenador se quede sin recursos).
Si por accidente o descuido llegas a ejecutar el siguiente loop while...
... la salida de la celda conezará a devolver numeros 0 sin parar. Si eso llega a suceder, la
solución será ir a Kernel / Restart & Clear Output.
Break y Continue
Hay dos palabras clave que puedes utilizar en los loops (tanto while como for), y son las
palabras break y continue.
In [ ]: contador = 0
En este ejemplo, el loop seguirá iterando una y otra vez mientras que contador sea menor a
10, y en cada iteración imprimirá el valor de contador.
Pero hay dos incidencias preparadas:
In [ ]: range()
type()
len()
In [ ]: "Hola".upper()
[1, 2, 3].sort()
(1, 2, 3).count()
nombre_funcion(parámetros)
Todas las funciones que vimos hasta ahora son funciones que ya vienen incorporadas a
python, y como te dije hay muchísimas que ni siquiera hemos visto, pero que están a tu
disposición para encontrarlas usando type, dir y help en cada caso.
Pero lo que veremos en esta lección, es que no solamente podemos usar las funciones
incorporadas en python, sino también crear nuestras propias funciones ¿suena bien,
verdad?
Vamos a crear nuestra primera función usando la palabra def, que significa definición:
In [2]: saludo()
Hola mundo
Una vez que has definido una función, esta ya existe en el contexto de tu programa (este
cuaderno), y puedes llamarla tantas veces como quieras, sin tener que escribir su código otra
vez.
In [3]: saludo()
Hola mundo
La definición de la función saludo tiene sus paréntesis vacíos, por lo tanto esa función no
espera que le pasemos ningún parámetro al momento de llamarla.
Pero si colocamos una o más variables dentro de los paréntesis al momento de definirla,
eso significa que cuando la llamemos, tengamos que pasar valores (parámetros) dentro de
los paréntesis. Estos valores pueden ser usados por el código interno de la función.
In [5]: tu_saludo("federico")
Hola federico
In [6]: tu_saludo("Juana")
Hola Juana
La mayoría de las veces vamos a querer que nuestras funciones, al terminar, hagan una de
estas dos cosas:
Las funciones que hicimos hasta ahora solo han mostrado algo en pantalla, pero no han
devuelto nada que podamos seguir utilizando en el código siguiente.
Para lograr que nuestras funciones nos devuelvan nueva información que podamos seguir
manipulando, usamos la palabra return:
In [8]: sumar(2, 3)
Out[8]: 5
Ahora dispongo de una variable llamada numero que contiene el valor devuelto por la
función sumar(), y puedo disponer de él para hacer nuevas cosas en mi código.
In [10]: numero
Out[10]: 5
In [11]: numero * 2
Out[11]: 10
Dentro de nuestras funciones podemos poner cualquier tipo de código, como loops o
estructuras de control.
En el siguiente ejemplo, voy a crear una función que pida un número, y que imprima todos
los número pares que hay desde 1 hasta el número ingresado.
In [13]: imprimir_pares_hasta(6)
2
4
6
Las funciones van a tener un peso crítico en tu desarrollo como programador, así que
permítete el tiempo para practicar, y de a poco ir tomándoles la mano.
Funciones que Llaman Funciones
Es importante entender que las funciones son casi el corazón lógico de la programación,
porque son las encargadas de organizar y estructurar el funcionamiento de tu programa.
Mientras más puedas dividir tu código en funciones separadas, más eficiente y ordenado
será tu código, y además más facil de mantener.
Puede que con lo que vimos hasta ahora, esto no haya sido tan evidente, pero en esta
lección te voy a enseñar a llamar a funciones desde las funciones, y esto va a hacer que
puedas ver con más claridad cómo esto ayuda a que nuestros programas se parezcan más a
eso, a verdaderos programas.
Veamos un pequeño ejemplo de cómo implementarlo. Voy a crear dos funciones que se
encarguen de preguntar el nombre y el apellido del usuario.
In [ ]: def pedir_nombre():
nombre = input("Dime tu nombre: ")
return nombre
In [ ]: def pedir_apellido():
apellido = input("Dime tu apellido: ")
return apellido
Ahora voy a crear una función que se encargue de saludar al usuario, pero que, en vez de
preguntar los datos por su cuenta, lo que haga sea llamar a las funciones que se encargan
de esa tarea.
In [ ]: def saludar():
saludo = f"Hola {pedir_nombre()} {pedir_apellido()}"
print(saludo)
In [ ]: saludar()
Ahora tengo una función que se encarga de llamar a otras funciones, y que recibe lo que
esas funciones devuelven, y lo usa en su código.
In [ ]: mi_lista = [1, 2, 3, 4, 5]
def cuadrado(n):
return n * n
def calcular_lista(numeros):
for numero in numeros:
resultado = cuadrado(numero)
print(f"El cuadrado de {numero} es {resultado}")
In [ ]: calcular_lista(mi_lista)