Introducción a Python
1. Resumen
Vamos a hacer una breve introducción a Python, explicando los tipos de datos que tenemos, los operadores, el uso de funciones y de clases. Además, veremos cómo usar los objetos iterables, cómo usar módulos, etc.
2. Tipos de datos de Python
Existen 7 tipos de datos en Python
- De tipo texto:
str
- Numéricos:
int
,float
,complex
- Secuencias:
list
,tuple
,range
- Mapping:
dict
- Sets:
set
,frozenset
- Booleanos:
bool
- Binarios:
bytes
,bytearray
,memoryview
Podemos obtener el tipo de dato mediante la función type()
type(5.)
float
Python es un lenguaje de tipado dinámico, es decir, puedes tener una variable de un tipo y luego asignarle otro tipo
a = 5type(a)
int
a = 'MaximoFN'type(a)
str
Python tipea las variables por ti, pero si las quieres tipear tú se puede hacer
b = int(5.1)type(b), b
(int, 5)
Aunque b
se ha inicializado como 5.1
, es decir, debería ser de tipo float
, al tiparlo nosotros a tipo int
, vemos que es de tipo int
y además su valor es 5
2.1. Strings
Los strings
son cadenas de caracteres, estas se pueden definir con doble comilla "
o comilla simple '
string = "MaximoFN"string
'MaximoFN'
string = 'MaximoFN'string
'MaximoFN'
Para escribir un string
muy largo y no tener una fila que ocupe mucho espacio se puede introducir en varias líneas
string = """Este es un ejemplo decomo estoy introduciendo un stringen varias lineas"""string
'Este es un ejemplo de como estoy introduciendo un string en varias lineas'
string = '''Este es un ejemplo decomo estoy introduciendo un stringen varias lineas'''string
'Este es un ejemplo de como estoy introduciendo un string en varias lineas'
Sin embargo vemos que en medio ha metido el carácter \n
, este carácter indica el salto de línea. Si usamos la función print()
veremos como ya no aparece
print(string)
Este es un ejemplo decomo estoy introduciendo un stringen varias lineas
Como hemos dicho los strings son cadenas de caracteres, por lo que podemos navegar e iterar a través de ellos
for i in range(10):# Se indica a la función print que cuando imprima no termine con un salto de# linea para escribir todo en la misma lineaprint(string[i], end='')
Este es un
Podemos obtener la longitud de nuestro string mediante la función len()
len(string)
73
Chequear si hay algún string determinado dentro del nuestro
'ejemplo' in string
True
Los strings tienen ciertos atributos útiles, como poner todo en mayúsculas
print(string.upper())
ESTE ES UN EJEMPLO DECOMO ESTOY INTRODUCIENDO UN STRINGEN VARIAS LINEAS
Todo en minúsculas
print(string.lower())
este es un ejemplo decomo estoy introduciendo un stringen varias lineas
Reemplazar caracteres
print(string.replace('o', '@'))
Este es un ejempl@ dec@m@ est@y intr@duciend@ un stringen varias lineas
Obtener todas las palabras
print(string.split())
['Este', 'es', 'un', 'ejemplo', 'de', 'como', 'estoy', 'introduciendo', 'un', 'string', 'en', 'varias', 'lineas']
Puedes ver todos los métodos de los string en este enlace
Otra cosa útil que se puede hacer con los strings es concatenarlos
string1 = 'Maximo'string2 = 'FN'string1 + string2
'MaximoFN'
Antes explicamos que el carácter \n
correspondía a un salto de línea, este carácter especial corresponde a una serie de caracteres especiales llamados Escape Characters
. Veamos otros
Si declaramos un string con doble comilla y queremos añadir una doble comilla dentro del string usamos el escape character \"
print("Este es el blog de \"MaximoFN\"")
Este es el blog de "MaximoFN"
Lo mismo con la comilla simple, añadimos \'
print('Este es el blog de \'MaximoFN\'')
Este es el blog de 'MaximoFN'
Ahora tenemos el problema de si queremos añadir el carácter \
ya que como hemos visto es un escape character
, así que lo solucionamos poniendo doble barra (backslash) \\
print('Este es el blog de \\MaximoFN\\')
Este es el blog de \MaximoFN\
Ya vimos antes el escape character
de nueva línea \n
print('Este es el blog de \nMaximoFN')
Este es el blog deMaximoFN
Si queremos escribir desde el inicio de línea añadimos \r
print('Esto no se imprimirá \rEste es el blog de MaximoFN')
Este es el blog de MaximoFN
Si queremos añadir un espacio grande (sangría) usamos \t
print('Este es el blog de \tMaximoFN')
Este es el blog de MaximoFN
Podemos borrar un carácter con \b
print('Este es el blog de \bMaximoFN')
Este es el blog deMaximoFN
Podemos añadir el código ASCII en octal mediante \ooo
print('\115\141\170\151\155\157\106\116')
MaximoFN
O añadir el código ASCII en hexadecimal mediante \xhh
print('\x4d\x61\x78\x69\x6d\x6f\x46\x4e')
MaximoFN
Por último, podemos convertir otro tipo de dato a string
n = 5print(type (n))string = str(n)print(type(string))
<class 'int'><class 'str'>
2.2. Números
2.2.1. Enteros
Números de tipo entero
n = 5n, type(n)
(5, int)
2.2.2. Float
Números de tipo de coma flotante
n = 5.1n, type(n)
(5.1, float)
2.2.3. Complejos
Números complejos
n = 3 + 5jn, type(n)
((3+5j), complex)
2.2.4. Conversión
Se puede convertir entre tipos de números
n = 5n = float(n)n, type(n)
(5.0, float)
n = 5.1n = complex(n)n, type(n)
((5.1+0j), complex)
n = 5.1n = int(n)n, type(n)
(5, int)
No se puede convertir un número complex
a tipo int
o tipo float
2.3. Secuencias
2.3.1. Listas
Las listas guardan múltiples ítems en una variable. Se declaran mediante los símbolos []
, con los ítems separados por comas
lista = ['item0', 'item1', 'item2', 'item3', 'item4', 'item5']lista
['item0', 'item1', 'item2', 'item3', 'item4', 'item5']
Podemos obtener la longitud de una lista mediante la función len()
len(lista)
6
Las listas pueden tener ítems de distintos tipos
lista = ['item0', 1, True, 5.3, "item4", 5, 6.6]lista
['item0', 1, True, 5.3, 'item4', 5, 6.6]
En Python se empieza a contar desde la posición 0, es decir, si queremos obtener la primera posición de la lista
lista[0]
'item0'
Pero una de las cosas potentes de Python es que si queremos acceder a la última posición podemos usar índices negativos
lista[-1]
6.6
Si en vez de la última posición de la lista queremos la penúltima
lista[-2]
5
Si solo queremos un rango de valores, por ejemplo, del segundo al quinto ítem accedemos mediante [2:5]
lista[2:5]
[True, 5.3, 'item4']
Si se omite el primer número del rango significa que queremos desde el primer ítem de la lista hasta el ítem indicado, es decir, si queremos desde el primer ítem hasta el quinto usamos [:5]
lista[:5]
['item0', 1, True, 5.3, 'item4']
Si se omite el último número del rango significa que queremos desde el ítem indicado hasta el último, es decir, si queremos desde el tercer ítem hasta el último usamos [3:]
lista[3:]
[5.3, 'item4', 5, 6.6]
Podemos escoger el rango de ítems también con números negativos, es decir, si queremos desde el antepenúltimo hasta el penúltimo usamos [-3:-1]
. Esto es útil cuando se tiene listas que no se sabe su longitud, pero se sabe que se quiere un rango de valores del final, porque por ejemplo, la lista se ha creado con medidas que se van tomando y se quiere saber las últimas medias
lista[-3:-1]
['item4', 5]
Se puede comprobar si un ítem está en la lista
'item4' in lista
True
2.3.1.1. Editar listas
Las listas en Python son dinámicas, es decir, se pueden modificar. Por ejemplo se puede modificar el tercer ítem
lista[2] = Falselista
['item0', 1, False, 5.3, 'item4', 5, 6.6]
También se puede modificar un rango de valores
lista[1:4] = [1.1, True, 3]lista
['item0', 1.1, True, 3, 'item4', 5, 6.6]
Se pueden agregar valores al final de la lista mediante el método append()
lista.append('item7')lista
['item0', 1.1, True, 3, 'item4', 5, 6.6, 'item7']
O podemos insertar un valor en una posición determinada mediante el método insert()
lista.insert(2, 'insert')lista
['item0', 1.1, 'insert', True, 3, 'item4', 5, 6.6, 'item7']
Se pueden unir listas mediante el método extend()
lista2 = ['item8', 'item9']lista.extend(lista2)lista
['item0', 1.1, 'insert', True, 3, 'item4', 5, 6.6, 'item7', 'item8', 'item9']
No es necesario extender la lista mediante otra lista, se puede hacer mediante otro tipo de dato iterable de Python (tuplas
, sets
, diccionarios
, etc)
tupla = ('item10', 'item11')lista.extend(tupla)lista
['item0',1.1,'insert',True,3,'item4',5,6.6,'item7','item8','item9','item10','item11']
Podemos eliminar una posición determinada mediante el método pop()
lista.pop(2)lista
['item0',1.1,True,3,'item4',5,6.6,'item7','item8','item9','item10','item11']
Si no se especifica el índice se elimina el último ítem
lista.pop()lista
['item0', 1.1, True, 3, 'item4', 5, 6.6, 'item7', 'item8', 'item9', 'item10']
O se puede eliminar un item sabiendo su valor mediante el método remove()
lista.remove('item7')lista
['item0', 1.1, True, 3, 'item4', 5, 6.6, 'item8', 'item9', 'item10']
Con la función del()
se puede eliminar también un ítem de la posición indicada
del lista[3]lista
['item0', 1.1, True, 'item4', 5, 6.6, 'item8', 'item9', 'item10']
Si no se indica el índice se elimina la lista completa
Con el método clear()
deja la lista vacía
lista.clear()lista
[]
Se puede obtener la cantidad de ítems con un valor determinado mediante el método count()
lista = [5, 4, 6, 5, 7, 8, 5, 3, 1, 5]lista.count(5)
4
También se puede obtener el primer índice de un ítem con un valor determinado mediante el método index()
lista = [5, 4, 6, 5, 7, 8, 5, 3, 1, 5]lista.index(5)
0
2.3.1.2. List comprehension
Podemos operar a traves de la lista
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]newlist = []# Iteramos por todos los items de la listafor x in fruits:# Si el item contiene el caracter "a" lo añadimos a newlistif "a" in x:newlist.append(x)newlist
['apple', 'banana', 'mango']
Otras de las cosas potentes de Python son las list comprehension
, que permiten hacer todo en una sola línea y que el código quede más compacto
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]newlist = [x for x in fruits if "a" in x]newlist
['apple', 'banana', 'mango']
La sintaxis es la siguiente:
newlist = [expression for item in iterable if condition == True]
Se puede aprovechar para realizar operaciones en la lista original
newlist = [x.upper() for x in fruits if "a" in x]newlist
['APPLE', 'BANANA', 'MANGO']
2.3.1.3. Ordenar listas
Para ordenar listas usamos el método sort()
lista = [5, 8, 3, 4, 9, 5, 6]lista.sort()lista
[3, 4, 5, 5, 6, 8, 9]
También nos las ordena alfabéticamente
lista = ["orange", "mango", "kiwi", "pineapple", "banana"]lista.sort()lista
['banana', 'kiwi', 'mango', 'orange', 'pineapple']
A la hora de ordenar alfabéticamente distingue entre mayúsculas y minúsculas
lista = ["orange", "mango", "kiwi", "Pineapple", "banana"]lista.sort()lista
['Pineapple', 'banana', 'kiwi', 'mango', 'orange']
Se pueden ordenar en orden descendente mediante el atributo reverse = True
lista = [5, 8, 3, 4, 9, 5, 6]lista.sort(reverse = True)lista
[9, 8, 6, 5, 5, 4, 3]
Se pueden ordenar de la manera que queramos mediante el atributo key
def myfunc(n):# devuelve el valor absoluto de n - 50return abs(n - 50)lista = [100, 50, 65, 82, 23]lista.sort(key = myfunc)lista
[50, 65, 23, 82, 100]
Se puede aprovechar esto para que, por ejemplo, a la hora de ordenar no distinga entre mayúsculas y minúsculas
lista = ["orange", "mango", "kiwi", "Pineapple", "banana"]lista.sort(key = str.lower)lista
['banana', 'kiwi', 'mango', 'orange', 'Pineapple']
Se puede invertir la lista mediante el método reverse
lista = [5, 8, 3, 4, 9, 5, 6]lista.reverse()lista
[6, 5, 9, 4, 3, 8, 5]
2.3.1.4. Copiar listas
No se pueden copiar listas mediante lista1 = lista2
, ya que si se modifica lista1
también se modifica lista2
lista1 = [5, 8, 3, 4, 9, 5, 6]lista2 = lista1lista1[0] = Truelista2
[True, 8, 3, 4, 9, 5, 6]
Por lo que hay que usar el método copy()
lista1 = [5, 8, 3, 4, 9, 5, 6]lista2 = lista1.copy()lista1[0] = Truelista2
[5, 8, 3, 4, 9, 5, 6]
Ó hay que usar el constructor de listas list()
lista1 = [5, 8, 3, 4, 9, 5, 6]lista2 = list(lista1)lista1[0] = Truelista2
[5, 8, 3, 4, 9, 5, 6]
2.3.1.5. Concatenar listas
Se pueden concatenar listas mediante el operador +
lista1 = [5, 8, 3, 4, 9, 5, 6]lista2 = ['a', 'b', 'c']lista = lista1 + lista2lista
[5, 8, 3, 4, 9, 5, 6, 'a', 'b', 'c']
O mediante el método extend
lista1 = [5, 8, 3, 4, 9, 5, 6]lista2 = ['a', 'b', 'c']lista1.extend(lista2)lista1
[5, 8, 3, 4, 9, 5, 6, 'a', 'b', 'c']
Otra forma de concatenar es repetir la tupla X veces mediante el operador *
lista1 = ['a', 'b', 'c']lista2 = lista1 * 3lista2
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']
2.3.2. Tuplas
Las tuplas son similares a las listas, guardan múltiples ítems en una variable, pueden contener ítems de distintos tipos, pero no se pueden modificar, ni reordenar. Se definen mediante ()
, con los ítems separados por comas
Al no poderse modificar hace que las tuplas se ejecuten un poco más rápido que las listas, por lo que si no necesitas modificar los datos es mejor utilizar tuplas en vez de listas
tupla = ('item0', 1, True, 3.3, 'item4', True)tupla
('item0', 1, True, 3.3, 'item4', True)
Se puede obtener su longitud mediante la función len()
len (tupla)
6
Para crear tuplas con un único elemento es necesario añadir una coma
tupla = ('item0',)tupla, type(tupla)
(('item0',), tuple)
Para acceder a un elemento de la tupla se procede igual que con las listas
tupla = ('item0', 1, True, 3.3, 'item4', True)print(tupla[0])print(tupla[-1])print(tupla[2:4])print(tupla[-4:-2])
item0True(True, 3.3)(True, 3.3)
Podemos comprobar si hay un ítem en la tupla
'item4' in tupla
True
2.3.2.1. Modificar tuplas
Aunque las tuplas no son modificables, se pueden modificar convirtiéndolas a listas, modificando la lista y después volviéndola a convertir a tupla
lista = list(tupla)lista[4] = 'ITEM4'tupla = tuple(lista)tupla
('item0', 1, True, 3.3, 'ITEM4', True)
Al convertirla a lista podemos hacer todas las modificaciones vistas en las listas
Lo que sí se puede es eliminar la tupla entera
del tuplaif 'tupla' not in locals():print("tupla eliminada")
tupla eliminada
2.3.2.2. Desempaquetar tuplas
Cuando creamos tuplas, en realidad estamos empaquetando datos
tupla = ('item0', 1, True, 3.3, 'item4', True)tupla
('item0', 1, True, 3.3, 'item4', True)
pero podemos desempaquetarlos
item0, item1, item2, item3, item4, item5 = tuplaitem0, item1, item2, item3, item4, item5
('item0', 1, True, 3.3, 'item4', True)
Si queremos sacar menos datos que la longitud de la tupla añadimos un *
item0, item1, item2, *item3 = tuplaitem0, item1, item2, item3
('item0', 1, True, [3.3, 'item4', True])
Se puede poner el asterisco *
en otra parte si por ejemplo lo que queremos es el último ítem
item0, item1, *item2, item5 = tuplaitem0, item1, item2, item5
('item0', 1, [True, 3.3, 'item4'], True)
2.3.2.3. Concatenar tuplas
Se pueden concatenar tuplas mediante el operador +
tupla1 = ("a", "b" , "c")tupla2 = (1, 2, 3)tupla3 = tupla1 + tupla2tupla3
('a', 'b', 'c', 1, 2, 3)
Otra forma de concatenar es repetir la tupla X veces mediante el operador *
tupla1 = ("a", "b" , "c")tupla2 = tupla1 * 3tupla2
('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')
2.3.2.4. Métodos de las tuplas
Las tuplas tienen dos métodos, el primero es el método count()
que devuelve el número de veces que existe un ítem dentro de la tupla
tupla = (5, 4, 6, 5, 7, 8, 5, 3, 1, 5)tupla.count(5)
4
Otro método es index()
que devuelve la primera posición de un ítem dentro de la tupla
tupla = (5, 4, 6, 5, 7, 8, 5, 3, 1, 5)tupla.index(5)
0
2.3.3. Range
Con range()
podemos crear una secuencia de números, comenzando desde 0 (de forma predeterminada), se incrementa en 1 (de forma predeterminada) y se detiene antes de un número especificado
range(start, stop, step)
Por ejemplo si queremos una secuencia de 0 a 5 (sin incluir el 5)
for i in range(5):print(f'{i} ', end='')
0 1 2 3 4
Si por ejemplo no queremos que empiece en 0
for i in range(2, 5):print(f'{i} ', end='')
2 3 4
for i in range(-2, 5):print(f'{i} ', end='')
-2 -1 0 1 2 3 4
Por último, si no queremos que se incremente en 1. Si por ejemplo queremos una secuencia de números pares
for i in range(0, 10, 2):print(f'{i} ', end='')
0 2 4 6 8
2.4. Diccionarios
Los diccionarios se usan para guardar datos en pares key:data
. Son modificables, no ordenados y no permiten duplicidades. Se definen mediante los símbolos {}
. Admiten ítems de distintos tipos de datos
diccionario = {"brand": "Ford","model": "Mustang","year": 1964,"colors": ["red", "white", "blue"]}diccionario
{'brand': 'Ford','model': 'Mustang','year': 1964,'colors': ['red', 'white', 'blue']}
Como se ha dicho no permiten duplicidades
diccionario = {"brand": "Ford","model": "Mustang","year": 1964,"year": 2000,"colors": ["red", "white", "blue"]}diccionario["year"]
2000
Se puede obtener su longitud mediante la función len()
len(diccionario)
4
Como se puede ver la longitud es 4 y no 5, ya que year
lo cuenta solo una vez
2.4.1. Acceder a los ítems
Para acceder a un ítem lo podemos hacer a través de su key
diccionario["model"]
'Mustang'
También se puede acceder mediante el método get()
diccionario.get("model")
'Mustang'
Para saber todas las key
s de los diccionarios se puede usar el método keys()
diccionario.keys()
dict_keys(['brand', 'model', 'year', 'colors'])
Se puede usar una variable para apuntar a las key
s del diccionario, con lo que llamándola una vez es necesario
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se declara una vez la variable que apunta a las keysx = diccionario.keys()print(x)# Se añade una nueva keydiccionario["color"] = "white"# Se consulta la variable que apunta a las keyprint(x)
dict_keys(['brand', 'model', 'year'])dict_keys(['brand', 'model', 'year', 'color'])
Para obtener los valores del diccionario se puede usar el método values()
diccionario.values()
dict_values(['Ford', 'Mustang', 1964, 'white'])
Se puede usar una variable para apuntar a los values
s del diccionario, con lo que llamándola una vez es necesario
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se declara una vez la variable que apunta a los valuesx = diccionario.values()print(x)# Se modifica un valuediccionario["year"] = 2020# Se consulta la variable que apunta a los valuesprint(x)
dict_values(['Ford', 'Mustang', 1964])dict_values(['Ford', 'Mustang', 2020])
Si lo que se quiere son los item
s enteros, es decir key
s y value
s hay que usar el método items()
diccionario.items()
dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 2020)])
Se puede usar una variable para apuntar a los item
s del diccionario, con lo que llamándola una vez es necesario
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se declara una vez la variable que apunta a los itemsx = diccionario.items()print(x)# Se modifica un valuediccionario["year"] = 2020# Se consulta la variable que apunta a los itemsprint(x)
dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 1964)])dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 2020)])
Se puede comprobar si una key
existe en el diccionario
"model" in diccionario
True
2.4.2. Modificar los ítems
Se puede modificar un item
accediendo a él directamente
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se modifica un itemdiccionario["year"] = 2020diccionario
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}
O se puede modificar mediante el método update()
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se modifica un itemdiccionario.update({"year": 2020})diccionario
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}
2.4.3. Añadir ítems
Se puede añadir un item
agregándolo sin más
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se modifica un itemdiccionario["colour"] = "blue"diccionario
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'colour': 'blue'}
O se puede agregar mediante el método update()
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se modifica un itemdiccionario.update({"colour": "blue"})diccionario
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'colour': 'blue'}
2.4.4. Eliminar items
Se puede eliminar un item
con una key
específica mediante el método pop()
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se elimina un itemdiccionario.pop("model")diccionario
{'brand': 'Ford', 'year': 1964}
O se puede eliminar un item
con una key
específica mediante del
indicando el nombre de la key
entre los símbolos []
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se elimina un itemdel diccionario["model"]diccionario
{'brand': 'Ford', 'year': 1964}
Se elimina el diccionario entero si se usa del
y no se especifica la key
de un ítem
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se elimina un itemdel diccionarioif 'diccionario' not in locals():print("diccionario eliminado")
diccionario eliminado
Si lo que se quiere es eliminar el último item
introducido se puede usar el método popitem()
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se elimina el último item introducidodiccionario.popitem()diccionario
{'brand': 'Ford', 'model': 'Mustang'}
Si se quiere limpiar el diccionario hay que usar el método clear()
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}diccionario.clear()diccionario
{}
2.4.5. Copiar diccionarios
No se pueden copiar diccionarios mediante diccionario1 = diccionario2
, ya que si se modifica diccionario1
también se modifica diccionario2
diccionario1 = {"brand": "Ford","model": "Mustang","year": 1964}diccionario2 = diccionario1diccionario1["year"] = 2000diccionario2["year"]
2000
Por lo que hay que usar el método copy()
diccionario1 = {"brand": "Ford","model": "Mustang","year": 1964}diccionario2 = diccionario1.copy()diccionario1["year"] = 2000diccionario2["year"]
1964
Ó hay que usar el constructor de diccionarios dict()
diccionario1 = {"brand": "Ford","model": "Mustang","year": 1964}diccionario2 = dict(diccionario1)diccionario1["year"] = 2000diccionario2["year"]
1964
2.4.6. Diccionarios anidados
Los diccionarios pueden tener items
s de cualquier tipo de dato, incluso otros diccionarios. A este tipo de diccionarios se les denomina diccionarios nested
diccionario_nested = {"child1" : {"name" : "Emil","year" : 2004},"child2" : {"name" : "Tobias","year" : 2007},"child3" : {"name" : "Linus","year" : 2011}}diccionario_nested
{'child1': {'name': 'Emil', 'year': 2004},'child2': {'name': 'Tobias', 'year': 2007},'child3': {'name': 'Linus', 'year': 2011}}
child1 = {"name" : "Emil","year" : 2004}child2 = {"name" : "Tobias","year" : 2007}child3 = {"name" : "Linus","year" : 2011}diccionario_nested = {"child1" : child1,"child2" : child2,"child3" : child3}diccionario_nested
{'child1': {'name': 'Emil', 'year': 2004},'child2': {'name': 'Tobias', 'year': 2007},'child3': {'name': 'Linus', 'year': 2011}}
2.4.7. Métodos de los diccionarios
Estos son los métodos que se pueden usar en los diccionarios
2.4.8. Dictionary comprehension
Igual que podíamos hacer lists comprehensions
mediante la sintaxis
list_comprehension = [expression for item in iterable if condition == True]
Podemos hacer disctionarys comprehensions
mediante la siguiente sintaxis
dictionary_comprehension = [key expresion: value expresion for item in iterable if condition == True]
Veamos un ejemplo
dictionary_comprehension = {x: x**2 for x in (2, 4, 6) if x > 2}dictionary_comprehension
{4: 16, 6: 36}
2.5. Sets
2.5.1. Set
Los sets
se utilizan en python para guardar un conjunto de items en una sola variable. Se puede guardar items de distinto tipo. Son no ordenados y no tienen índice.
Se diferencian de las listas en que no tienen ni orden ni índice.
Se declaran mediante los símbolos {}
Como set
es una palabra reservada en Python creamos un set
con el nombre set_
set_ = {'item0', 1, 5.3, "item4", 5, 6.6}set_
{1, 5, 5.3, 6.6, 'item0', 'item4'}
No puede haber ítems duplicados, si encuentra algún ítem duplicado se queda solo con uno
set_ = {'item0', 1, 5.3, "item4", 5, 6.6, 'item0'}set_
{1, 5, 5.3, 6.6, 'item0', 'item4'}
Se puede obtener la longitud del set
mediante la función len()
len(set_)
6
Como se puede ver la longitud del set es 6 y no 7, ya que se queda con un solo 'item0'
Se puede comprobar si un ítem se encuentra en el set
'item4' in set_
True
2.5.1.1. Añadir ítems
Se puede añadir un ítem al set mediante el método add()
set_.add(8.8)set_
{1, 5, 5.3, 6.6, 8.8, 'item0', 'item4'}
Se puede agregar otro set mediante el método update()
set2 = {"item5", "item6", 7}set_.update(set2)set_
{1, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5', 'item6'}
También se pueden añadir ítems de tipos de datos iterables de Python
lista = ["item9", 10, 11.2]set_.update(lista)set_
{1, 10, 11.2, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5', 'item6', 'item9'}
2.5.1.2. Eliminar ítems
Se puede eliminar un ítem determinado mediante el método remove()
set_.remove('item9')set_
{1, 10, 11.2, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5', 'item6'}
O mediante el método discard()
set_.discard('item6')set_
{1, 10, 11.2, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5'}
Mediante el método pop()
se puede eliminar el último item, pero como los set
s no son ordenados no hay manera de saber cuál es el último item. El método pop()
devuelve el item eliminado
print(f"set antes de pop(): {set_}")eliminado = set_.pop()print(f"Se ha eliminado {eliminado}")
set antes de pop(): {1, 5, 5.3, 6.6, 8.8, 7, 10, 11.2, 'item5', 'item0', 'item4'}Se ha eliminado 1
Mediante el método clear()
se puede vaciar el conjunto
set_.clear()set_
set()
Por último, con del
se puede eliminar el set
del set_if 'set_' not in locals():print("set eliminado")
set eliminado
2.5.1.3. Unir ítems
Una forma de unir sets es mediante el método union()
set1 = {"a", "b" , "c"}set2 = {1, 2, 3}set3 = set1.union(set2)set3
{1, 2, 3, 'a', 'b', 'c'}
Otra forma es mediante el método update()
, pero de esta manera se añade un set en otro, no se crea uno nuevo
set1 = {"a", "b" , "c"}set2 = {1, 2, 3}set1.update(set2)set1
{1, 2, 3, 'a', 'b', 'c'}
Estos métodos de unión eliminan los duplicados, pero si queremos obtener los ítems duplicados en dos sets usamos el método intersection()
set1 = {"apple", "banana", "cherry"}set2 = {"google", "microsoft", "apple"}set3 = set1.intersection(set2)set3
{'apple'}
Si queremos obtener los ítems duplicados en dos sets, pero sin crear un set nuevo, usamos el método intersection_update()
set1 = {"apple", "banana", "cherry"}set2 = {"google", "microsoft", "apple"}set1.intersection_update(set2)set1
{'apple'}
Ahora al revés, si queremos quedarnos con los no duplicados usamos el método symmetric_difference()
.
La diferencia entre eso y la unión entre dos sets es que en la unión se queda con todos los ítems, pero los que están duplicados solo los coge una vez. Ahora nos quedamos con los que no están duplicados
set1 = {"apple", "banana", "cherry"}set2 = {"google", "microsoft", "apple"}set3 = set1.symmetric_difference(set2)set3
{'banana', 'cherry', 'google', 'microsoft'}
Si queremos quedarnos con los no duplicados sin crear un set nuevo usamos el método symmetric_difference_update()
set1 = {"apple", "banana", "cherry"}set2 = {"google", "microsoft", "apple"}set1.symmetric_difference_update(set2)set1
{'banana', 'cherry', 'google', 'microsoft'}
2.5.1.4. Métodos de los sets
Estos son los métodos que se pueden usar en los sets
2.5.2. Frozenset
Los frozenset
s son como los set
s pero con la salvedad de que son inmutables, al igual que las tupla
s son como las list
s pero inmutables. Por lo que no podremos añadir o eliminar items
2.6. Booleanos
Hay solo dos booleanos en Python: True
y False
Mediante la función bool()
se puede evaluar si cualquier cosa es True
o False
print(bool("Hello"))print(bool(15))print(bool(0))
TrueTrueFalse
2.6.1. Otros tipos de datos True o False
Los siguientes datos son True
:
- Cualquier string que no esté vacío
- Cualquier número excepto el 0
- Cualquier lista, tupla, diccionario o set que no esté vacío
print(bool("Hola"))print(bool(""))
TrueFalse
print(bool(3))print(bool(0))
TrueFalse
lista = [1, 2, 3]print(bool(lista))lista = []print(bool(lista))
TrueFalse
tupla = (1, 2, 3)print(bool(tupla))tupla = ()print(bool(tupla))
TrueFalse
diccionario = {"brand": "Ford","model": "Mustang","year": 1964,"colors": ["red", "white", "blue"]}print(bool(diccionario))diccionario.clear()print(bool(diccionario))
TrueFalse
set_ = {'item0', 1, 5.3, "item4", 5, 6.6}print(bool(set_))set_.clear()print(bool(set_))
TrueFalse
2.7. Binarios
2.7.1. Bytes
El tipo bytes
es una secuencia inmutable de bytes. Solo admiten caracteres ASCII. También se pueden representar los bytes mediante números enteros cuyos valores deben cumplir 0 <= x < 256
Para crear un tipo byte debemos introducir antes el carácter b
byte = b"MaximoFN"byte
b'MaximoFN'
También se pueden crear mediante su constructor bytes()
byte = bytes(10)byte
b' '
byte = bytes(range(10))byte
b' '
Se pueden concatenar bytes mediante el operador +
byte1 = b'DeepMax'byte2 = b'FN'byte3 = byte1 + byte2byte3
b'DeepMaxFN'
O mediante la repetición con el operador *
byte1 = b'MaximoFN 'byte2 = byte1 * 3byte2
b'MaximoFN MaximoFN MaximoFN '
Podemos comprobar si un carácter está dentro de la cadena
b'D' in byte1
False
Estos son los métodos que se pueden usar en los bytes
2.7.2. Bytearray
Los bytearray
s son iguales que los bytes
solo que son mutables
byte_array = bytearray(b'MaximoFN')byte_array
bytearray(b'MaximoFN')
2.7.3. Memoryview
Los objetos memoryview
permiten que el código Python acceda a los datos internos de un objeto que admite el protocolo de buffer sin realizar copias.
La función memoryview()
permite el acceso directo de lectura y escritura a los datos orientados a bytes de un objeto sin necesidad de copiarlos primero. Eso puede generar grandes ganancias de rendimiento cuando se opera con objetos grandes, ya que no crea una copia al cortar.
Protocolo de búfer, puede crear otro objeto de acceso para modificar los datos grandes sin copiarlos. Esto hace que el programa utilice menos memoria y aumenta la velocidad de ejecución.
byte_array = bytearray('XYZ', 'utf-8')print(f'Antes de acceder a la memoria: {byte_array}')mem_view = memoryview(byte_array)mem_view[2]= 74print(f'Después de acceder a la memoria: {byte_array}')
Antes de acceder a la memoria: bytearray(b'XYZ')Después de acceder a la memoria: bytearray(b'XYJ')
3. Operadores
3.1. Operadores aritméticos
Operador suma +
3 + 5
8
Operador resta -
3 - 5
-2
Operador multiplicación *
3 * 5
15
Operador división /
3 / 5
0.6
Operador módulo %
. Devuelve el resto de una división
25 % 2
1
Operador exponente **
5 ** 2
25
Operador división entera //
25 // 2
12
3.2. Operadores de comparación
Operador es igual ==
1 == 1
True
Operador es distinto !=
1 != 2
True
Operador es mayor que >
3 > 2
True
Operador es menor que <
2 < 3
True
Operador es mayor o igual que >=
3 >= 3
True
Operador es menor o igual que <=
3 <= 3
True
3.3. Operadores lógicos
Operador and
True and True
True
Operador or
True or False
True
Operador not
not False
True
3.4. Operadores de identidad
Operador is
5.3 is 5.3
True
Operador is not
5.3 is not 5
True
3.5. Operadores de pertenencia
Operador in
x = ["apple", "banana"]"banana" in x
True
Operador not in
x = ["apple", "banana"]"orange" not in x
True
3.6. Operadores bit a bit
Operador AND &
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101c = a & b; # 12 = 0000 1100c
12
Operador OR |
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101c = a | b; # 61 = 0011 1101c
61
Operador XOR ^
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101c = a ^ b; # 49 = 0011 0001c
49
Operador NOT ~
a = 60 # 60 = 0011 1100c = ~a; # -61 = 1100 0011c
-61
Operador desplazamiento hacia la izquierda <<
a = 60 # 60 = 0011 1100c = a << 2; # 240 = 1111 0000c
240
Operador desplazamiento hacia la derecha >>
a = 60 # 60 = 0011 1100c = a >> 2; # 15 = 0000 1111c
15
3.7. Operadores de asignación
Operador =
a = 5a
5
Operador +=
. x += y
es equivalente a x = x + y
a += 5a
10
Operador -=
. x -= y
es equivalente a `x = x - y
a -= 5a
5
Operador *=
. x *= y
es equivalente a `x = x * y
a *= 3a
15
Operador /=
. x /= y
es equivalente a `x = x / y
a /= 3a
5.0
Operador %=
. x %= y
es equivalente a `x = x % y
a = 25a %= 2a
1
Operador //=
. x //= y
es equivalente a `x = x // y
a = 25a //= 2a
12
Operador **=
. x **= y
es equivalente a `x = x ** y
a = 5a **= 2a
25
Operador &=
. x &= y
es equivalente a `x = x & y
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101a &= b; # 12 = 0000 1100a
12
Operador |=
. x |= y
es equivalente a x = x | y
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101a |= b; # 61 = 0011 1101a
61
Operador ^=
. x ^= y
es equivalente a `x = x ^ y
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101a ^= b; # 49 = 0011 0001a
49
Operador >>=
. x >>= y
es equivalente a `x = x >> y
a = 60 # 60 = 0011 1100a <<= 2; # 240 = 1111 0000a
240
Operador <<=
. x <<= y
es equivalente a x = x << y
a = 60 # 60 = 0011 1100a >>= 2; # 15 = 0000 1111a
15
4. Control de flujo
Para poder utilizar las herramientas de control de flujo es necesario añadir la sentencia, dos puntos :
y en una nueva línea escribir el código con indentación
A diferencia de otros lenguajes, Python necesita la indentación (añadir un espacio en blanco) para definir el código de dentro de una herramienta de control de flujo
4.1. If
Mediante if
podemos crear condiciones
if len('MaximoFN') == 8:print('MaximoFN tiene 8 caracteres')
MaximoFN tiene 8 caracteres
Si queremos crear más de una condición podemos usar elif
if len('MaximoFN') < 8:print('MaximoFN tiene menos de 8 caracteres')elif len('MaximoFN') == 8:print('MaximoFN tiene 8 caracteres')
MaximoFN tiene 8 caracteres
Si lo que queremos es que se ejecute algo en caso de que no se cumpla ninguna de las condiciones indicadas podemos usar else
if len('MaximoFN') < 8:print('MaximoFN tiene menos de 8 caracteres')elif len('MaximoFN') > 8:print('MaximoFN tiene más de 8 caracteres')else:print('MaximoFN tiene 8 caracteres')
MaximoFN tiene 8 caracteres
Si queremos escribir todo en una sola línea
if len('MaximoFN') == 8: print('MaximoFN tiene 8 caracteres')
MaximoFN tiene 8 caracteres
Igual, si queremos escribir todo en una línea, pero con varias condiciones
print('MaximoFN tiene menos de 8 caracteres') if len('MaximoFN') < 8 else print('MaximoFN tiene más de 8 caracteres') if len('MaximoFN') > 8 else print('MaximoFN tiene 8 caracteres')
MaximoFN tiene 8 caracteres
Si por ejemplo queremos hacer la estructura del if
pero no queremos, de momento, codificar una de las condiciones, podemos usar pass
if len('MaximoFN') < 8:print('MaximoFN tiene menos de 8 caracteres')elif len('MaximoFN') > 8:passelse:print('MaximoFN tiene 8 caracteres')
MaximoFN tiene 8 caracteres
4.2. While
El bucle while
se ejecuta mientras la condición sea True
i = 0string = 'MaximoFN'while len(string) > i:print(string[i], end='')i += 1
MaximoFN
Si queremos que el bucle pare por alguna condición usamos break
i = 0string = 'MaximoFN'while len(string) > i:if string[i] == 'F':breakprint(string[i], end='')i += 1
Maximo
Si queremos que una de las iteraciones no se ejecute por alguna razón usamos continue
i = 0string = 'Maximo FN'while len(string) > i:if string[i] == ' ':i += 1continueprint(string[i], end='')i += 1
MaximoFN
Mediante else
se puede ejecutar un bloque de código si la condición del while
no es True
i = 0string = 'MaximoFN'while len(string) > i:print(string[i], end='')i += 1else:print("\nSe ha terminado el while")
MaximoFNSe ha terminado el while
4.3. For
El bucle for
se usa para ejecutar código mientras se itera por una secuencia, esta secuencia puede ser cualquier elemento iterable de Python (string
, lista
, tupla
, range
, diccionario
, set
)
string = 'MaximoFN'for x in string:print(x, end='')
MaximoFN
lista = ['M', 'a', 'x', 'i', 'm', 'o', 'F', 'N']for x in lista:print(x, end='')
MaximoFN
tupla = ('M', 'a', 'x', 'i', 'm', 'o', 'F', 'N')for x in tupla:print(x, end='')
MaximoFN
string = 'MaximoFN'for i in range(len(string)):print(string[i], end='')
MaximoFN
diccionario = {"letra1": "M","letra2": "a","letra3": "x","letra4": "i","letra5": "m","letra6": "o","letra7": "F","letra8": "N",}for x in diccionario.values():print(x, end='')
MaximoFN
También se puede iterar por los set
s, pero como son elementos no ordenados, no tendremos control del orden de ejecución
set_ = {'M', 'a', 'x', 'i', 'm', 'o', 'F', 'N'}for x in set_:print(x, end='')
NximoaMF
Si queremos que el bucle pare por alguna condición usamos break
string = 'MaximoFN'for x in string:if x == 'F':breakprint(x, end='')
Maximo
Si queremos que una de las iteracciones no se ejecute por alguna razón usamos continue
string = 'Maximo FN'for x in string:if x == ' ':continueprint(x, end='')
MaximoFN
Mediante else
se puede ejecutar un bloque de código si la condición del while
no es True
string = 'MaximoFN'for x in string:print(x, end='')else:print("\nSe ha terminado el for")
MaximoFNSe ha terminado el for
Si por ejemplo queremos hacer la estructura del for
pero no queremos, de momento, codificar el interior podemos usar pass
string = 'MaximoFN'for x in string:passprint('Interior del for no codificado')
Interior del for no codificado
5. Funciones
Una función es una porción de código que se puede ejecutar tantas veces como quieras. Se le puede pasar argumentos y puede devolver datos como resultado
Para definir una función se comienza con la palabra reservada def
seguido del nombre de la función, paréntesis ()
, dos puntos :
y a continuación en una nueva línea indentado el código de la función
def funcion():print('MaximoFN')
Para llamar a la función solo es necesario escribir su nombre
def funcion():print('MaximoFN')funcion()
MaximoFN
A las funciones se les pueden pasar todos los argumentos que se quiera, dentro de los paréntesis y separados por comas
def funcion(string1, string2):print(string1 + ' ' + string2)funcion("Hola", "MaximoFN")
Hola MaximoFN
Cuando se llama a la función hay que pasarle el mismo número de argumentos que se han declarado, si se pasan más o menos obtendríamos un error.
Si no sabemos los argumentos que va a recibir la función se puede usar *args
, es decir, poniendo un *
antes de los argumentos se indica que el número de argumentos es libre.
Al hacer esto se le pasa una tupla
(recordemos que es inmutable) con los argumentos
def funcion(*argumentos):numero_argumentos = len(argumentos)for i in range(numero_argumentos):print(argumentos[i], end=' ')funcion("funcion", "con", "varios", "argumentos", "sin", "especificar", "cuantos")
funcion con varios argumentos sin especificar cuantos
En caso de no saber el orden de los argumentos de una función, podemos indicar el argumento que le queremos pasar indicándole su nombre
def funcion(argumento1, argumento2, argumento3):print(argumento1 + ' '+ argumento2 + ' ' + argumento3)funcion(argumento3 = "MaximoFN", argumento1 = "Blog", argumento2 = "de")
Blog de MaximoFN
En caso de querer pasar los argumentos con su nombre, pero en caso de no saber cuántos argumentos se van a pasar se puede usar **kargs
. En este caso se le pasará un diccionario con los argumentos
def funcion(**kargumentos):print("Autor del blog: " + kargumentos["autor"])funcion(blog = "Blog", pertenencia = "de", autor = "MaximoFN")
Autor del blog: MaximoFN
Si queremos que algún argumento tenga un valor por defecto lo podemos indicar entre los paréntesis de la función. De esta manera si a la hora de llamar a la función no se pasa dicho argumento, este en la función tendrá el valor por defecto
def funcion(argumento1, argumento2, argumento3 = "MaximoFN"):print(argumento1 + ' '+ argumento2 + ' ' + argumento3)funcion("Blog", "de")
Blog de MaximoFN
Se puede pasar cualquier tipo de dato como argumento, por ejemplo si se pasa una lista
como argumento, dentro de la función, dicho argumento será tratado como una lista
def funcion(argumento):longitud_lista = len(argumento)for i in range(longitud_lista):print(argumento[i], end=' ')funcion(["Blog", "de", "MaximoFN"])
Blog de MaximoFN
Las funciones pueden devolver datos, esto se hace mediante la palabra reservada return
def funcion(argumento):longitud_lista = len(argumento)string = ""for i in range(longitud_lista):string = string + argumento[i] + ' 'return stringprint(funcion(["Blog", "de", "MaximoFN"]))
Blog de MaximoFN
Pueden devolver más de un dato
def funcion(argumento):longitud_lista = len(argumento)string0 = argumento[0]string1 = argumento[1]string2 = argumento[2]return string0, string1, string2dato0, dato1, dato2 = funcion(["Blog", "de", "MaximoFN"])print(dato0 + ' ' + dato1 + ' ' + dato2)
Blog de MaximoFN
Si uno de los datos devueltos no nos interesa podemos pasar de él mediante _
def funcion(argumento):longitud_lista = len(argumento)string0 = argumento[0]string1 = argumento[1]string2 = argumento[2]return string0, string1, string2_, _, dato_de_interes = funcion(["Blog", "de", "MaximoFN"])print(dato_de_interes)
MaximoFN
Si por ejemplo queremos hacer la estructura de la función pero no queremos, de momento, codificar el interior podemos usar pass
def funcion():passfuncion()
Una función puede llamarse a si misma, a esto se le llama recursión o recursividad de la función.
Por ejemplo podemos usar esta cualidad para calcular el factorial de un número
def funcion():passfuncion()def factorial(n):if n == 0 or n == 1:return 1else:return n * factorial(n-1)factorial(5)
120
5.1. Built in functions
Hay una serie de funciones ya definidas en Python que se pueden usar, como por ejemplo la función abs()
, que devuelve el valor absoluto
abs(-5)
5
A continuación se muestra una lista de estas funciones
import builtinsdir(builtins)
['ArithmeticError','AssertionError','AttributeError','BaseException','BlockingIOError','BrokenPipeError','BufferError','BytesWarning','ChildProcessError','ConnectionAbortedError','ConnectionError','ConnectionRefusedError','ConnectionResetError','DeprecationWarning','EOFError','Ellipsis','EnvironmentError','Exception','False','FileExistsError','FileNotFoundError','FloatingPointError','FutureWarning','GeneratorExit','IOError','ImportError','ImportWarning','IndentationError','IndexError','InterruptedError','IsADirectoryError','KeyError','KeyboardInterrupt','LookupError','MemoryError','ModuleNotFoundError','NameError','None','NotADirectoryError','NotImplemented','NotImplementedError','OSError','OverflowError','PendingDeprecationWarning','PermissionError','ProcessLookupError','RecursionError','ReferenceError','ResourceWarning','RuntimeError','RuntimeWarning','StopAsyncIteration','StopIteration','SyntaxError','SyntaxWarning','SystemError','SystemExit','TabError','TimeoutError','True','TypeError','UnboundLocalError','UnicodeDecodeError','UnicodeEncodeError','UnicodeError','UnicodeTranslateError','UnicodeWarning','UserWarning','ValueError','Warning','ZeroDivisionError','__IPYTHON__','__build_class__','__debug__','__doc__','__import__','__loader__','__name__','__package__','__spec__','abs','all','any','ascii','bin','bool','breakpoint','bytearray','bytes','callable','chr','classmethod','compile','complex','copyright','credits','delattr','dict','dir','display','divmod','enumerate','eval','exec','filter','float','format','frozenset','get_ipython','getattr','globals','hasattr','hash','help','hex','id','input','int','isinstance','issubclass','iter','len','license','list','locals','map','max','memoryview','min','next','object','oct','open','ord','pow','print','property','range','repr','reversed','round','set','setattr','slice','sorted','staticmethod','str','sum','super','tuple','type','vars','zip']
5.2. Documentación de una función
Se puede añadir una explicación de una función que creemos mediante un comentario al inicio de la función, de esta manera cuando llamemos a la built in function
help()
nos mostrará dicha explicación.
def funcion():"Esta es la explicación de la función"Nonehelp(funcion)
Help on function funcion in module __main__:funcion()Esta es la explicación de la función
Otra opción para ver la explicación de la función es usar el método __doc__
de la función
funcion.__doc__
'Esta es la explicación de la función'
5.3. Decoradores
Los decoradores son una funcionalidad de Python que permiten añadir características nuevas a una función
Se crea una función decorador que tiene como parámetro otra función. Entonces la función decorador añade la característica nueva a la función que recibe
def decorador(parametro_funcion):"""Agrega barritas arriba y abajo de la funcion"""def envoltorio():"""Aplica las barritas al texto"""print("==================")parametro_funcion()print("==================")return envoltoriodef funcion():print("MaximoFN")funcion_envoltorio = decorador(funcion)print('Función sin decoradores: ')funcion()print('\nFunción con decoradores: ')funcion_envoltorio()
Función sin decoradores:MaximoFNFunción con decoradores:==================MaximoFN==================
Pero otra manera más potente de usar los decoradores es mediante el uso de @
y el nombre del decorador antes de la función.
Es decir, primero se define el decorador y a continuación se llama a una función con el decorador definido
def decorador2(parametro_funcion2):"""Agrega barritas arriba y abajo de la funcion"""def envoltorio2():"""Aplica las barritas al texto"""print("==================")parametro_funcion2()print("==================")return envoltorio2@decorador2def funcion2():print("MaximoFN")print('Función con decoradores: ')funcion2()
Función con decoradores:==================MaximoFN==================
5.4. *args
y **kwargs
*args
y **kwargs
son argumentos opcionales que se pueden usar al definir una función en Python. La sintaxis es la siguiente:
def mi_funcion(arg1, arg2, *args, **kwargs):
# código de la función aquí
5.4.1. *args
*args
se usa para enviar un número variable de argumentos a una función. Al usar *args
, puedes enviar una cantidad variable de argumentos a la función sin tener que especificar el número exacto de argumentos que necesita la función. Los argumentos se reciben en la función como una tupla.
def saludo(saludo, *nombres):for nombre in nombres:print(f"{saludo}, {nombre}")saludo("Hola", "Alicia", "Roberto", "Carlos")
Hola, AliciaHola, RobertoHola, Carlos
5.4.2. **kwargs
**kwargs
se usa de la misma manera, pero para enviar un número variable de argumentos con palabras clave (keyword arguments
) a una función. Al usar **kwargs
, puedes enviar una cantidad variable de argumentos a la función y especificar el valor de cada argumento usando su nombre. Los argumentos se reciben en la función como un diccionario.
def saludo(saludo, **personas):for key, value in personas.items():print(f"{saludo} {key}, tu edad es {value} años")saludo("Hola", Juan=22, Maria=32, Pedro=25)
Hola Juan, tu edad es 22 añosHola Maria, tu edad es 32 añosHola Pedro, tu edad es 25 años
6. Funciones adicionales
6.1. Funciones lambda
Una función lambda es una pequeña función anónima.
Una función lambda puede tomar cualquier número de argumentos, pero solo puede tener una expresión.
Las funciones lambda se definen de la siguiente manera:
lambda arguments : expression
x = lambda a : a + 10print(x(5))
15
x = lambda a, b, c : a + b + cprint(x(5, 6, 2))
13
El poder de lambda se muestra mejor cuando las usa como una función anónima dentro de otra función.
def myfunc(n):return lambda a : a * nmydoubler = myfunc(2)mytripler = myfunc(3)print(f"mydoubler: {mydoubler(11)}")print(f"mytripler: {mytripler(11)}")
mydoubler: 22mytripler: 33
6.2. Función map
La función map
permite aplicar a cada elemento de una estructura iterable una función
lista = [1, 2, 3]def funcion_mas_1(valor):return valor + 1lista_modificada = list(map(funcion_mas_1, lista))lista_modificada
[2, 3, 4]
Esto es equivalente a usar list comprehension
lista_modificada = [funcion_mas_1(x) for x in lista]lista_modificada
[2, 3, 4]
6.3. Función filter
La función filter
permite seleccionar los elementos de una estructura iterable que cumplan con una característica
lista = [1, 2, 3, 4, 5, 6, 7]def esPar(valor):return valor % 2 == 0lista_filtrada = list(filter(esPar, lista))lista_filtrada
[2, 4, 6]
Esto es equivalente a usar list comprehension
lista_filtrada = [x for x in lista if esPar(x)]lista_filtrada
[2, 4, 6]
6.4. Función reduce
La función reduce
permite realizar tareas acumulativas en estructuras iterables
from functools import reducelista = [1, 22, 33]def acumular(valor, acumulador):print(f'valor = {valor}, acumulador = {acumulador}, acumulacion = {valor + acumulador}')return valor + acumuladoracumulacion = reduce(acumular, lista)print(f'\nacumulacion = {acumulacion}')
valor = 1, acumulador = 22, acumulacion = 23valor = 23, acumulador = 33, acumulacion = 56acumulacion = 56
6.5. Función zip
Con la función zip
se puede comprimir varias estructuras iterables en una sola, es decir permite agrupar varias estructuras Ax en una sola estructura B. La estructura B está formada por tuplas de los elementos de las estructuras Ax
nombres = ["Manolo", "Andres", "Fernando"]altura = [181, 178, 180]my_zip = list(zip(nombres, altura))my_zip
[('Manolo', 181), ('Andres', 178), ('Fernando', 180)]
6.5. Generadores
Supongamos que queremos iterar sobre una secuencia de números, pero de una manera especial que no nos ofrece ningún tipo de bucle, pues esto lo podemos solucionar con los generadores. Para poder hacer esto, la función generadora no tiene que devolver el valor con return
, sino con yield
para que sepa que tiene que seguir iterando
def iterador_custom(N):for i in range (N):if i % 3 == 0:yield igenerador = iterador_custom(20)for i in generador:print(i)
0369121518
Acabamos de hacer un iterador por números múltiplos de 3
6.6. High order functions
Podemos crear funciones que reciben otras funciones como parámetros, de manera que la función que recibe otra función como parámetro se llama función de orden superior (high order function). Veamos un ejemplo
def increment(x):return x + 1def hof(f, x):return 2*f(x)print(hof(increment, 3))
8
7. Clases y objetos
Python es un lenguaje de programación orientado a objetos. Casi todo en Python es un objeto, con sus propiedades y métodos.
Una clase es como un constructor de objetos o un "plano" para crear objetos.
Para crear una clase se usa la palabra reservada class
class Clase:variable = 'MaximoFN'
Una vez creada la clase se puede crear un objeto de dicha clase
class Clase:variable = 'MaximoFN'objeto = Clase()Clase.variable
'MaximoFN'
Normalmente las clases tienen una función inicial, que se ejecuta cuando se crea un objeto de la clase. Esta función se denomina dunder init y se escribe __init__()
. A la función dunder init se le tiene que pasar siempre la variable self
, que indica la propia clase, y a continuación, las variables que se quiera
Con esta función se suelen inicializar las variables de las clases, o se ejecuta el código que se necesite cuando se crea un objeto de la clase
class Persona:def __init__(self, nombre, edad):self.nombre = nombreself.edad = edadobjeto_persona = Persona("Miguel", 36)print(objeto_persona.nombre)print(objeto_persona.edad)
Miguel36
Además de la función inicial dunder init, se pueden crear más funciones. A estas funciones se les llama métodos de la clase. A estos métodos siempre hay que pasarles la variable self
class Persona:def __init__(self, nombre, edad):self.nombre = nombreself.edad = edaddef saludar(self):print(f'Hola mi nombre es {self.nombre} y tengo {self.edad} años')objeto_persona = Persona("Miguel", 36)objeto_persona.saludar()
Hola mi nombre es Miguel y tengo 36 años
La variable self
no tiene por qué ser llamada self
, puede tener cualquier nombre, pero dentro de cada clase tiene que ser siempre el mismo. Pero por convenio se suele usar self
class Persona:def __init__(yo_mismo, nombre, edad):yo_mismo.nombre = nombreyo_mismo.edad = edaddef saludar(yo_mismo):print(f'Hola mi nombre es {yo_mismo.nombre} y tengo {yo_mismo.edad} años')objeto_persona = Persona("Miguel", 36)objeto_persona.saludar()
Hola mi nombre es Miguel y tengo 36 años
Se pueden modificar las variables de los objetos
objeto_persona.nombre = 'Marta'objeto_persona.saludar()
Hola mi nombre es Marta y tengo 36 años
Incluso eliminarlas
del objeto_persona.nombre
También se puede eliminar el objeto entero
del objeto_persona.nombredel objeto_persona
Si por ejemplo queremos hacer la estructura de la clase pero no queremos, de momento, codificar el interior podemos usar pass
del objeto_persona.nombredel objeto_personaclass Persona:passobjeto_persona = Persona()
7.1. Herencia
La herencia nos permite definir una clase que herede todos los métodos y propiedades de otra clase.
La clase padre es la clase de la que se hereda, también llamada clase base.
La clase hija es la clase que hereda de otra clase, también llamada clase derivada.
Creamos una clase padre
del objeto_persona.nombredel objeto_personaclass Persona:passobjeto_persona = Persona()class Persona:def __init__(self, nombre, apellido):self.nombre = nombreself.apellido = apellidodef imprimir_nombre(self):print(f'Me llamo {self.nombre} {self.apellido}')objeto_padre = Persona("Laura", "Perez")objeto_padre.imprimir_nombre()
Me llamo Laura Perez
Para crear la clase hija hay que indicar entre paréntesis, a la hora de declarar la clase, de qué clase hereda
class Estudiante(Persona):pass
Y a la hora de crear el objeto de la clase hija, se le pasan los parámetros que la clase padre necesita
class Estudiante(Persona):passobjeto_hijo = Estudiante("Mariano", "Sanz")objeto_hijo.imprimir_nombre()
Me llamo Mariano Sanz
Hasta ahora la clase hija ha heredado las funciones de la clase padre, pero podemos modificarlas reescribiéndolas. Por ejemplo reescribiendo la función dunder init.
Si se reescribe la función dunder init, si queremos que se llame a la función dunder init de la clase padre hay que llamarla.
Para esto hay dos maneras, una es mediante el nombre de la clase padre, en este caso hay que pasarle la variable self
class Estudiante(Persona):def __init__(self, nombre, apellido):Persona.__init__(self, nombre, apellido)objeto_hijo = Estudiante("Mariano", "Sanz")objeto_hijo.imprimir_nombre()
Me llamo Mariano Sanz
Otra forma es mediante super()
, en este caso no hace falta pasarle la variable self
class Estudiante(Persona):def __init__(self, nombre, apellido):super().__init__(nombre, apellido)objeto_hijo = Estudiante("Mariano", "Sanz")objeto_hijo.imprimir_nombre()
Me llamo Mariano Sanz
Al modificar las funciones se puede agregar código nuevo
class Estudiante(Persona):def __init__(self, nombre, apellido, curso):Persona.__init__(self, nombre, apellido)self.curso = cursodef imprimir_nombre(self):Persona.imprimir_nombre(self)print(f'Estoy en el curso número {self.curso}')objeto_hijo = Estudiante("Mariano", "Sanz", 4)objeto_hijo.imprimir_nombre()
Me llamo Mariano SanzEstoy en el curso número 4
Por último se pueden agregar nuevos métodos
class Estudiante(Persona):def __init__(self, nombre, apellido, curso):Persona.__init__(self, nombre, apellido)self.curso = cursodef imprimir_nombre(self):Persona.imprimir_nombre(self)print(f'Estoy en el curso número {self.curso}')def imprimir_estudiante(self):print(f"Soy un estudiante del curso número {self.curso}")objeto_hijo = Estudiante("Mariano", "Sanz", 4)objeto_hijo.imprimir_nombre()objeto_hijo.imprimir_estudiante()
Me llamo Mariano SanzEstoy en el curso número 4Soy un estudiante del curso número 4
7.2. Sobrecarga de operadores
Podemos definir operaciones básicas, como la suma, entre varios objetos de una clase. Por ejemplo, si tenemos una clase que representa un vector, podemos definir la suma y la multiplicación entre objetos de dicha clase
class Vector:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):return Vector(self.x + other.x, self.y + other.y)def __mul__(self, other):return Vector(self.x * other.x, self.y * other.y)def __str__(self):return f"Vector ({self.x}, {self.y})"v1 = Vector(1, 2)v2 = Vector(3, 4)print(v1 + v2) # Vector (4, 6)print(v1 * v2) # Vector (3, 8)
Vector (4, 6)Vector (3, 8)
Todas las posibles sobrecargas de operaciones son:
__add__(self, other)
: sobrecarga el operador de suma (+
).__sub__(self, other)
: sobrecarga el operador de resta (-
).__mul__(self, other)
: sobrecarga el operador de multiplicación (*
).__truediv__(self, other)
: sobrecarga el operador de división (/
).__floordiv__(self, other)
: sobrecarga el operador de división de redondeo (//
).__mod__(self, other)
: sobrecarga el operador de módulo (%
).__divmod__(self, other)
: sobrecarga la funcióndivmod()
.__pow__(self, other)
: sobrecarga el operador de potencia (**
).__lshift__(self, other)
: sobrecarga el operador de desplazamiento a la izquierda (<<
).__rshift__(self, other)
: sobrecarga el operador de desplazamiento a la derecha (>>
).__and__(self, other)
: sobrecarga el operador de and (&
).__or__(self, other)
: sobrecarga el operador de or (|
).__xor__(self, other)
: sobrecarga el operador de xor (^
).__lt__(self, other)
: sobrecarga el operador de comparación menor que (<
).__le__(self, other)
: sobrecarga el operador de comparación menor o igual que (<=
).__eq__(self, other)
: sobrecarga el operador de comparación igual a (==
).__ne__(self, other)
: sobrecarga el operador de comparación diferente a (!=
).__gt__(self, other)
: sobrecarga el operador de comparación mayor que (>
).__ge__(self, other)
: sobrecarga el operador de comparación mayor o igual que (>=
).__neg__(self)
: sobrecarga el operador de negación (-
).__pos__(self)
: sobrecarga el operador de posición (+
).__abs__(self)
: sobrecarga la funciónabs()
.__invert__(self)
: sobrecarga el operador de inversión (~
).__complex__(self)
: sobrecarga la funcióncomplex()
.__int__(self)
: sobrecarga la funciónint()
.__float__(self)
: sobrecarga la funciónfloat()
.
7.3. Iteradores personalizados
Como hemos visto en el apartado 2 (Tipos de datos de Python), existen algunos tipos de datos sobre los que se puede iterar. Pero podemos hacernos nuestra propia clase iterable, siempre que tenga las funciones __len__
y __getitem__
class custonIterator:def __init__(self, n):self.items = [i for i in range(n)]def __len__(self):return len(self.items)def __getitem__(self, index):return self.items[index]iterator = custonIterator(10)print(len(iterator)) # 10print(iterator[0]) # 0print(iterator[1]) # 1
1001
Ahora podemos iterar con el objeto de nuestra clase con bucles for
por ejemplo
for i in iterator:print(i, end=" ") # 0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
7.4. Llamada a objetos como funciones
Nos puede interesar llamar a un objeto de una función como una clase, esto se puede conseguir agregando la función __call__
a la clase
class potencia:def __init__(self, base):self.base = basedef __call__(self, potencia):return self.base ** potenciapotencia_cuadrado = potencia(2)print(potencia_cuadrado(3)) # 8
8
7.5. Atributos y funciones privados
Cuando creamos una clase, podemos hacer que algunos atributos o funciones sean privados y no se pueda acceder desde fuera de la clase, para ello hay que añadir __
antes del atributo o clase
class Privados:def __init__(self):self.publico = "Soy público"self.__privado = "Soy privado"def getPrivado(self):return self.__privadodef setPrivado(self, valor):self.__privado = valordef __funcion_privada(self):return "Soy una función privada"def funcion_publica(self):return self.__funcion_privada()privados = Privados()print("Acceso al atributo publico: ", end="")try:print(f"{privados.publico}")except:print("\tNo se puede acceder al atributo privado")print("Acceso al atributo privado: ", end="")try:print(f"{privados.__privado}")except:print("\tNo se puede acceder al atributo privado")print("Acceso al atributo privado mediante el accesor: ", end="")try:print(f"{privados.getPrivado()}")except:print("\tNo se puede acceder al atributo privado mediante el accesor")print("Llamada a la función privada: ", end="")try:print(f"{privados.__funcion_privada()}")except:print("\tNo se puede llamar a la función privada")print("Llamada a la función pública: ", end="")try:print(f"{privados.funcion_publica()}")except:print("\tNo se puede llamar a la función pública")
Acceso al atributo publico: Soy públicoAcceso al atributo privado: No se puede acceder al atributo privadoAcceso al atributo privado mediante el accesor: Soy privadoLlamada a la función privada: No se puede llamar a la función privadaLlamada a la función pública: Soy una función privada
8. Iteradores
Un iterador es un objeto que contiene un número contable de valores.
Un iterador es un objeto sobre el que se puede iterar, lo que significa que puede recorrer todos los valores.
Técnicamente, en Python, un iterador es un objeto que implementa el protocolo del iterador, que consta de los métodos __iter__()
y __next__()
.
Las listas
, tuplas
, diccionarios
y conjuntos son todos objetos iterables. Son contenedores iterables de los que se puede obtener un iterador.
Todos estos objetos tienen un método iter()
que se usa para obtener un iterador:
tupla = ("manzana", "plátano", "cereza")iterable = iter(tupla)print(next(iterable))print(next(iterable))print(next(iterable))
manzanaplátanocereza
string = "plátano"iterable = iter(string)print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')
p l á t a n o
El bucle for
en realidad crea un objeto iterador y ejecuta el método next()
para cada bucle.
tupla = ("manzana", "plátano", "cereza")for x in tupla:print(x)
manzanaplátanocereza
string = "plátano"for x in string:print(x, end=' ')
p l á t a n o
8.1. Crear un objeto iterador
Para crear un objeto/clase como iterador, hay que implementar los métodos __iter__()
y __next__()
.
class Numeros:def __iter__(self):self.a = 1return selfdef __next__(self):x = self.aself.a += 1return xobjeto_iterador = Numeros()iterador = iter(objeto_iterador)print(next(iterador), end=' ')print(next(iterador), end=' ')print(next(iterador), end=' ')print(next(iterador), end=' ')print(next(iterador), end=' ')
1 2 3 4 5
El ejemplo anterior continuaría para siempre si tuviera suficientes llamadas a next()
, o si se usara en un bucle for
.
Para evitar que la iteración continúe para siempre, podemos usar la declaración StopIteration
.
En el método __next__()
, podemos agregar una condición de terminación para generar un error si la iteración se realiza un número específico de veces:
class Numeros:def __iter__(self):self.a = 1return selfdef __next__(self):if self.a <= 20:x = self.aself.a += 1return xelse:raise StopIterationobjeto_iterador = Numeros()iterador = iter(objeto_iterador)for x in iterador:print(x, end=' ')
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
8.2. Iterar obteniendo el índice y el valor
Podemos iterar por un objeto iterable obteniendo en cada iteración su índice y su valor mediante el método enumerate()
string = "MaximoFN"for index, valor in enumerate(string):print(f"En la posición {index}, está el caracter {valor}")
En la posición 0, está el caracter MEn la posición 1, está el caracter aEn la posición 2, está el caracter xEn la posición 3, está el caracter iEn la posición 4, está el caracter mEn la posición 5, está el caracter oEn la posición 6, está el caracter FEn la posición 7, está el caracter N
8.3. Iterar por dos objetos iterables a la vez
Si tenemos dos objetos iterables, cuya longitud sea la misma, podemos iterar por los dos a la vez mediante el método zip()
string1 = 'MaximoFN__'string2 = 'PythonPost'if len(string1) == len(string2):for valor1, valor2 in zip(string1, string2):print(f"En el primer string hay {valor1}, en el segundo string hay {valor2}")
En el primer string hay M, en el segundo string hay PEn el primer string hay a, en el segundo string hay yEn el primer string hay x, en el segundo string hay tEn el primer string hay i, en el segundo string hay hEn el primer string hay m, en el segundo string hay oEn el primer string hay o, en el segundo string hay nEn el primer string hay F, en el segundo string hay PEn el primer string hay N, en el segundo string hay oEn el primer string hay _, en el segundo string hay sEn el primer string hay _, en el segundo string hay t
9. Alcance de variables
Una variable solo está disponible dentro de la región en la que se crea. A esto se le llama alcance
9.1. Alcance local
Una variable creada dentro de una función pertenece al ámbito local de esa función y solo se puede usar dentro de esa función.
def funcion():x = 300print(x)funcion()
300
La variable x
no está disponible fuera de la función, pero está disponible para cualquier función dentro de la función
def funcion():x = 300def funcion_interna():print(x)funcion_interna()funcion()
300
9.2. Alcance global
Una variable creada en el cuerpo principal del código Python es una variable global y pertenece al ámbito global.
Las variables globales están disponibles desde cualquier ámbito, global y local.
x = 300def funcion():print(f'Ámbito local: {x}')funcion()print(f'Ámbito global: {x}')
Ámbito local: 300Ámbito global: 300
Si se crean dos variables, una global y otra local, las dos con el mismo nombre, Python las creará como dos variables distintas
x = 300def funcion():x = 200print(f'Variable local: {x}')funcion()print(f'Variable global: {x}')
Variable local: 200Variable global: 300
Si se necesita crear una variable global, pero está declarada en el ámbito local, se puede usar la palabra clave global
.
La palabra clave global
hace que la variable sea global.
def funcion():global xx = 300funcion()print(f'Variable global: {x}')
Variable global: 300
Además, el uso de la palabra clave global
permite realizar un cambio en una variable global dentro de una función.
x = 300def funcion():global xx = 200funcion()print(f'Variable global: {x}')
Variable global: 200
10. Módulos
Un módulo es un archivo que contiene un conjunto de funciones que desea incluir en su aplicación.
Para crear un módulo, simplemente guarde el código que desea en un archivo con la extensión de archivo .py
Tip: En los cuadernos Jupyter (Colab es un cuaderno Jupyter en línea) si escribimos el carácter
!
antes de un comando podremos ejecutar comandos de consola
Primero vamos a ver en qué directorio estamos, para eso usamos el comando pwd
(print working directory)
!pwd
/home/wallabot/Documentos/web/portafolio/posts
Vamos a crear una carpeta para crear nuestros módulos con el comando mkdir
(make directory)
!mkdir introduccion_python
A continuación veamos qué archivos hay en nuestra carpeta. Esto lo haremos mediante el comando ls
(list)
!mkdir introduccion_python!ls introduccion_python
Vemos que está vacía, creamos un nuevo archivo .py
en el que vamos a crear nuestro módulo
!mkdir introduccion_python!ls introduccion_python%%writefile introduccion_python/modulo1.pydef funcion_del_modulo(nombre):print("Hola, " + nombre)
Writing introduccion_python/modulo1.py
Volvemos a ver qué archivos hay en nuestra carpeta
!ls introduccion_python
modulo1.py __pycache__
Vemos que se ha creado un archivo modulo1.py
. Ya podemos usarlo
Para usar un módulo externo hay que usar la palabra import
. Para usar las funciones del módulo hay que poner primero el nombre del módulo, un .
y a continuación el nombre de la función que se quiere usar
import introduccion_python.modulo1introduccion_python.modulo1.funcion_del_modulo('MaximoFN')
Hola, MaximoFN
Si queremos que dentro de nuestro código, el módulo tenga un nombre determinado podemos usar la palabra as
import introduccion_python.modulo1 as mod1mod1.funcion_del_modulo('MaximoFN')
Hola, MaximoFN
Si el módulo tiene varias funciones, pero solo queremos importar una podemos mediante el uso de las palabras from
e import
. La forma sería
from <modulo> import <funcion>
En este caso no hace falta indicar el nombre del módulo al llamar a la función
%%writefile introduccion_python/modulo2.pydef funcion1_del_modulo(nombre):print("Hola, " + nombre + ", funcion 1")def funcion2_del_modulo(nombre):print("Hola, " + nombre + ", funcion 2")def funcion3_del_modulo(nombre):print("Hola, " + nombre + ", funcion 3")
Writing introduccion_python/modulo2.py
from introduccion_python.modulo2 import funcion2_del_modulofuncion2_del_modulo('MaximoFN')
Hola, MaximoFN, funcion 2
No solo podemos usar módulos creados por nosotros, si no módulos ya instalados (built-in modules
)
Por ejemplo podemos usar el módulo platform
import platformx = platform.system()x
'Linux'
10.1. Entry points: archivos como módulos y no como scripts
Vamos ahora a crear un archivo llamado modulo3.py
%%writefile introduccion_python/modulo3.pyprint("Hola desde modulo3")def funcion_del_modulo():return "Hola desde la función del modulo3"
Overwriting introduccion_python/modulo3.py
Si ahora importamos modulo3.py
para usar la función funcion_del_modulo
veamos qué ocurre
import introduccion_python.modulo3 as mod3print(mod3.funcion_del_modulo())
Hola desde modulo3Hola desde la función del modulo3
Vemos que se ha ejecutado el print
de modulo3.py
, pero no es lo que nosotros queríamos, esto es debido a que al llamarse el archivo modulo3.py
Python lo ejecuta como un script
Pero ¿qué ocurre si queremos ejecutar introduccion_python/main.py
como un script?
!python introduccion_python/modulo3.py
Hola desde modulo3
Vemos que solo se ejecuta el print
, pero no la función funcion_del_modulo
. Si queremos tener la dualidad de funcionalidad del archivo modulo3.py
, es decir, que podamos importarlo desde otro módulo sin que se ejecute como un script y ejecutarlo solo y que se ejecute la función que nosotros queremos, se usa un entry point
. Esto es, usar la condición if __name__ == '__main__':
y a continuación indicar qué queremos que se ejecute. Veámoslo con un ejemplo, voy a reescribir el archivo modulo3.py
%%writefile introduccion_python/modulo3.pyprint("Hola desde modulo3")def funcion_del_modulo():return "Hola desde la función del modulo3"if __name__ == "__main__":funcion_del_modulo()
Overwriting introduccion_python/modulo3.py
Si ahora llamo a main.py
desde otro módulo, ya no se ejecutará el print
import introduccion_python.modulo3 as mod3print(mod3.funcion_del_modulo())
Hola desde la función del modulo3
Y si lo ejecuto como un script independiente, se ejecutará la función funcion_del_modulo
!python introduccion_python/modulo3.py
Hola desde modulo3
11. Paquetes
En Python podemos crearnos nuestros propios paquetes, para ello creamos una carpeta con el nombre del paquete
!mkdir mi_paquete_de_python
Creamos ahora dos archivos dentro
!mkdir mi_paquete_de_python!touch mi_paquete_de_python/modulo1.py mi_paquete_de_python/modulo2.py
Y escribimos en ellos
!mkdir mi_paquete_de_python!touch mi_paquete_de_python/modulo1.py mi_paquete_de_python/modulo2.py%%writefile mi_paquete_de_python/modulo1.pydef funcion1():print("Hola desde la función 1 del módulo 1")def funcion2():print("Hola desde la función 2 del módulo 1")
Overwriting mi_paquete_de_python/modulo1.py
%%writefile mi_paquete_de_python/modulo2.pydef funcion1():print("Hola desde la función 1 del módulo 2")def funcion2():print("Hola desde la función 2 del módulo 2")
Overwriting mi_paquete_de_python/modulo2.py
Ahora podemos llamar a las funciones de nuestro paquete
from mi_paquete_de_python import modulo1 as mod1from mi_paquete_de_python import modulo2 as mod2mod1.funcion1()mod1.funcion2()mod2.funcion1()mod2.funcion2()
Hola desde la función 1 del módulo 1Hola desde la función 2 del módulo 1Hola desde la función 1 del módulo 2Hola desde la función 2 del módulo 2
Pero qué ocurre si nuestro paquete tiene decenas de archivos con funciones que queremos usar, tendríamos que importar todos los archivos uno a uno. Para evitar esto, se puede crear un archivo __init__.py
dentro del paquete donde se haga toda esta importación de archivos
!touch mi_paquete_de_python/__init__.py
!touch mi_paquete_de_python/__init__.py%%writefile mi_paquete_de_python/__init__.pyimport modulo1import modulo2
Overwriting mi_paquete_de_python/__init__.py
Ahora podemos solamente importar nuestro paquete, que ya internamente se han importado todos los módulos
import mi_paquete_de_python as mi_paquetemi_paquete.modulo1.funcion1()mi_paquete.modulo1.funcion2()mi_paquete.modulo2.funcion1()mi_paquete.modulo2.funcion2()
Hola desde la función 1 del módulo 1Hola desde la función 2 del módulo 1Hola desde la función 1 del módulo 2Hola desde la función 2 del módulo 2
De esta manera solo tenemos que hacer un import
12. Try... Except
Cuando ocurre un error, o una excepción como se llama realmente, Python normalmente se detendrá y generará un mensaje de error.
Estas excepciones se pueden manejar usando las declaraciones try
y except
try:print(variable_no_declarada)except:print("Ha ocurrido una excepción")
Ha ocurrido una excepción
Dado que el bloque try
genera un error, entonces se ejecutará el bloque except
Sin el bloque try
, el programa se bloquearía y generaría un error
Se pueden definir tantos bloques de excepción como se desee, por ejemplo, si se quiere ejecutar un bloque de código especial para un tipo de error especial
try:print(variable_no_declarada)except NameError:print("La variable \'variable_no_declarada\' no está definida")except:print("Algo inesperado ha ocurrido")
La variable 'variable_no_declarada' no está definida
Se puede usar la palabra else
para indicar el caso en el que no haya ocurrido un error
try:print('MaximoFN')except NameError:print("Ha ocurrido una excepción")else:print('Todo OK')
MaximoFNTodo OK
con la palabra finally
se ejecutará un código al final haya ocurrido una excepción o no
try:print(variable_no_declarada)except:print("Ha ocurrido una excepción")finally:print("'try except' finallizado")
Ha ocurrido una excepción'try except' finallizado
Esto puede resultar útil para cerrar objetos y limpiar recursos
class Clase:variable = 'MaximoFN'objeto = Clase()try:print(Clase.mi_variable)except:print("Ha ocurrido una excepción")finally:del objeto
Ha ocurrido una excepción
12.1. Crear una excepción
Como desarrollador de Python, se puede elegir lanzar una excepción si ocurre una condición.
Para lanzar (o generar) una excepción, hay que usar la palabra clave raise
def division(numerador, denominador):if denominador == 0:raise Exception("El denominador no puede ser 0")return numerador/denominadorprint(division(10, 0))
---------------------------------------------------------------------------Exception Traceback (most recent call last)<ipython-input-16-33fb6066fa78> in <module>5 return numerador/denominador6----> 7 print(division(10, 0))<ipython-input-16-33fb6066fa78> in division(numerador, denominador)1 def division(numerador, denominador):2 if denominador == 0:----> 3 raise Exception("El denominador no puede ser 0")45 return numerador/denominadorException: El denominador no puede ser 0
Se puede definir qué tipo de error generar y el texto que se imprimirá al usuario
def division(numerador, denominador):if denominador == 0:raise TypeError("El denominador no puede ser 0")return numerador/denominadorprint(division(10, 0))
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-17-26bfa63ae44c> in <module>5 return numerador/denominador6----> 7 print(division(10, 0))<ipython-input-17-26bfa63ae44c> in division(numerador, denominador)1 def division(numerador, denominador):2 if denominador == 0:----> 3 raise TypeError("El denominador no puede ser 0")45 return numerador/denominadorTypeError: El denominador no puede ser 0
13. Keywords o palabras reservadas
Durante este post en varias ocasiones han aparecido palabras reservadas de Python o keyword
s, estas son una serie de palabras reservadas por Python
A continuación se muestra una lista de las keyword
s
import keywordkeyword.kwlist
['False','None','True','and','as','assert','async','await','break','class','continue','def','del','elif','else','except','finally','for','from','global','if','import','in','is','lambda','nonlocal','not','or','pass','raise','return','try','while','with','yield']
14. El Zen de Python
Importando el módulo this
podemos leer el zen
de Python, es decir, su filosofía o principios
import this
The Zen of Python, by Tim PetersBeautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!