Introducción a Python

Introducción a Python Introducción a Python

Introducción a Pythonlink image 0

1. Resumenlink image 1

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.

python

2. Tipos de datos de Pythonlink image 2

Existen 7 tipos de datos en Python

  1. De tipo texto: str
  2. Numéricos: int, float, complex
  3. Secuencias: list, tuple, range
  4. Mapping: dict
  5. Sets: set, frozenset
  6. Booleanos: bool
  7. Binarios: bytes, bytearray, memoryview

Podemos obtener el tipo de dato mediante la función type()

	
type(5.)
Copy
	
float

Python es un lenguaje de tipado dinámico, es decir, puedes tener una variable de un tipo y luego asignarle otro tipo

	
a = 5
type(a)
Copy
	
int
	
a = 'MaximoFN'
type(a)
Copy
	
str

Python tipea las variables por ti, pero si las quieres tipear tú se puede hacer

	
b = int(5.1)
type(b), b
Copy
	
(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. Stringslink image 3

Los strings son cadenas de caracteres, estas se pueden definir con doble comilla " o comilla simple '

	
string = "MaximoFN"
string
Copy
	
'MaximoFN'
	
string = 'MaximoFN'
string
Copy
	
'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 de
como estoy introduciendo un string
en varias lineas"""
string
Copy
	
'Este es un ejemplo de como estoy introduciendo un string en varias lineas'
	
string = '''Este es un ejemplo de
como estoy introduciendo un string
en varias lineas'''
string
Copy
	
'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)
Copy
	
Este es un ejemplo de
como estoy introduciendo un string
en 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 linea
print(string[i], end='')
Copy
	
Este es un

Podemos obtener la longitud de nuestro string mediante la función len()

	
len(string)
Copy
	
73

Chequear si hay algún string determinado dentro del nuestro

	
'ejemplo' in string
Copy
	
True

Los strings tienen ciertos atributos útiles, como poner todo en mayúsculas

	
print(string.upper())
Copy
	
ESTE ES UN EJEMPLO DE
COMO ESTOY INTRODUCIENDO UN STRING
EN VARIAS LINEAS

Todo en minúsculas

	
print(string.lower())
Copy
	
este es un ejemplo de
como estoy introduciendo un string
en varias lineas

Reemplazar caracteres

	
print(string.replace('o', '@'))
Copy
	
Este es un ejempl@ de
c@m@ est@y intr@duciend@ un string
en varias lineas

Obtener todas las palabras

	
print(string.split())
Copy
	
['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
Copy
	
'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\"")
Copy
	
Este es el blog de "MaximoFN"

Lo mismo con la comilla simple, añadimos \'

	
print('Este es el blog de \'MaximoFN\'')
Copy
	
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\\')
Copy
	
Este es el blog de \MaximoFN\

Ya vimos antes el escape character de nueva línea \n

	
print('Este es el blog de \nMaximoFN')
Copy
	
Este es el blog de
MaximoFN

Si queremos escribir desde el inicio de línea añadimos \r

	
print('Esto no se imprimirá \rEste es el blog de MaximoFN')
Copy
	
Este es el blog de MaximoFN

Si queremos añadir un espacio grande (sangría) usamos \t

	
print('Este es el blog de \tMaximoFN')
Copy
	
Este es el blog de MaximoFN

Podemos borrar un carácter con \b

	
print('Este es el blog de \bMaximoFN')
Copy
	
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')
Copy
	
MaximoFN

O añadir el código ASCII en hexadecimal mediante \xhh

	
print('\x4d\x61\x78\x69\x6d\x6f\x46\x4e')
Copy
	
MaximoFN

Por último, podemos convertir otro tipo de dato a string

	
n = 5
print(type (n))
string = str(n)
print(type(string))
Copy
	
<class 'int'>
<class 'str'>

2.2. Númeroslink image 4

2.2.1. Enteroslink image 5

Números de tipo entero

	
n = 5
n, type(n)
Copy
	
(5, int)

2.2.2. Floatlink image 6

Números de tipo de coma flotante

	
n = 5.1
n, type(n)
Copy
	
(5.1, float)

2.2.3. Complejoslink image 7

Números complejos

	
n = 3 + 5j
n, type(n)
Copy
	
((3+5j), complex)

2.2.4. Conversiónlink image 8

Se puede convertir entre tipos de números

	
n = 5
n = float(n)
n, type(n)
Copy
	
(5.0, float)
	
n = 5.1
n = complex(n)
n, type(n)
Copy
	
((5.1+0j), complex)
	
n = 5.1
n = int(n)
n, type(n)
Copy
	
(5, int)

No se puede convertir un número complex a tipo int o tipo float

2.3. Secuenciaslink image 9

2.3.1. Listaslink image 10

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
Copy
	
['item0', 'item1', 'item2', 'item3', 'item4', 'item5']

Podemos obtener la longitud de una lista mediante la función len()

	
len(lista)
Copy
	
6

Las listas pueden tener ítems de distintos tipos

	
lista = ['item0', 1, True, 5.3, "item4", 5, 6.6]
lista
Copy
	
['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]
Copy
	
'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]
Copy
	
6.6

Si en vez de la última posición de la lista queremos la penúltima

	
lista[-2]
Copy
	
5

Si solo queremos un rango de valores, por ejemplo, del segundo al quinto ítem accedemos mediante [2:5]

	
lista[2:5]
Copy
	
[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]
Copy
	
['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:]
Copy
	
[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]
Copy
	
['item4', 5]

Se puede comprobar si un ítem está en la lista

	
'item4' in lista
Copy
	
True
2.3.1.1. Editar listaslink image 11

Las listas en Python son dinámicas, es decir, se pueden modificar. Por ejemplo se puede modificar el tercer ítem

	
lista[2] = False
lista
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
['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
Copy
	
[]

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)
Copy
	
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)
Copy
	
0
2.3.1.2. List comprehensionlink image 12

Podemos operar a traves de la lista

	
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
newlist = []
# Iteramos por todos los items de la lista
for x in fruits:
# Si el item contiene el caracter "a" lo añadimos a newlist
if "a" in x:
newlist.append(x)
newlist
Copy
	
['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
Copy
	
['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
Copy
	
['APPLE', 'BANANA', 'MANGO']
2.3.1.3. Ordenar listaslink image 13

Para ordenar listas usamos el método sort()

	
lista = [5, 8, 3, 4, 9, 5, 6]
lista.sort()
lista
Copy
	
[3, 4, 5, 5, 6, 8, 9]

También nos las ordena alfabéticamente

	
lista = ["orange", "mango", "kiwi", "pineapple", "banana"]
lista.sort()
lista
Copy
	
['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
Copy
	
['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
Copy
	
[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 - 50
return abs(n - 50)
lista = [100, 50, 65, 82, 23]
lista.sort(key = myfunc)
lista
Copy
	
[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
Copy
	
['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
Copy
	
[6, 5, 9, 4, 3, 8, 5]
2.3.1.4. Copiar listaslink image 14

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 = lista1
lista1[0] = True
lista2
Copy
	
[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] = True
lista2
Copy
	
[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] = True
lista2
Copy
	
[5, 8, 3, 4, 9, 5, 6]
2.3.1.5. Concatenar listaslink image 15

Se pueden concatenar listas mediante el operador +

	
lista1 = [5, 8, 3, 4, 9, 5, 6]
lista2 = ['a', 'b', 'c']
lista = lista1 + lista2
lista
Copy
	
[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
Copy
	
[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 * 3
lista2
Copy
	
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']

2.3.2. Tuplaslink image 16

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
Copy
	
('item0', 1, True, 3.3, 'item4', True)

Se puede obtener su longitud mediante la función len()

	
len (tupla)
Copy
	
6

Para crear tuplas con un único elemento es necesario añadir una coma

	
tupla = ('item0',)
tupla, type(tupla)
Copy
	
(('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])
Copy
	
item0
True
(True, 3.3)
(True, 3.3)

Podemos comprobar si hay un ítem en la tupla

	
'item4' in tupla
Copy
	
True
2.3.2.1. Modificar tuplaslink image 17

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
Copy
	
('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 tupla
if 'tupla' not in locals():
print("tupla eliminada")
Copy
	
tupla eliminada
2.3.2.2. Desempaquetar tuplaslink image 18

Cuando creamos tuplas, en realidad estamos empaquetando datos

	
tupla = ('item0', 1, True, 3.3, 'item4', True)
tupla
Copy
	
('item0', 1, True, 3.3, 'item4', True)

pero podemos desempaquetarlos

	
item0, item1, item2, item3, item4, item5 = tupla
item0, item1, item2, item3, item4, item5
Copy
	
('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 = tupla
item0, item1, item2, item3
Copy
	
('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 = tupla
item0, item1, item2, item5
Copy
	
('item0', 1, [True, 3.3, 'item4'], True)
2.3.2.3. Concatenar tuplaslink image 19

Se pueden concatenar tuplas mediante el operador +

	
tupla1 = ("a", "b" , "c")
tupla2 = (1, 2, 3)
tupla3 = tupla1 + tupla2
tupla3
Copy
	
('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 * 3
tupla2
Copy
	
('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')
2.3.2.4. Métodos de las tuplaslink image 20

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)
Copy
	
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)
Copy
	
0

2.3.3. Rangelink image 21

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='')
Copy
	
0 1 2 3 4

Si por ejemplo no queremos que empiece en 0

	
for i in range(2, 5):
print(f'{i} ', end='')
Copy
	
2 3 4
	
for i in range(-2, 5):
print(f'{i} ', end='')
Copy
	
-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='')
Copy
	
0 2 4 6 8

2.4. Diccionarioslink image 22

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
Copy
	
{'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"]
Copy
	
2000

Se puede obtener su longitud mediante la función len()

	
len(diccionario)
Copy
	
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 ítemslink image 23

Para acceder a un ítem lo podemos hacer a través de su key

	
diccionario["model"]
Copy
	
'Mustang'

También se puede acceder mediante el método get()

	
diccionario.get("model")
Copy
	
'Mustang'

Para saber todas las keys de los diccionarios se puede usar el método keys()

	
diccionario.keys()
Copy
	
dict_keys(['brand', 'model', 'year', 'colors'])

Se puede usar una variable para apuntar a las keys 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 keys
x = diccionario.keys()
print(x)
# Se añade una nueva key
diccionario["color"] = "white"
# Se consulta la variable que apunta a las key
print(x)
Copy
	
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()
Copy
	
dict_values(['Ford', 'Mustang', 1964, 'white'])

Se puede usar una variable para apuntar a los valuess 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 values
x = diccionario.values()
print(x)
# Se modifica un value
diccionario["year"] = 2020
# Se consulta la variable que apunta a los values
print(x)
Copy
	
dict_values(['Ford', 'Mustang', 1964])
dict_values(['Ford', 'Mustang', 2020])

Si lo que se quiere son los items enteros, es decir keys y values hay que usar el método items()

	
diccionario.items()
Copy
	
dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 2020)])

Se puede usar una variable para apuntar a los items 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 items
x = diccionario.items()
print(x)
# Se modifica un value
diccionario["year"] = 2020
# Se consulta la variable que apunta a los items
print(x)
Copy
	
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
Copy
	
True

2.4.2. Modificar los ítemslink image 24

Se puede modificar un item accediendo a él directamente

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se modifica un item
diccionario["year"] = 2020
diccionario
Copy
	
{'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 item
diccionario.update({"year": 2020})
diccionario
Copy
	
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}

2.4.3. Añadir ítemslink image 25

Se puede añadir un item agregándolo sin más

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se modifica un item
diccionario["colour"] = "blue"
diccionario
Copy
	
{'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 item
diccionario.update({"colour": "blue"})
diccionario
Copy
	
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'colour': 'blue'}

2.4.4. Eliminar itemslink image 26

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 item
diccionario.pop("model")
diccionario
Copy
	
{'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 item
del diccionario["model"]
diccionario
Copy
	
{'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 item
del diccionario
if 'diccionario' not in locals():
print("diccionario eliminado")
Copy
	
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 introducido
diccionario.popitem()
diccionario
Copy
	
{'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
Copy
	
{}

2.4.5. Copiar diccionarioslink image 27

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 = diccionario1
diccionario1["year"] = 2000
diccionario2["year"]
Copy
	
2000

Por lo que hay que usar el método copy()

	
diccionario1 = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
diccionario2 = diccionario1.copy()
diccionario1["year"] = 2000
diccionario2["year"]
Copy
	
1964

Ó hay que usar el constructor de diccionarios dict()

	
diccionario1 = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
diccionario2 = dict(diccionario1)
diccionario1["year"] = 2000
diccionario2["year"]
Copy
	
1964

2.4.6. Diccionarios anidadoslink image 28

Los diccionarios pueden tener itemss 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
Copy
	
{'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
Copy
	
{'child1': {'name': 'Emil', 'year': 2004},
'child2': {'name': 'Tobias', 'year': 2007},
'child3': {'name': 'Linus', 'year': 2011}}

2.4.7. Métodos de los diccionarioslink image 29

Estos son los métodos que se pueden usar en los diccionarios

2.4.8. Dictionary comprehensionlink image 30

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
Copy
	
{4: 16, 6: 36}

2.5. Setslink image 31

2.5.1. Setlink image 32

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_
Copy
	
{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_
Copy
	
{1, 5, 5.3, 6.6, 'item0', 'item4'}

Se puede obtener la longitud del set mediante la función len()

	
len(set_)
Copy
	
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_
Copy
	
True
2.5.1.1. Añadir ítemslink image 33

Se puede añadir un ítem al set mediante el método add()

	
set_.add(8.8)
set_
Copy
	
{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_
Copy
	
{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_
Copy
	
{1, 10, 11.2, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5', 'item6', 'item9'}
2.5.1.2. Eliminar ítemslink image 34

Se puede eliminar un ítem determinado mediante el método remove()

	
set_.remove('item9')
set_
Copy
	
{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_
Copy
	
{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 sets 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}")
Copy
	
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_
Copy
	
set()

Por último, con del se puede eliminar el set

	
del set_
if 'set_' not in locals():
print("set eliminado")
Copy
	
set eliminado
2.5.1.3. Unir ítemslink image 35

Una forma de unir sets es mediante el método union()

	
set1 = {"a", "b" , "c"}
set2 = {1, 2, 3}
set3 = set1.union(set2)
set3
Copy
	
{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
Copy
	
{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
Copy
	
{'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
Copy
	
{'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
Copy
	
{'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
Copy
	
{'banana', 'cherry', 'google', 'microsoft'}
2.5.1.4. Métodos de los setslink image 36

Estos son los métodos que se pueden usar en los sets

2.5.2. Frozensetlink image 37

Los frozensets son como los sets pero con la salvedad de que son inmutables, al igual que las tuplas son como las lists pero inmutables. Por lo que no podremos añadir o eliminar items

2.6. Booleanoslink image 38

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))
Copy
	
True
True
False

2.6.1. Otros tipos de datos True o Falselink image 39

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(""))
Copy
	
True
False
	
print(bool(3))
print(bool(0))
Copy
	
True
False
	
lista = [1, 2, 3]
print(bool(lista))
lista = []
print(bool(lista))
Copy
	
True
False
	
tupla = (1, 2, 3)
print(bool(tupla))
tupla = ()
print(bool(tupla))
Copy
	
True
False
	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964,
"colors": ["red", "white", "blue"]
}
print(bool(diccionario))
diccionario.clear()
print(bool(diccionario))
Copy
	
True
False
	
set_ = {'item0', 1, 5.3, "item4", 5, 6.6}
print(bool(set_))
set_.clear()
print(bool(set_))
Copy
	
True
False

2.7. Binarioslink image 40

2.7.1. Byteslink image 41

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
Copy
	
b'MaximoFN'

También se pueden crear mediante su constructor bytes()

	
byte = bytes(10)
byte
Copy
	
b''
	
byte = bytes(range(10))
byte
Copy
	
b' '

Se pueden concatenar bytes mediante el operador +

	
byte1 = b'DeepMax'
byte2 = b'FN'
byte3 = byte1 + byte2
byte3
Copy
	
b'DeepMaxFN'

O mediante la repetición con el operador *

	
byte1 = b'MaximoFN '
byte2 = byte1 * 3
byte2
Copy
	
b'MaximoFN MaximoFN MaximoFN '

Podemos comprobar si un carácter está dentro de la cadena

	
b'D' in byte1
Copy
	
False

Estos son los métodos que se pueden usar en los bytes

2.7.2. Bytearraylink image 42

Los bytearrays son iguales que los bytes solo que son mutables

	
byte_array = bytearray(b'MaximoFN')
byte_array
Copy
	
bytearray(b'MaximoFN')

2.7.3. Memoryviewlink image 43

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]= 74
print(f'Después de acceder a la memoria: {byte_array}')
Copy
	
Antes de acceder a la memoria: bytearray(b'XYZ')
Después de acceder a la memoria: bytearray(b'XYJ')

3. Operadoreslink image 44

3.1. Operadores aritméticoslink image 45

Operador suma +

	
3 + 5
Copy
	
8

Operador resta -

	
3 - 5
Copy
	
-2

Operador multiplicación *

	
3 * 5
Copy
	
15

Operador división /

	
3 / 5
Copy
	
0.6

Operador módulo %. Devuelve el resto de una división

	
25 % 2
Copy
	
1

Operador exponente **

	
5 ** 2
Copy
	
25

Operador división entera //

	
25 // 2
Copy
	
12

3.2. Operadores de comparaciónlink image 46

Operador es igual ==

	
1 == 1
Copy
	
True

Operador es distinto !=

	
1 != 2
Copy
	
True

Operador es mayor que >

	
3 > 2
Copy
	
True

Operador es menor que <

	
2 < 3
Copy
	
True

Operador es mayor o igual que >=

	
3 >= 3
Copy
	
True

Operador es menor o igual que <=

	
3 <= 3
Copy
	
True

3.3. Operadores lógicoslink image 47

Operador and

	
True and True
Copy
	
True

Operador or

	
True or False
Copy
	
True

Operador not

	
not False
Copy
	
True

3.4. Operadores de identidadlink image 48

Operador is

	
5.3 is 5.3
Copy
	
True

Operador is not

	
5.3 is not 5
Copy
	
True

3.5. Operadores de pertenencialink image 49

Operador in

	
x = ["apple", "banana"]
"banana" in x
Copy
	
True

Operador not in

	
x = ["apple", "banana"]
"orange" not in x
Copy
	
True

3.6. Operadores bit a bitlink image 50

Operador AND &

	
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
c = a & b; # 12 = 0000 1100
c
Copy
	
12

Operador OR |

	
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
c = a | b; # 61 = 0011 1101
c
Copy
	
61

Operador XOR ^

	
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
c = a ^ b; # 49 = 0011 0001
c
Copy
	
49

Operador NOT ~

	
a = 60 # 60 = 0011 1100
c = ~a; # -61 = 1100 0011
c
Copy
	
-61

Operador desplazamiento hacia la izquierda <<

	
a = 60 # 60 = 0011 1100
c = a << 2; # 240 = 1111 0000
c
Copy
	
240

Operador desplazamiento hacia la derecha >>

	
a = 60 # 60 = 0011 1100
c = a >> 2; # 15 = 0000 1111
c
Copy
	
15

3.7. Operadores de asignaciónlink image 51

Operador =

	
a = 5
a
Copy
	
5

Operador +=. x += y es equivalente a x = x + y

	
a += 5
a
Copy
	
10

Operador -=. x -= y es equivalente a `x = x - y

	
a -= 5
a
Copy
	
5

Operador *=. x *= y es equivalente a `x = x * y

	
a *= 3
a
Copy
	
15

Operador /=. x /= y es equivalente a `x = x / y

	
a /= 3
a
Copy
	
5.0

Operador %=. x %= y es equivalente a `x = x % y

	
a = 25
a %= 2
a
Copy
	
1

Operador //=. x //= y es equivalente a `x = x // y

	
a = 25
a //= 2
a
Copy
	
12

Operador **=. x **= y es equivalente a `x = x ** y

	
a = 5
a **= 2
a
Copy
	
25

Operador &=. x &= y es equivalente a `x = x & y

	
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
a &= b; # 12 = 0000 1100
a
Copy
	
12

Operador |=. x |= y es equivalente a x = x | y

	
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
a |= b; # 61 = 0011 1101
a
Copy
	
61

Operador ^=. x ^= y es equivalente a `x = x ^ y

	
a = 60 # 60 = 0011 1100
b = 13 # 13 = 0000 1101
a ^= b; # 49 = 0011 0001
a
Copy
	
49

Operador >>=. x >>= y es equivalente a `x = x >> y

	
a = 60 # 60 = 0011 1100
a <<= 2; # 240 = 1111 0000
a
Copy
	
240

Operador <<=. x <<= y es equivalente a x = x << y

	
a = 60 # 60 = 0011 1100
a >>= 2; # 15 = 0000 1111
a
Copy
	
15

4. Control de flujolink image 52

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. Iflink image 53

Mediante if podemos crear condiciones

	
if len('MaximoFN') == 8:
print('MaximoFN tiene 8 caracteres')
Copy
	
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')
Copy
	
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')
Copy
	
MaximoFN tiene 8 caracteres

Si queremos escribir todo en una sola línea

	
if len('MaximoFN') == 8: print('MaximoFN tiene 8 caracteres')
Copy
	
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')
Copy
	
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:
pass
else:
print('MaximoFN tiene 8 caracteres')
Copy
	
MaximoFN tiene 8 caracteres

4.2. Whilelink image 54

El bucle while se ejecuta mientras la condición sea True

	
i = 0
string = 'MaximoFN'
while len(string) > i:
print(string[i], end='')
i += 1
Copy
	
MaximoFN

Si queremos que el bucle pare por alguna condición usamos break

	
i = 0
string = 'MaximoFN'
while len(string) > i:
if string[i] == 'F':
break
print(string[i], end='')
i += 1
Copy
	
Maximo

Si queremos que una de las iteraciones no se ejecute por alguna razón usamos continue

	
i = 0
string = 'Maximo FN'
while len(string) > i:
if string[i] == ' ':
i += 1
continue
print(string[i], end='')
i += 1
Copy
	
MaximoFN

Mediante else se puede ejecutar un bloque de código si la condición del while no es True

	
i = 0
string = 'MaximoFN'
while len(string) > i:
print(string[i], end='')
i += 1
else:
print("\nSe ha terminado el while")
Copy
	
MaximoFN
Se ha terminado el while

4.3. Forlink image 55

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='')
Copy
	
MaximoFN
	
lista = ['M', 'a', 'x', 'i', 'm', 'o', 'F', 'N']
for x in lista:
print(x, end='')
Copy
	
MaximoFN
	
tupla = ('M', 'a', 'x', 'i', 'm', 'o', 'F', 'N')
for x in tupla:
print(x, end='')
Copy
	
MaximoFN
	
string = 'MaximoFN'
for i in range(len(string)):
print(string[i], end='')
Copy
	
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='')
Copy
	
MaximoFN

También se puede iterar por los sets, 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='')
Copy
	
NximoaMF

Si queremos que el bucle pare por alguna condición usamos break

	
string = 'MaximoFN'
for x in string:
if x == 'F':
break
print(x, end='')
Copy
	
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 == ' ':
continue
print(x, end='')
Copy
	
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")
Copy
	
MaximoFN
Se 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:
pass
print('Interior del for no codificado')
Copy
	
Interior del for no codificado

5. Funcioneslink image 56

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')
Copy

Para llamar a la función solo es necesario escribir su nombre

	
def funcion():
print('MaximoFN')
funcion()
Copy
	
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")
Copy
	
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")
Copy
	
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")
Copy
	
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")
Copy
	
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")
Copy
	
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"])
Copy
	
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 string
print(funcion(["Blog", "de", "MaximoFN"]))
Copy
	
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, string2
dato0, dato1, dato2 = funcion(["Blog", "de", "MaximoFN"])
print(dato0 + ' ' + dato1 + ' ' + dato2)
Copy
	
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)
Copy
	
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():
pass
funcion()
Copy

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():
pass
funcion()
def factorial(n):
if n == 0 or n == 1:
return 1
else:
return n * factorial(n-1)
factorial(5)
Copy
	
120

5.1. Built in functionslink image 57

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)
Copy
	
5

A continuación se muestra una lista de estas funciones

	
import builtins
dir(builtins)
Copy
	
['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ónlink image 58

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"
None
help(funcion)
Copy
	
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__
Copy
	
'Esta es la explicación de la función'

5.3. Decoradoreslink image 59

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 envoltorio
def funcion():
print("MaximoFN")
funcion_envoltorio = decorador(funcion)
print('Función sin decoradores: ')
funcion()
print('\nFunción con decoradores: ')
funcion_envoltorio()
Copy
	
Función sin decoradores:
MaximoFN
Funció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
@decorador2
def funcion2():
print("MaximoFN")
print('Función con decoradores: ')
funcion2()
Copy
	
Función con decoradores:
==================
MaximoFN
==================

5.4. *args y **kwargslink image 60

*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. *argslink image 61

*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")
Copy
	
Hola, Alicia
Hola, Roberto
Hola, Carlos

5.4.2. **kwargslink image 62

**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)
Copy
	
Hola Juan, tu edad es 22 años
Hola Maria, tu edad es 32 años
Hola Pedro, tu edad es 25 años

6. Funciones adicionaleslink image 63

6.1. Funciones lambdalink image 64

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 + 10
print(x(5))
Copy
	
15
	
x = lambda a, b, c : a + b + c
print(x(5, 6, 2))
Copy
	
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 * n
mydoubler = myfunc(2)
mytripler = myfunc(3)
print(f"mydoubler: {mydoubler(11)}")
print(f"mytripler: {mytripler(11)}")
Copy
	
mydoubler: 22
mytripler: 33

6.2. Función maplink image 65

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 + 1
lista_modificada = list(map(funcion_mas_1, lista))
lista_modificada
Copy
	
[2, 3, 4]

Esto es equivalente a usar list comprehension

	
lista_modificada = [funcion_mas_1(x) for x in lista]
lista_modificada
Copy
	
[2, 3, 4]

6.3. Función filterlink image 66

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 == 0
lista_filtrada = list(filter(esPar, lista))
lista_filtrada
Copy
	
[2, 4, 6]

Esto es equivalente a usar list comprehension

	
lista_filtrada = [x for x in lista if esPar(x)]
lista_filtrada
Copy
	
[2, 4, 6]

6.4. Función reducelink image 67

La función reduce permite realizar tareas acumulativas en estructuras iterables

	
from functools import reduce
lista = [1, 22, 33]
def acumular(valor, acumulador):
print(f'valor = {valor}, acumulador = {acumulador}, acumulacion = {valor + acumulador}')
return valor + acumulador
acumulacion = reduce(acumular, lista)
print(f'\nacumulacion = {acumulacion}')
Copy
	
valor = 1, acumulador = 22, acumulacion = 23
valor = 23, acumulador = 33, acumulacion = 56
acumulacion = 56

6.5. Función ziplink image 68

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
Copy
	
[('Manolo', 181), ('Andres', 178), ('Fernando', 180)]

6.5. Generadoreslink image 69

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 i
generador = iterador_custom(20)
for i in generador:
print(i)
Copy
	
0
3
6
9
12
15
18

Acabamos de hacer un iterador por números múltiplos de 3

6.6. High order functionslink image 70

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 + 1
def hof(f, x):
return 2*f(x)
print(hof(increment, 3))
Copy
	
8

7. Clases y objetoslink image 71

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'
Copy

Una vez creada la clase se puede crear un objeto de dicha clase

	
class Clase:
variable = 'MaximoFN'
objeto = Clase()
Clase.variable
Copy
	
'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 = nombre
self.edad = edad
objeto_persona = Persona("Miguel", 36)
print(objeto_persona.nombre)
print(objeto_persona.edad)
Copy
	
Miguel
36

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 = nombre
self.edad = edad
def saludar(self):
print(f'Hola mi nombre es {self.nombre} y tengo {self.edad} años')
objeto_persona = Persona("Miguel", 36)
objeto_persona.saludar()
Copy
	
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 = nombre
yo_mismo.edad = edad
def 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()
Copy
	
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()
Copy
	
Hola mi nombre es Marta y tengo 36 años

Incluso eliminarlas

	
del objeto_persona.nombre
Copy

También se puede eliminar el objeto entero

	
del objeto_persona.nombre
del objeto_persona
Copy

Si por ejemplo queremos hacer la estructura de la clase pero no queremos, de momento, codificar el interior podemos usar pass

	
del objeto_persona.nombre
del objeto_persona
class Persona:
pass
objeto_persona = Persona()
Copy

7.1. Herencialink image 72

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.nombre
del objeto_persona
class Persona:
pass
objeto_persona = Persona()
class Persona:
def __init__(self, nombre, apellido):
self.nombre = nombre
self.apellido = apellido
def imprimir_nombre(self):
print(f'Me llamo {self.nombre} {self.apellido}')
objeto_padre = Persona("Laura", "Perez")
objeto_padre.imprimir_nombre()
Copy
	
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
Copy

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):
pass
objeto_hijo = Estudiante("Mariano", "Sanz")
objeto_hijo.imprimir_nombre()
Copy
	
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()
Copy
	
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()
Copy
	
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 = curso
def 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()
Copy
	
Me llamo Mariano Sanz
Estoy 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 = curso
def 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()
Copy
	
Me llamo Mariano Sanz
Estoy en el curso número 4
Soy un estudiante del curso número 4

7.2. Sobrecarga de operadoreslink image 73

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 = x
self.y = y
def __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)
Copy
	
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ón divmod().
  • __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ón abs().
  • __invert__(self): sobrecarga el operador de inversión (~).
  • __complex__(self): sobrecarga la función complex().
  • __int__(self): sobrecarga la función int().
  • __float__(self): sobrecarga la función float().

7.3. Iteradores personalizadoslink image 74

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)) # 10
print(iterator[0]) # 0
print(iterator[1]) # 1
Copy
	
10
0
1

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
Copy
	
0 1 2 3 4 5 6 7 8 9

7.4. Llamada a objetos como funcioneslink image 75

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 = base
def __call__(self, potencia):
return self.base ** potencia
potencia_cuadrado = potencia(2)
print(potencia_cuadrado(3)) # 8
Copy
	
8

7.5. Atributos y funciones privadoslink image 76

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.__privado
def setPrivado(self, valor):
self.__privado = valor
def __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")
Copy
	
Acceso al atributo publico: Soy público
Acceso al atributo privado: No se puede acceder al atributo privado
Acceso al atributo privado mediante el accesor: Soy privado
Llamada a la función privada: No se puede llamar a la función privada
Llamada a la función pública: Soy una función privada

8. Iteradoreslink image 77

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))
Copy
	
manzana
plátano
cereza
	
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=' ')
Copy
	
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)
Copy
	
manzana
plátano
cereza
	
string = "plátano"
for x in string:
print(x, end=' ')
Copy
	
p l á t a n o

8.1. Crear un objeto iteradorlink image 78

Para crear un objeto/clase como iterador, hay que implementar los métodos __iter__() y __next__().

	
class Numeros:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
objeto_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=' ')
Copy
	
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 = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
objeto_iterador = Numeros()
iterador = iter(objeto_iterador)
for x in iterador:
print(x, end=' ')
Copy
	
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 valorlink image 79

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}")
Copy
	
En la posición 0, está el caracter M
En la posición 1, está el caracter a
En la posición 2, está el caracter x
En la posición 3, está el caracter i
En la posición 4, está el caracter m
En la posición 5, está el caracter o
En la posición 6, está el caracter F
En la posición 7, está el caracter N

8.3. Iterar por dos objetos iterables a la vezlink image 80

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}")
Copy
	
En el primer string hay M, en el segundo string hay P
En el primer string hay a, en el segundo string hay y
En el primer string hay x, en el segundo string hay t
En el primer string hay i, en el segundo string hay h
En el primer string hay m, en el segundo string hay o
En el primer string hay o, en el segundo string hay n
En el primer string hay F, en el segundo string hay P
En el primer string hay N, en el segundo string hay o
En el primer string hay _, en el segundo string hay s
En el primer string hay _, en el segundo string hay t

9. Alcance de variableslink image 81

Una variable solo está disponible dentro de la región en la que se crea. A esto se le llama alcance

9.1. Alcance locallink image 82

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 = 300
print(x)
funcion()
Copy
	
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 = 300
def funcion_interna():
print(x)
funcion_interna()
funcion()
Copy
	
300

9.2. Alcance globallink image 83

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 = 300
def funcion():
print(f'Ámbito local: {x}')
funcion()
print(f'Ámbito global: {x}')
Copy
	
Á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 = 300
def funcion():
x = 200
print(f'Variable local: {x}')
funcion()
print(f'Variable global: {x}')
Copy
	
Variable local: 200
Variable 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 x
x = 300
funcion()
print(f'Variable global: {x}')
Copy
	
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 = 300
def funcion():
global x
x = 200
funcion()
print(f'Variable global: {x}')
Copy
	
Variable global: 200

10. Móduloslink image 84

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
Copy
	
/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
Copy

A continuación veamos qué archivos hay en nuestra carpeta. Esto lo haremos mediante el comando ls (list)

	
!mkdir introduccion_python
!ls introduccion_python
Copy

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.py
def funcion_del_modulo(nombre):
print("Hola, " + nombre)
Copy
	
Writing introduccion_python/modulo1.py

Volvemos a ver qué archivos hay en nuestra carpeta

	
!ls introduccion_python
Copy
	
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.modulo1
introduccion_python.modulo1.funcion_del_modulo('MaximoFN')
Copy
	
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 mod1
mod1.funcion_del_modulo('MaximoFN')
Copy
	
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.py
def 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")
Copy
	
Writing introduccion_python/modulo2.py
	
from introduccion_python.modulo2 import funcion2_del_modulo
funcion2_del_modulo('MaximoFN')
Copy
	
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 platform
x = platform.system()
x
Copy
	
'Linux'

10.1. Entry points: archivos como módulos y no como scriptslink image 85

Vamos ahora a crear un archivo llamado modulo3.py

	
%%writefile introduccion_python/modulo3.py
print("Hola desde modulo3")
def funcion_del_modulo():
return "Hola desde la función del modulo3"
Copy
	
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 mod3
print(mod3.funcion_del_modulo())
Copy
	
Hola desde modulo3
Hola 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
Copy
	
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.py
print("Hola desde modulo3")
def funcion_del_modulo():
return "Hola desde la función del modulo3"
if __name__ == "__main__":
funcion_del_modulo()
Copy
	
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 mod3
print(mod3.funcion_del_modulo())
Copy
	
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
Copy
	
Hola desde modulo3

11. Paqueteslink image 86

En Python podemos crearnos nuestros propios paquetes, para ello creamos una carpeta con el nombre del paquete

	
!mkdir mi_paquete_de_python
Copy

Creamos ahora dos archivos dentro

	
!mkdir mi_paquete_de_python
!touch mi_paquete_de_python/modulo1.py mi_paquete_de_python/modulo2.py
Copy

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.py
def 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")
Copy
	
Overwriting mi_paquete_de_python/modulo1.py
	
%%writefile mi_paquete_de_python/modulo2.py
def 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")
Copy
	
Overwriting mi_paquete_de_python/modulo2.py

Ahora podemos llamar a las funciones de nuestro paquete

	
from mi_paquete_de_python import modulo1 as mod1
from mi_paquete_de_python import modulo2 as mod2
mod1.funcion1()
mod1.funcion2()
mod2.funcion1()
mod2.funcion2()
Copy
	
Hola desde la función 1 del módulo 1
Hola desde la función 2 del módulo 1
Hola desde la función 1 del módulo 2
Hola 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
Copy
	
!touch mi_paquete_de_python/__init__.py
%%writefile mi_paquete_de_python/__init__.py
import modulo1
import modulo2
Copy
	
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_paquete
mi_paquete.modulo1.funcion1()
mi_paquete.modulo1.funcion2()
mi_paquete.modulo2.funcion1()
mi_paquete.modulo2.funcion2()
Copy
	
Hola desde la función 1 del módulo 1
Hola desde la función 2 del módulo 1
Hola desde la función 1 del módulo 2
Hola desde la función 2 del módulo 2

De esta manera solo tenemos que hacer un import

12. Try... Exceptlink image 87

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")
Copy
	
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")
Copy
	
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')
Copy
	
MaximoFN
Todo 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")
Copy
	
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
Copy
	
Ha ocurrido una excepción

12.1. Crear una excepciónlink image 88

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/denominador
print(division(10, 0))
Copy
	
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-16-33fb6066fa78> in <module>
5 return numerador/denominador
6
----> 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")
4
5 return numerador/denominador
Exception: 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/denominador
print(division(10, 0))
Copy
	
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-17-26bfa63ae44c> in <module>
5 return numerador/denominador
6
----> 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")
4
5 return numerador/denominador
TypeError: El denominador no puede ser 0

13. Keywords o palabras reservadaslink image 89

Durante este post en varias ocasiones han aparecido palabras reservadas de Python o keywords, estas son una serie de palabras reservadas por Python

A continuación se muestra una lista de las keywords

	
import keyword
keyword.kwlist
Copy
	
['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 Pythonlink image 90

Importando el módulo this podemos leer el zen de Python, es decir, su filosofía o principios

	
import this
Copy
	
The Zen of Python, by Tim Peters
Beautiful 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!

Seguir leyendo

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

¿Alguna vez has hablado con un LLM y te ha respondido algo que suena como si hubiera estado bebiendo café de máquina durante toda la noche? 😂 ¡Eso es lo que llamamos una alucinación en el mundo de los LLMs! Pero no te preocupes, porque no es que tu modelo de lenguaje esté loco (aunque a veces puede parecerlo 🤪). La verdad es que los LLMs pueden ser un poco... creativos cuando se trata de generar texto. Pero gracias a DoLa, un método que utiliza capas de contraste para mejorar la factibilidad de los LLMs, podemos evitar que nuestros modelos de lenguaje se conviertan en escritores de ciencia ficción 😂. En este post, te explicaré cómo funciona DoLa y te mostraré un ejemplo de código para que puedas entender mejor cómo hacer que tus LLMs sean más fiables y menos propensos a inventar historias. ¡Vamos a salvar a nuestros LLMs de la locura y hacer que sean más útiles! 🚀

Últimos posts -->

¿Has visto estos proyectos?

Subtify

Subtify Subtify

Generador de subtítulos para videos en el idioma que desees. Además a cada persona le pone su subtítulo de un color

Ver todos los proyectos -->

¿Quieres aplicar la IA en tu proyecto? Contactame!

¿Quieres mejorar con estos tips?

Últimos tips -->

Usa esto en local

Los espacios de Hugging Face nos permite ejecutar modelos con demos muy sencillas, pero ¿qué pasa si la demo se rompe? O si el usuario la elimina? Por ello he creado contenedores docker con algunos espacios interesantes, para poder usarlos de manera local, pase lo que pase. De hecho, es posible que si pinchas en alún botón de ver proyecto te lleve a un espacio que no funciona.

Ver todos los contenedores -->

¿Quieres aplicar la IA en tu proyecto? Contactame!

¿Quieres entrenar tu modelo con estos datasets?

short-jokes-dataset

Dataset de chistes en inglés

opus100

Dataset con traducciones de inglés a español

netflix_titles

Dataset con películas y series de Netflix

Ver más datasets -->