Introduction to Python

Introduction to Python Introduction to Python

Introduction to Pythonlink image 91

Disclaimer: This post has been translated to English using a machine translation model. Please, let me know if you find any mistakes.

1. Summarylink image 92

Let's make a brief introduction to Python, explaining the data types we have, operators, the use of functions and classes. Additionally, we will see how to use iterable objects, how to use modules, etc. python

2. Data types in Pythonlink image 93

There are 7 data types in Python

  1. Text type: str2. Numerical: int, float, complex3. Sequences: list, tuple, range4. Mapping: dict5. Sets: set, frozenset6. Booleans: bool7. Binaries: bytes, bytearray, memoryview

We can get the data type using the type() function.

	
type(5.)
Copy
	
float

Python is a dynamically typed language, which means you can have a variable of one type and then assign it another type.

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

Python types variables for you, but if you want to type them yourself, you can do so.

	
b = int(5.1)
type(b), b
Copy
	
(int, 5)

Although b has been initialized as 5.1, that is, it should be of type float, when we type it as int, we see that it is of type int and its value is 5

2.1. Stringslink image 94

strings are sequences of characters, these can be defined with double quotes " or single quotes '

	
string = "MaximoFN"
string
Copy
	
'MaximoFN'
	
string = 'MaximoFN'
string
Copy
	
'MaximoFN'

To write a very long string and not have a line that takes up too much space, it can be introduced on multiple lines

	
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'

However, we see that in the middle it has inserted the character , this character indicates a line break. If we use the print() function, we will see that it no longer appears.

	
print(string)
Copy
	
Este es un ejemplo de
como estoy introduciendo un string
en varias lineas

As we have said, strings are sequences of characters, so we can navigate and iterate through them.

	
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

We can get the length of our string using the len() function.

	
len(string)
Copy
	
73

Check if there is a specific string within ours

	
'ejemplo' in string
Copy
	
True

Strings have certain useful attributes, such as converting everything to uppercase.

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

all in lowercase

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

Replace characters

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

Get all the words

	
print(string.split())
Copy
	
['Este', 'es', 'un', 'ejemplo', 'de', 'como', 'estoy', 'introduciendo', 'un', 'string', 'en', 'varias', 'lineas']

You can see all the string methods in this link

Another useful thing that can be done with strings is concatenating them.

	
string1 = 'Maximo'
string2 = 'FN'
string1 + string2
Copy
	
'MaximoFN'

We previously explained that the character \n corresponds to a line break. This special character is part of a series of special characters called Escape Characters. Let's look at some others.

If we declare a string with double quotes and want to add a double quote inside the string, we use the escape character \"

	
print("Este es el blog de \"MaximoFN\"")
Copy
	
Este es el blog de "MaximoFN"

The same with the single quote, we add \'

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

Now we have the problem of whether we want to add the \ character since, as we have seen, it is an escape character, so we solve it by putting a double backslash \.

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

We have already seen the newline escape character \n

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

If we want to write from the beginning of the line, we add \r

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

If we want to add a large space (indent) we use \t

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

We can delete a character with \b

	
print('Este es el blog de \bMaximoFN')
Copy
	
Este es el blog deMaximoFN

We can add the ASCII code in octal using \ooo

	
print('\115\141\170\151\155\157\106\116')
Copy
	
MaximoFN

Or add the ASCII code in hexadecimal using \xhh

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

Lastly, we can convert another type of data into a string

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

2.2. Numberslink image 95

2.2.1. Integerslink image 96

Integer numbers

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

2.2.2. Floatlink image 97

Floating-point numbers

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

2.2.3. Complexlink image 98

Complex numbers

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

2.2.4. Conversionlink image 99

Numbers can be converted between types

	
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)

A complex number cannot be converted to type int or type float

2.3. Sequenceslink image 100

2.3.1. Listslink image 101

Lists store multiple items in a variable. They are declared using the [] symbols, with items separated by commas.

	
lista = ['item0', 'item1', 'item2', 'item3', 'item4', 'item5']
lista
Copy
	
['item0', 'item1', 'item2', 'item3', 'item4', 'item5']

We can get the length of a list using the len() function.

	
len(lista)
Copy
	
6

Lists can have items of different types

	
lista = ['item0', 1, True, 5.3, "item4", 5, 6.6]
lista
Copy
	
['item0', 1, True, 5.3, 'item4', 5, 6.6]

In Python, counting starts from position 0, that is, if we want to get the first element of the list

	
lista[0]
Copy
	
'item0'

But one of the powerful things about Python is that if we want to access the last position we can use negative indices

	
lista[-1]
Copy
	
6.6

If instead of the last position in the list we want the penultimate one

	
lista[-2]
Copy
	
5

If we only want a range of values, for example, from the second to the fifth item, we access them via [2:5]

	
lista[2:5]
Copy
	
[True, 5.3, 'item4']

If the first number in the range is omitted, it means we want from the first item in the list to the indicated item, that is, if we want from the first item to the fifth, we use [:5]

	
lista[:5]
Copy
	
['item0', 1, True, 5.3, 'item4']

If the last number in the range is omitted, it means we want from the indicated item to the last. That is, if we want from the third item to the last, we use [3:].

	
lista[3:]
Copy
	
[5.3, 'item4', 5, 6.6]

We can also choose the range of items with negative numbers, that is, if we want from the third-to-last to the second-to-last we use [-3:-1]. This is useful when you have lists whose length is unknown, but you know you want a range of values from the end, for example, because the list was created with measurements that are being taken and you want to know the last averages.

	
lista[-3:-1]
Copy
	
['item4', 5]

It can be checked if an item is in the list

	
'item4' in lista
Copy
	
True
2.3.1.1. Editing listslink image 102

Lists in Python are dynamic, meaning they can be modified. For example, you can modify the third item.

	
lista[2] = False
lista
Copy
	
['item0', 1, False, 5.3, 'item4', 5, 6.6]

A range of values can also be modified.

	
lista[1:4] = [1.1, True, 3]
lista
Copy
	
['item0', 1.1, True, 3, 'item4', 5, 6.6]

Values can be added to the end of the list using the append() method.

	
lista.append('item7')
lista
Copy
	
['item0', 1.1, True, 3, 'item4', 5, 6.6, 'item7']

Or we can insert a value at a specific position using the insert() method.

	
lista.insert(2, 'insert')
lista
Copy
	
['item0', 1.1, 'insert', True, 3, 'item4', 5, 6.6, 'item7']

Lists can be joined using the extend() method.

	
lista2 = ['item8', 'item9']
lista.extend(lista2)
lista
Copy
	
['item0', 1.1, 'insert', True, 3, 'item4', 5, 6.6, 'item7', 'item8', 'item9']

It is not necessary to extend the list using another list; it can be done using another iterable data type in Python (tuples, sets, dictionaries, etc).

	
tupla = ('item10', 'item11')
lista.extend(tupla)
lista
Copy
	
['item0',
1.1,
'insert',
True,
3,
'item4',
5,
6.6,
'item7',
'item8',
'item9',
'item10',
'item11']

We can remove a specific position using the pop() method.

	
lista.pop(2)
lista
Copy
	
['item0',
1.1,
True,
3,
'item4',
5,
6.6,
'item7',
'item8',
'item9',
'item10',
'item11']

If the index is not specified, the last item is removed.

	
lista.pop()
lista
Copy
	
['item0', 1.1, True, 3, 'item4', 5, 6.6, 'item7', 'item8', 'item9', 'item10']

Or an item can be removed knowing its value using the remove() method.

	
lista.remove('item7')
lista
Copy
	
['item0', 1.1, True, 3, 'item4', 5, 6.6, 'item8', 'item9', 'item10']

With the del() function, you can also delete an item from the specified position.

	
del lista[3]
lista
Copy
	
['item0', 1.1, True, 'item4', 5, 6.6, 'item8', 'item9', 'item10']

If the index is not specified, the entire list is deleted.

With the clear() method, I empty the list.

	
lista.clear()
lista
Copy
	
[]

The number of items with a specific value can be obtained using the count() method.

	
lista = [5, 4, 6, 5, 7, 8, 5, 3, 1, 5]
lista.count(5)
Copy
	
4

You can also get the first index of an item with a specific value using the index() method.

	
lista = [5, 4, 6, 5, 7, 8, 5, 3, 1, 5]
lista.index(5)
Copy
	
0
2.3.1.2. List comprehensionlink image 103

We can operate through the list

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

Some of the powerful features of Python are list comprehensions, which allow you to do everything in one line and make the code more compact.

	
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
newlist = [x for x in fruits if "a" in x]
newlist
Copy
	
['apple', 'banana', 'mango']

The syntax is as follows:

newlist = [expression for item in iterable if condition == True]```

It can be used to perform operations on the original list

	
newlist = [x.upper() for x in fruits if "a" in x]
newlist
Copy
	
['APPLE', 'BANANA', 'MANGO']
2.3.1.3. Sorting listslink image 104

To order lists we use the sort() method.

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

It also sorts them alphabetically

	
lista = ["orange", "mango", "kiwi", "pineapple", "banana"]
lista.sort()
lista
Copy
	
['banana', 'kiwi', 'mango', 'orange', 'pineapple']

When sorting alphabetically, distinguish between uppercase and lowercase.

	
lista = ["orange", "mango", "kiwi", "Pineapple", "banana"]
lista.sort()
lista
Copy
	
['Pineapple', 'banana', 'kiwi', 'mango', 'orange']

They can be sorted in descending order using the attribute reverse = True

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

They can be ordered in the way we want using the key attribute.

	
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]

This can be used, for example, so that when sorting, it does not distinguish between uppercase and lowercase.

	
lista = ["orange", "mango", "kiwi", "Pineapple", "banana"]
lista.sort(key = str.lower)
lista
Copy
	
['banana', 'kiwi', 'mango', 'orange', 'Pineapple']

The list can be reversed using the reverse method.

	
lista = [5, 8, 3, 4, 9, 5, 6]
lista.reverse()
lista
Copy
	
[6, 5, 9, 4, 3, 8, 5]
2.3.1.4. Copying listslink image 105

Lists cannot be copied using list1 = list2, because if list1 is modified, list2 is also modified.

	
lista1 = [5, 8, 3, 4, 9, 5, 6]
lista2 = lista1
lista1[0] = True
lista2
Copy
	
[True, 8, 3, 4, 9, 5, 6]

So, you have to use the copy() method.

	
lista1 = [5, 8, 3, 4, 9, 5, 6]
lista2 = lista1.copy()
lista1[0] = True
lista2
Copy
	
[5, 8, 3, 4, 9, 5, 6]

Or you have to use the list constructor 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. Concatenating listslink image 106

Lists can be concatenated using the + operator.

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

Or using the extend method

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

Another way to concatenate is to repeat the tuple X times using the * operator

	
lista1 = ['a', 'b', 'c']
lista2 = lista1 * 3
lista2
Copy
	
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']

2.3.2 Tupleslink image 107

Tuples are similar to lists, they store multiple items in a variable, can contain items of different types, but they cannot be modified or reordered. They are defined using (), with items separated by commas. Since they cannot be modified, tuples execute a bit faster than lists, so if you don't need to modify the data, it's better to use tuples instead of lists.

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

Its length can be obtained using the len() function.

	
len (tupla)
Copy
	
6

To create tuples with a single element, it is necessary to add a comma

	
tupla = ('item0',)
tupla, type(tupla)
Copy
	
(('item0',), tuple)

To access an element of the tuple, proceed in the same way as with lists.

	
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)

We can check if there is an item in the tuple

	
'item4' in tupla
Copy
	
True
2.3.2.1. Modifying tupleslink image 108

Although tuples are not mutable, they can be modified by converting them to lists, modifying the list, and then converting it back to a tuple.

	
lista = list(tupla)
lista[4] = 'ITEM4'
tupla = tuple(lista)
tupla
Copy
	
('item0', 1, True, 3.3, 'ITEM4', True)

By converting it to a list, we can make all the modifications seen in lists.

What can be done is to delete the complete tuple

	
del tupla
if 'tupla' not in locals():
print("tupla eliminada")
Copy
	
tupla eliminada
2.3.22. Unpack tupleslink image 109

When we create tuples, we are actually packaging data

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

but we can unpack them

	
item0, item1, item2, item3, item4, item5 = tupla
item0, item1, item2, item3, item4, item5
Copy
	
('item0', 1, True, 3.3, 'item4', True)

If we want to extract fewer elements than the length of the tuple, we add a *

	
item0, item1, item2, *item3 = tupla
item0, item1, item2, item3
Copy
	
('item0', 1, True, [3.3, 'item4', True])

The asterisk * can be placed elsewhere if, for example, what we want is the last item.

	
item0, item1, *item2, item5 = tupla
item0, item1, item2, item5
Copy
	
('item0', 1, [True, 3.3, 'item4'], True)
2.3.23. Concatenating tupleslink image 110

Tuples can be concatenated using the + operator

	
tupla1 = ("a", "b" , "c")
tupla2 = (1, 2, 3)
tupla3 = tupla1 + tupla2
tupla3
Copy
	
('a', 'b', 'c', 1, 2, 3)

Another way to concatenate is to repeat the tuple X times using the * operator

	
tupla1 = ("a", "b" , "c")
tupla2 = tupla1 * 3
tupla2
Copy
	
('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')
2.3.24. Tuple Methodslink image 111

Tuples have two methods, the first is the count() method which returns the number of times an item appears within the tuple.

	
tupla = (5, 4, 6, 5, 7, 8, 5, 3, 1, 5)
tupla.count(5)
Copy
	
4

Another method is index() which returns the first position of an item within the tuple.

	
tupla = (5, 4, 6, 5, 7, 8, 5, 3, 1, 5)
tupla.index(5)
Copy
	
0

2.3.3. Rangelink image 112

With range() we can create a sequence of numbers, starting from 0 (by default), it increments by 1 (by default) and stops before a specified number.

range(start, stop, step)```

For example, if we want a sequence from 0 to 5 (not including 5)

	
for i in range(5):
print(f'{i} ', end='')
Copy
	
0 1 2 3 4

If for example we don't want it to start at 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

Lastly, if we don't want it to increment by 1, for example, if we want a sequence of even numbers.

	
for i in range(0, 10, 2):
print(f'{i} ', end='')
Copy
	
0 2 4 6 8

2.4. Dictionarieslink image 113

Dictionaries are used to store data in key:value pairs. They are mutable, unordered, and do not allow duplicates. They are defined using the {} symbols. They support items of different data types.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964,
"colors": ["red", "white", "blue"]
}
diccionario
Copy
	
{'brand': 'Ford',
'model': 'Mustang',
'year': 1964,
'colors': ['red', 'white', 'blue']}

As has been said, duplicates are not allowed.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964,
"year": 2000,
"colors": ["red", "white", "blue"]
}
diccionario["year"]
Copy
	
2000

Its length can be obtained using the len() function.

	
len(diccionario)
Copy
	
4

As can be seen, the length is 4 and not 5, since year is counted only once.

2.4.1. Accessing Itemslink image 114

To access an element, we can do so through its key

	
diccionario["model"]
Copy
	
'Mustang'

It can also be accessed using the get method.

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

To know all the keys of dictionaries, you can use the keys() method.

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

A variable can be used to point to the keys of the dictionary, so that calling it once is necessary

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

To get the values from the dictionary, you can use the values() method.

	
diccionario.values()
Copy
	
dict_values(['Ford', 'Mustang', 1964, 'white'])

A variable can be used to point to the values of the dictionary, so that calling it once is necessary.

	
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])

If what you want are the entire items, that is, keys and values, you should use the items() method.

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

A variable can be used to point to the items in the dictionary, so that calling it once is necessary.

	
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)])

It can be checked if a key exists in the dictionary

	
"model" in diccionario
Copy
	
True

2.4.2. Modify the itemslink image 115

An item can be modified by accessing it directly.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se modifica un item
diccionario["year"] = 2020
diccionario
Copy
	
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}

Or it can be modified using the update() method.

	
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. Adding Itemslink image 116

An item can be added in this way:

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se modifica un item
diccionario["colour"] = "blue"
diccionario
Copy
	
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'colour': 'blue'}

Or it can be added using the update() method.

	
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. Remove itemslink image 117

An item with a specific key can be removed using the pop() method.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se elimina un item
diccionario.pop("model")
diccionario
Copy
	
{'brand': 'Ford', 'year': 1964}

Or you can delete an item with a specific key using del by specifying the key name between the [] symbols.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se elimina un item
del diccionario["model"]
diccionario
Copy
	
{'brand': 'Ford', 'year': 1964}

The dictionary will raise an error if del is used and the key of an item is not specified.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se elimina un item
del diccionario
if 'diccionario' not in locals():
print("diccionario eliminado")
Copy
	
diccionario eliminado

If what is desired is to remove the last item introduced, the popitem() method can be used.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
# Se elimina el último item introducido
diccionario.popitem()
diccionario
Copy
	
{'brand': 'Ford', 'model': 'Mustang'}

If you want to clear the dictionary, you can use the clear() method.

	
diccionario = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
diccionario.clear()
diccionario
Copy
	
{}

2.4.5. Copying dictionarieslink image 118

Dictionaries cannot be copied using dictionary1 = dictionary2, because if you modify dictionary1, dictionary2 will also be modified.

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

So, you have to use the copy() method.

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

Or you have to use the dictionary constructor dict()

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

2.4.6. Anidated Dictionarieslink image 119

Dictionaries can have items of any data type, even other dictionaries. These types of dictionaries are called nested dictionaries.

	
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. Dictionary Methodslink image 120

These are the methods that can be used on dictionaries.

2.4.8. Dictionary comprehensionlink image 121

igual que podemos hacer list comprehensions mediante la sintaxis

list comprehension = [expression for item in iterable if condition == True]```
      
      We can create `dictionary comprehensions` using the following syntax
      ``` python
      dictionary comprehension = {key_expression: value_expression for item in iterable if condition == True}```
      
      Let's start with an example
      
	
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 122

2.5.1. Setlink image 123

Sets are used in Python to store a collection of items in a single variable. They can store items of different types. They are unordered and do not have an index. They differ from lists in that they have neither order nor index. They are declared using the symbols

Since set is a reserved word in Python, we create a set with the name set_

	
set_ = {'item0', 1, 5.3, "item4", 5, 6.6}
set_
Copy
	
{1, 5, 5.3, 6.6, 'item0', 'item4'}

Items cannot be duplicated, if a duplicate item is found, only one is kept.

	
set_ = {'item0', 1, 5.3, "item4", 5, 6.6, 'item0'}
set_
Copy
	
{1, 5, 5.3, 6.6, 'item0', 'item4'}

The length of the set can be obtained using the len() function.

	
len(set_)
Copy
	
6

As can be seen, the length of the set is 6 and not 7, since it remains with only one 'item0'

It can be checked if an item is in the set

	
'item4' in set_
Copy
	
True
2.5.1.1. Add itemslink image 124

An element can be added to a set using the add() method.

	
set_.add(8.8)
set_
Copy
	
{1, 5, 5.3, 6.6, 8.8, 'item0', 'item4'}

Another set can be added using the update() method.

	
set2 = {"item5", "item6", 7}
set_.update(set2)
set_
Copy
	
{1, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5', 'item6'}

Items can also be added from iterable data types in 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. Remove itemslink image 125

An item can be removed using the remove() method.

	
set_.remove('item9')
set_
Copy
	
{1, 10, 11.2, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5', 'item6'}

Or using the discard() method

	
set_.discard('item6')
set_
Copy
	
{1, 10, 11.2, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5'}

The pop() method can remove the last item, but since sets are unordered, there's no way to know which is the last item. The pop() method returns the removed item.

	
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

The clear() method can be used to empty the set.

	
set_.clear()
set_
Copy
	
set()

Lastly, with del you can delete the set

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

a way to unite sets is through the union() method

	
set1 = {"a", "b" , "c"}
set2 = {1, 2, 3}
set3 = set1.union(set2)
set3
Copy
	
{1, 2, 3, 'a', 'b', 'c'}

Another way is through the update() method, but this way adds a set to another, it doesn't create a new one.

	
set1 = {"a", "b" , "c"}
set2 = {1, 2, 3}
set1.update(set2)
set1
Copy
	
{1, 2, 3, 'a', 'b', 'c'}

These methods of union remove the duplicates, but if we want to get the duplicated elements in two sets we can use the intersection() method.

	
set1 = {"apple", "banana", "cherry"}
set2 = {"google", "microsoft", "apple"}
set3 = set1.intersection(set2)
set3
Copy
	
{'apple'}

If we want to get the duplicate elements in two sets, but without creating a new set, we can use the intersection_update() method.

	
set1 = {"apple", "banana", "cherry"}
set2 = {"google", "microsoft", "apple"}
set1.intersection_update(set2)
set1
Copy
	
{'apple'}

Now, if we want to get rid of the duplicates, we can use the symmetric_difference() method. The difference between this and the union of two sets is that in the union, all items are included, but duplicates are only taken once. Now we keep only those that are not duplicated.

	
set1 = {"apple", "banana", "cherry"}
set2 = {"google", "microsoft", "apple"}
set3 = set1.symmetric_difference(set2)
set3
Copy
	
{'banana', 'cherry', 'google', 'microsoft'}

If we want to remove the duplicates without creating a new set, we use the symmetric_difference_update() method.

	
set1 = {"apple", "banana", "cherry"}
set2 = {"google", "microsoft", "apple"}
set1.symmetric_difference_update(set2)
set1
Copy
	
{'banana', 'cherry', 'google', 'microsoft'}
2.5.1.4. Methods of setslink image 127

These are the methods that can be used with sets.

2.5.2. FrozenSetlink image 128

The frozensets are like sets but with the safety that they are immutable, just as tuples are like lists but immutable. Therefore, we cannot add or remove items.

2.6. Booleanslink image 129

There are only two booleans in Python: True and False

The function bool() can evaluate if anything is True or False.

	
print(bool("Hello"))
print(bool(15))
print(bool(0))
Copy
	
True
True
False

2.6.1. Other Data Types True and Falselink image 130

The following data are True:* Any string that is not empty* Any number except 0* Any list, tuple, dictionary, or set that is not empty

	
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. Binarieslink image 131

2.7.1. Byteslink image 132

The bytes type is an immutable sequence of bytes. It only accepts ASCII characters. Bytes can also be represented using integers whose values must satisfy 0 <= x < 256.

To create a byte type, we must introduce the character b

	
byte = b"MaximoFN"
byte
Copy
	
b'MaximoFN'

It can also be created using its constructor bytes()

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

Bytes can be concatenated using the + operator.

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

Repetition with the * operator

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

We can check if a character is within the string

	
b'D' in byte1
Copy
	
False

These are the methods that can be used with bytes.

2.7.2. Bytearraylink image 133

The bytearrays are the same as bytes except that they are mutable.

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

2.7.3. MemoryViewlink image 134

The memoryview objects allow Python code to access the internal data of an object that supports the buffer protocol without making copies. The memoryview() function allows direct read and write access to the byte-oriented data of an object without the need to copy it first. This can result in significant performance gains when working with large objects, as it does not create a copy when slicing. buffer protocol, it can create another access object to modify large data without copying it. This makes the program use less memory and increase execution speed.

	
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. Operatorslink image 135

3.1. Arithmetic Operatorslink image 136

Operator sum +

	
3 + 5
Copy
	
8

Operator minus -

	
3 - 5
Copy
	
-2

Multiplication operator *

	
3 * 5
Copy
	
15

Division operator /

	
3 / 5
Copy
	
0.6

Modulo operator %. Returns the remainder of a division.

	
25 % 2
Copy
	
1

Exponent operator **

	
5 ** 2
Copy
	
25

Integer division operator //

	
25 // 2
Copy
	
12

3.2. Comparison Operatorslink image 137

Operator is equal ==

	
1 == 1
Copy
	
True

Operator is different !=

	
1 != 2
Copy
	
True

Operator is greater than >

	
3 > 2
Copy
	
True

Operator is less than <

	
2 < 3
Copy
	
True

Operator is greater than or equal to >=

	
3 >= 3
Copy
	
True

Operator is less than or equal to <=

	
3 <= 3
Copy
	
True

3.3. Logical Operatorslink image 138

Operator and

	
True and True
Copy
	
True

Operator or

	
True or False
Copy
	
True

Operator not

	
not False
Copy
	
True

3.4. Identity Operatorslink image 139

Operator is

	
5.3 is 5.3
Copy
	
True

Operator is not

	
5.3 is not 5
Copy
	
True

3.5. Membership Operatorslink image 140

Operator in

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

Operator not in

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

3.6. Bitwise Operatorslink image 141

Operator AND &

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

Operator OR |

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

XOR operator ^

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

Operator NOT ~

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

Left shift operator <<

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

Right shift operator >>

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

3.7. Assignment Operatorslink image 142

Operator `=

	
a = 5
a
Copy
	
5

Operator +=. x += y is equivalent to x = x + y

	
a += 5
a
Copy
	
10

Operator -=. x -= y is equivalentTox = x - y

	
a -= 5
a
Copy
	
5

Operator *=. x *= y is equivalent to x = x * y

	
a *= 3
a
Copy
	
15

Operator /=. x /= y is equivalentTox = x / y

	
a /= 3
a
Copy
	
5.0

Operator %=. x %= y is equivalentTox = x % y

	
a = 25
a %= 2
a
Copy
	
1

Operator //=. x //= y is equivalent to x = x // y

	
a = 25
a //= 2
a
Copy
	
12

Operator **=. x **=y is equivalent to x = x ** y

	
a = 5
a **= 2
a
Copy
	
25

Operator &=. x &= y is equivalent to x = x & y

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

Operator |=. x |= y is equivalent to x = x | y

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

Operator ^=. x ^= y is equivalent to x = x ^ y.

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

Operator >>=. x >>= y is equivalent to x = x >> y.

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

Operator <<=. x <<= y is equivalent to x = x << y

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

4. Flow Controllink image 143

To be able to use the flow control tools, it is necessary to add a colon : and on a new line write the code with indentation. Unlike other languages, Python requires indentation (white space at the beginning of a line) to define the code inside a control structure.

4.1. Iflink image 144

With if we can create conditionals

	
if len('MaximoFN') == 8:
print('MaximoFN tiene 8 caracteres')
Copy
	
MaximoFN tiene 8 caracteres

If we want to createMoreThanOneConditionWeCanUseelif

	
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

If what we want is to execute something in case ofNoConditionsMatch, we can use 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

If we want to write everything in oneLine

	
if len('MaximoFN') == 8: print('MaximoFN tiene 8 caracteres')
Copy
	
MaximoFN tiene 8 caracteres

Equal, if we want to write everything in one line, ButWithSeveral conditions

	
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

If, for example, we want to create the structure of the if without specifying the conditions at the moment, we can use 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 145

The while loop executes as long as the condition is True

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

If we want the loop to stop under some condition, we use break

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

If we want one of the iterations not to executeForSomeReason, we use continue

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

The else block can be executed if the condition of the while loop is not 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 146

The for loop is used to execute code while iterating over an iterable. This iterable can be any Python iterable (string, list, tuple, range, dictionary, 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

Sets can also be iterated, but since they are unordered, there is no control over the order of execution.

	
set_ = {'M', 'a', 'x', 'i', 'm', 'o', 'F', 'N'}
for x in set_:
print(x, end='')
Copy
	
NximoaMF

If we want the loop to stop under some condition, we use break

	
string = 'MaximoFN'
for x in string:
if x == 'F':
break
print(x, end='')
Copy
	
Maximo

If we want one of the iterations not to executeForSomeReason, we use continue

	
string = 'Maximo FN'
for x in string:
if x == ' ':
continue
print(x, end='')
Copy
	
MaximoFN

The else block can be executed if the condition of the while loop is not True

	
string = 'MaximoFN'
for x in string:
print(x, end='')
else:
print("\nSe ha terminado el for")
Copy
	
MaximoFN
Se ha terminado el for

If forExample we want to create the structure of the for loop, at this point, to be able to fill it in later, we can use pass

	
string = 'MaximoFN'
for x in string:
pass
print('Interior del for no codificado')
Copy
	
Interior del for no codificado

5. Functionslink image 147

A function is a portion of code that can be executed multiple times as needed. It can take arguments and can return data as a result.

To define a function, you start with the reserved word def, followed by the functionName, parentheses (), a colon :, and then continue on a new indented line with the function code.

	
def funcion():
print('MaximoFN')
Copy

To call the function, it is only necessary to write its name.

	
funcion()
Copy
	
MaximoFN

Functions canTakeAnyArgumentsPassedAsParametersAndSeparatedByCommas

	
def funcion(string1, string2):
print(string1 + ' ' + string2)
funcion("Hola", "MaximoFN")
Copy
	
Hola MaximoFN

When calling the function, you must pass it the same number of arguments that were declared; otherwise, you would get an error. If we don't know the arguments that the functionWillReceive *args, it means that a * is used before the arguments to indicate that the number ofArguments is variable. When doing this, you passIt a tuple (which is immutable)WithTheArguments

	
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

In case you don't know the order of the arguments of a function, you can specify the argument you want to pass by indicating its name.

	
def funcion(argumento1, argumento2, argumento3):
print(argumento1 + ' '+ argumento2 + ' ' + argumento3)
funcion(argumento3 = "MaximoFN", argumento1 = "Blog", argumento2 = "de")
Copy
	
Blog de MaximoFN

In case you want to pass the arguments with their names, butEnCaseOf does notKnow howManyArguments there are to pass, you canUse **kwargs. In this case, a dictionary with the arguments will be passed.

	
def funcion(**kargumentos):
print("Autor del blog: " + kargumentos["autor"])
funcion(blog = "Blog", pertenencia = "de", autor = "MaximoFN")
Copy
	
Autor del blog: MaximoFN

If we want some argument to have a default value between the parameters of the function. This way, if the default value is not passed to the function, the argument in the function will have the default value.

	
def funcion(argumento1, argumento2, argumento3 = "MaximoFN"):
print(argumento1 + ' '+ argumento2 + ' ' + argumento3)
funcion("Blog", "de")
Copy
	
Blog de MaximoFN

Any type of data can be passed as an argument. For example, if a list is passed as an argument, within the function, that argument will be treated as a list.

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`.
      

Becomes:

Any type of data can be passed as an argument. For example, if a `list` is passed as an argument, within the function, that argument will be treated as a `list`.
      
	
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

Functions can return data, this is done using the reserved word return.

Las funciones pueden devolver datos, esto se hace mediante la palabra reservada `return`
      
Functions can return data, this is done using the reserved word `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

Can return more than one data

	
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

If one of the returned data is not of interest, we can skip it using _.

a, _, c = some_function()
      

This is a common practice in Python to ignore certain values that are returned but not needed.


If one of the returned data is not of interest, we can skip it using _.

a, _, c = some_function()
      
	
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

If, for example, we want to create the structure of the function but do not want to, for the moment, code the interior, we can use pass.

def my_function():
          pass
      

Si queremos indicar que la función aún no está completa, podemos usar un comentario o TODO:

def my_function():
          # TODO: Implementar la lógica de la función
          pass
      
	
def funcion():
pass
funcion()
Copy

A function can call itself, this is called recursion or function recursivity.

A function can call itself, this is called recursion or function recursivity.
      

Este método es útil para resolver problemas que se pueden descomponer en subproblemas más pequeños y similares al problema original.

This method is useful for solving problems that can be broken down into smaller, similar subproblems.
      

Si necesitas más ejemplos o tienes dudas, no dudes en pregar.

If you need more examples or have doubts, don't hesitate to ask.
      

For example, we can use this property to calculate the factorial of a number.

	
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 148

There is a series of predefined functions in Python that can be used, such as the abs() function, which returns the absolute value.

There is a series of predefined functions in Python that can be used, such as the `abs()` function, which returns the absolute value.
      
	
abs(-5)
Copy
	
5

The following is a list of these functions

	
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. Function Documentationlink image 149

We can add an explanation of a function we create by including a comment at the beginning of the function, so when we call the built-in function help(), it will display that explanation.

	
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

Another option to see the function explanation is to use the function's __doc__doc` is a built-in attribute that contains the docstring of the function. You can access it like this:

print(my_function.__doc__)
      
  • Pros:
    • It's a direct and easy way to access the docstring.
  • Cons:
    • It is less readable and less commonly used than the help() function.
def my_function():
          """
          This is a sample function to demonstrate the use of `__doc__`.
          """
          pass
      
      print(my_function.__doc__)
      

This will output the docstring of my_function.

"""
      This is a sample function to demonstrate the use of `__doc__`.
      """
      
	
funcion.__doc__
Copy
	
'Esta es la explicación de la función'

5.3. Decoratorslink image 150

Decorators are a Python feature that allows adding new features to a function.

# Example of a decorator
      def my_decorator(func):
          def wrapper():
              print("Something is happening before the function is called.")
              func()
              print("Something is happening after the function is called.")
          return wrapper
      
      @my_decorator
      def say_hello():
          print("Hello!")
      
      say_hello()
      

Note: This is a basic example of how decorators work in Python. They can be used to modify or enhance the behavior of functions or methods without permanently modifying the original code.


If you want to learn more about decorators, you can check the official Python documentation or other resources online. A decorator function is created that takes another function as a parameter. Then the decorator function adds the new feature to the function it receives.

def my_decorator(func):
          def wrapper():
              print("Something is happening before the function is called.")
              func()
              print("Something is happening after the function is called.")
          return wrapper
      
      @my_decorator
      def say_hello():
          print("Hello!")
      
      say_hello()
      

Este es un ejemplo de cómo se ve un decorador básico en Python. La función my_decorator toma func como parámetro y crea una función wrapper que agrega funcionalidades antes y después de llamar a func.

Cuando se llama a say_hello(), en realidad se está llamando a wrapper()

	
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
==================

But another more powerful way to use decorators is by using @ and the decorator's name before the function.

@decorator
      def function():
          pass
      

Este es un ejemplo de cómo se ve en el código.

@decorator
      def example_function():
          print("Esta función está decorada.")
      

Este método es más limpio y legible, especialmente cuando se usan múltiples decoradores.

@decorator1
      @decorator2
      def another_example_function():
          print("Esta función tiene dos decoradores.")
      

Esto facilita la lectura y el mantenimiento del código, ya que los decoradores se aplican de abajo hacia arriba.

@decorator1
      @decorator2
      def yet_another_example_function():
          print("Esta función tiene dos decoradores en orden inverso.")
      

Es importante notar que el orden en el que se aplican los decoradores puede afectar el comportamiento de la función decorada. That is, first the decorator is defined and then a function is called with the defined decorator.

def my_decorator(func):
          def wrapper():
              print("Something is happening before the function is called.")
              func()
              print("Something is happening after the function is called.")
          return wrapper
      
      @my_decorator
      def say_hello():
          print("Hello!")
      
      say_hello()
      
  • This will output:
Something is happening before the function is called.
      Hello!
      Something is happening after the function is called.

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 and **kwargslink image 151

*args and **kwargs are optional arguments that can be used when defining a function in Python. The syntax is as follows:

def my_function(arg1, arg2, *args, **kwargs):    # function code here```
      

2.5.1. *argslink image 152

*args is used to pass a variable number of arguments to a function. By using *args, you can pass a variable number of arguments to the function without having to specify the exact number of arguments the function needs. The arguments are received in the function as a tuple.

	
def saludo(saludo, *nombres):
for nombre in nombres:
print(f"{saludo}, {nombre}")
saludo("Hola", "Alicia", "Roberto", "Carlos")
Copy
	
Hola, Alicia
Hola, Roberto
Hola, Carlos

2.5.2. **kwargslink image 153

**kwargs is used in the same way, but to send a variable number of keyword arguments to a function. When using **kwargs, you can send a variable number of arguments to the function and specify the value of each argument using its name. The arguments are received in the function as a dictionary.

	
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. Additional Functionslink image 154

6.1. Lambda functionslink image 155

A lambda function is a small anonymous function.

una función *lambda* es una pequeña función anónima.
      
A *lambda* function is a small anonymous function.
      

Este método es útil para funciones cortas y simples que no necesitan un nombre propio. A lambda function can take any number of arguments, but can only have one expression.

A *lambda* function can take any number of arguments, but can only have one expression.
      

This command is already in English, so no translation is needed. However, if you need the entire text in English, here it is:

A *lambda* function can take any number of arguments, but can only have one expression.
      

Lambda functions are defined as follows: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

The power of lambda is best demonstrated when you use them as an anonymous function inside another function.

def my_function(n):
          return lambda a, b: (a + b) * n
      
      doubler = my_function(2)
      print(doubler(1, 2))  # Output: 6
      

En este ejemplo, my_function devuelve una función lambda que toma dos argumentos a y b, y multiplica su suma por n.

  1. Uso en funciones de orden superior: Las funciones lambda son muy útiles cuando se utilizan con funciones de orden superior como map(), filter(), y reduce().
# Uso con map()
      numbers = [1, 2, 3, 4, 5]
      squared = list(map(lambda x: x**2, numbers))
      print(squared)  # Output: [1, 4, 9, 16, 25]
      
      # Uso con filter()
      even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
      print(even_numbers)  # Output: [2, 4]
      
      # Uso con reduce()
      from functools import reduce
      product = reduce(lambda x, y: x * y, numbers)
      print(product)  # Output: 120
      

En estos ejemplos, las funciones lambda se utilizan para definir operaciones breves y concisas que se aplican a cada elemento de una lista o para reducir una lista a un solo valor.

	
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. map Functionlink image 156

The map function allows applying a function to each element of an iterable structure.

# Example usage of map
      numbers = [1, 2, 3, 4]
      squared = map(lambda x: x**2, numbers)
      print(list(squared))  # Output: [1, 4, 9, 16]
      

La función map toma dos argumentos: la función que se aplicará y el iterable sobre el cual se aplicará la función. El resultado es un objeto iterable que puede convertirse en una lista u otra estructura de datos.

# Another example
      words = ["hello", "world", "python"]
      uppercased = map(str.upper, words)
      print(list(uppercased))  # Output: ['HELLO', 'WORLD', 'PYTHON']
      

Esta función es muy útil para transformar datos de manera concisa y eficiente.

	
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]

This is equivalent to using list comprehension

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

6.3. filter Functionlink image 157

The filter function allows selecting the elements from an iterable structure that meet a condition.

# Example usage of filter
      numbers = [1, 2, 3, 4, 5]
      even_numbers = filter(lambda x: x % 2 == 0, numbers)
      print(list(even_numbers))  # Output: [2, 4]
      

La función filter es útil para filtrar elementos en una lista o cualquier otra estructura iterable basada en una condiciónThe filter function is useful for filtering elements in a list or any other iterable structure based on a condition.

	
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]

This is equivalent to using list comprehension

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

6.4. reduce Functionlink image 158

The reduce function allows performing accumulative tasks on iterable structures.

La función `reduce` permite realizar tareas acumulativas sobre estructuras iterables.
      

Becomes:

The `reduce` function allows performing accumulative tasks on iterable structures.
      
	
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. zip Functionlink image 159

With the zip function, you can combine multiple iterable structures into one, meaning it allows you to group several elements from the structures Ax into a single structure B. The structure B is composed of tuples of the elements from the structures Ax.

	
nombres = ["Manolo", "Andres", "Fernando"]
altura = [181, 178, 180]
my_zip = list(zip(nombres, altura))
my_zip
Copy
	
[('Manolo', 181), ('Andres', 178), ('Fernando', 180)]

65. Generatorslink image 160

Suppose we want to iterate over a sequence of numbers, but in a special way that no loop provides. This can be solved with generators. To do this, the generator function should not return the value with return, but with yield so that it knows it needs to continue iterating.

	
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

We just created an iterator for numbers that are multiples of 3

666. High order functionslink image 161

We can create functions that receive other functions as parameters, so the function that receives another function as a parameter is called a higher-order function (high order function). Let's see an example.

	
def increment(x):
return x + 1
def hof(f, x):
return 2*f(x)
print(hof(increment, 3))
Copy
	
8

7. Classes and Objectslink image 162

Python is an object-oriented programming language. Almost everything in Python is an object, with its attributes and methods. A class is like an object constructor or a "blueprint" for creating objects. To create a class, the reserved word class is used.

	
class Clase:
variable = 'MaximoFN'
Copy

Once the class has been created, an object of that class can be created.

	
objeto = Clase()
Clase.variable
Copy
	
'MaximoFN'

Normally, classes have an initialization function that runs when an object of the class is created. This function is called dunder init and is written as __init__(). The dunder init function must always be passed the variable self, which refers to the class itself, and then any additional variables you want to pass. This function is usually used to initialize the variables of the classes, or to execute the code that is needed when an object of the class is created.

	
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

In addition to the initial dunder init function, more functions can be created. These functions are called methods of the class. These methods always need to be passed the self variable.

	
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

The variable self does not have to be called self, it can have any name, but within each class it must always be the same. But by convention, self is usually used.

	
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

Variables of objects can be modified.

	
objeto_persona.nombre = 'Marta'
objeto_persona.saludar()
Copy
	
Hola mi nombre es Marta y tengo 36 años

Even removing them

	
del objeto_persona.nombre
Copy

The entire object can also be deleted.

	
del objeto_persona
Copy

If, for example, we want to create the structure of the class but do not want to, for now, code the interior, we can use pass

	
class Persona:
pass
objeto_persona = Persona()
Copy

7.1. Inheritancelink image 163

Inheritance allows us to define a class that inherits all the methods and properties from another class. The parent class is the class from which inheritance occurs, also called the base class. The child class is the class that inherits from another class, also called the derived class.

We create a parent class

	
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

To create the child class, you need to indicate between parentheses, when declaring the class, which class it inherits from.

	
class Estudiante(Persona):
pass
Copy

And when creating the object of the child class, the parameters that the parent class needs are passed.

	
objeto_hijo = Estudiante("Mariano", "Sanz")
objeto_hijo.imprimir_nombre()
Copy
	
Me llamo Mariano Sanz

So far, the child class has inherited the functions from the parent class, but we can modify them by overriding them. For example, by overriding the dunder init function. If the dunder init function is rewritten, if we want to call the dunder init function of the parent class, we need to call it. There are two ways to do this, one is through the name of the parent class. In this case, you have to pass it the self variable.

	
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

Another way is through super(), in this case you don't need to pass the self variable.

	
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

By modifying the functions, new code can be added.

	
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

Lastly, new methods can be added.

	
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. Operator Overloadinglink image 164

We can define basic operations, such as addition, between multiple objects of a class. For example, if we have a class that represents a vector, we can define addition and multiplication between objects of that class.

	
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)

All possible operator overloads are:

  • __add__(self, other): overloads the addition operator (+).* __sub__(self, other): overloads the subtraction operator (-).* __mul__(self, other): overloads the multiplication operator (*).* __truediv__(self, other): overloads the division operator (/).* __floordiv__(self, other): overloads the floor division operator (//). * __mod__(self, other): overloads the modulo operator (%).* __divmod__(self, other): overloads the divmod() function. * __pow__(self, other): overloads the power operator (**). * __lshift__(self, other): overloads the left shift operator (<<).* __rshift__(self, other): overloads the right shift operator (>>).* __and__(self, other): overloads the and operator (&).* __or__(self, other): overloads the or operator (|).* __xor__(self, other): overloads the xor operator (^). * __lt__(self, other): overloads the less than comparison operator (<).* __le__(self, other): overloads the less than or equal to comparison operator (<=).* __eq__(self, other): overloads the equality comparison operator (==).* __ne__(self, other): overloads the not equal to comparison operator (!=).* __gt__(self, other): overloads the greater than comparison operator (>).* __ge__(self, other): overloads the greater than or equal to comparison operator (>=).* __neg__(self): overloads the negation operator (-).* __pos__(self): overloads the unary positive operator (+). * __abs__(self): overloads the abs() function.* __invert__(self): overloads the inversion operator (~).* __complex__(self): overloads the complex() function. * __int__(self): overloads the int() function. * __float__(self): overloads the float() function.

7.3. Custom Iteratorslink image 165

As we have seen in section 2 (Python Data Types), there are some data types that can be iterated over. But we can create our own iterable class, as long as it has the functions __len__ and __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

Now we can iterate over the object of our class with for loops, for example

	
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. Calling Objects as Functionslink image 166

We might want to call an object of a function as if it were a class. This can be achieved by adding the __call__ function to the class.

	
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. Private Attributes and Functionslink image 167

When we create a class, we can make some attributes or functions private so they cannot be accessed from outside the class. To do this, you need to add __ before the attribute or method.

	
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. Iteratorslink image 168

An iterator is an object that contains a countable number of values. An iterator is an object over which you can iterate, meaning you can traverse all the elements. Technically, in Python, an iterator is an object that implements the iterator protocol, which consists of the methods iter() and next().

Lists, tuples, dictionaries, and sets are all iterable objects. They are iterable containers from which you can get an iterator. All these objects have an iter() method that is used to get an iterator:

	
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

The for loop actually creates an iterator object and calls the next() method on each iteration.

	
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. Create an iterator objectlink image 169

To create an object/class as an iterator, you need to implement the methods __iter__() and __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

The previous example would continue indefinitely if it had enough calls to next(), or if it were used in a for loop. To prevent the iteration from continuing forever, we can use the StopIteration statement. In the __next__() method, we can add a termination condition to raise an error if the iteration is performed a specific number of times:

	
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. Iterating getting the index and valuelink image 170

We can iterate over an iterable object, obtaining its index and value in each iteration using the enumerate() method.

	
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. Iterating simultaneously over two iterable objectslink image 171

If we have two iterable objects of the same length, we can iterate over both at the same time using the zip() method.

	
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. Variable Scopelink image 172

A variable is only available within the region where it is created. This is called scope.

9.1. Local Scopelink image 173

A variable created within a function belongs to the local scope of that function and can only be used within that function.

	
def funcion():
x = 300
print(x)
funcion()
Copy
	
300

The variable x is not available outside the function, but it is available to any function within it.

	
def funcion():
x = 300
def funcion_interna():
print(x)
funcion_interna()
funcion()
Copy
	
300

9.2. Global Scopelink image 174

A variable created in the main body of the Python code is a global variable and belongs to the global scope. Global variables are available from any scope, global and local.

	
x = 300
def funcion():
print(f'Ámbito local: {x}')
funcion()
print(f'Ámbito global: {x}')
Copy
	
Ámbito local: 300
Ámbito global: 300

If two variables are created, one global and one local, both with the same name, Python will create them as two distinct variables.

	
x = 300
def funcion():
x = 200
print(f'Variable local: {x}')
funcion()
print(f'Variable global: {x}')
Copy
	
Variable local: 200
Variable global: 300

If a global variable needs to be created, but it is declared in the local scope, the global keyword can be used. The keyword global makes the variable global.

	
def funcion():
global x
x = 300
funcion()
print(f'Variable global: {x}')
Copy
	
Variable global: 300

In addition, the use of the global keyword allows making a change to a global variable within a function.

	
x = 300
def funcion():
global x
x = 200
funcion()
print(f'Variable global: {x}')
Copy
	
Variable global: 200

10. Moduleslink image 175

A module is a file that contains a set of functions that you want to include in your application. To create a module, simply save the code you want in a file with the file extension .py

Tip: In Jupyter notebooks (Colab is an online Jupyter notebook) if we write the character ! before a command we can execute terminal commands

First, let's see which directory we are in. For that, we use the pwd command (print working directory).

	
!pwd
Copy
	
/home/wallabot/Documentos/web/portafolio/posts

Let's create a folder to create our modules with the mkdir (make directory) command.

	
!mkdir introduccion_python
Copy

Let's see what files are in our folder. We will do this using the ls (list) command.

	
!ls introduccion_python
Copy

We see that it is empty, so we create a new .py file in which we are going to create our module.

	
%%writefile introduccion_python/modulo1.py
def funcion_del_modulo(nombre):
print("Hola, " + nombre)
Copy
	
Writing introduccion_python/modulo1.py

We check again what files are in our folder

	
!ls introduccion_python
Copy
	
modulo1.py __pycache__

We see that a file modulo1.py has been created. We can now use it.

To use an external module, you have to use the import keyword. To use the functions of the module, you have to put first the name of the module, a . and then the name of the function you want to use.

	
import introduccion_python.modulo1
introduccion_python.modulo1.funcion_del_modulo('MaximoFN')
Copy
	
Hola, MaximoFN

If we want our module to have a specific name within our code, we can use the word as

	
import introduccion_python.modulo1 as mod1
mod1.funcion_del_modulo('MaximoFN')
Copy
	
Hola, MaximoFN

If the module has several functions, but we only want to import one, we can do this using the from and import keywords. The form would be

from <module> import <function>```
      
      In this case, there is no need to specify the module name when calling the function.
	
%%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

We can not only use modules created by us, but also installed modules (built-in modules). For example, we can use the platform module

	
import platform
x = platform.system()
x
Copy
	
'Linux'

10.1. Entry points: files as modules and not as scriptslink image 176

Now let's create a file called 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

If we now import modulo3.py to use the funcion_del_modulo function, let's see what happens.

	
import introduccion_python.modulo3 as mod3
print(mod3.funcion_del_modulo())
Copy
	
Hola desde modulo3
Hola desde la función del modulo3

We see that the print from modulo3.py has been executed, but that's not what we wanted. This is because when the file is named modulo3.py, Python runs it as a script.

But what if we want to run introduccion_python/main.py as a script?

	
!python introduccion_python/modulo3.py
Copy
	
Hola desde modulo3

We see that only the print is executed, but not the function funcion_del_modulo. If we want the duality of functionality of the file modulo3.py, that is, to be able to import it from another module without it executing as a script and to run it standalone and execute the function we want, we use an entry point. That is, using the condition if __name__ == '__main__': and then specifying what we want to execute. Let's see this with an example, I will rewrite the modulo3.py file.

	
%%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

If I now call main.py from another module, the print will no longer be executed.

	
import introduccion_python.modulo3 as mod3
print(mod3.funcion_del_modulo())
Copy
	
Hola desde la función del modulo3

And if I run it as a standalone script, the function funcion_del_modulo will be executed.

	
!python introduccion_python/modulo3.py
Copy
	
Hola desde modulo3

11. Packageslink image 177

In Python we can create our own packages. To do this, we create a folder with the package name.

	
!mkdir mi_paquete_de_python
Copy

We now create two files inside

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

And we write in them

	
%%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

Now we can call the functions from our package

	
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

But what if our package has dozens of files with functions that we want to use, would we have to import all the files one by one? To avoid this, we can create an __init__.py file within the package where all these file imports can be handled.

	
!touch mi_paquete_de_python/__init__.py
Copy
	
%%writefile mi_paquete_de_python/__init__.py
import modulo1
import modulo2
Copy
	
Overwriting mi_paquete_de_python/__init__.py

Now we can only import our package, which internally has already imported all the modules

	
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

This way we only have to do an import

12. Try... exceptlink image 178

When an error, or an exception as it is actually called, occurs, Python will normally catch it and generate an error message. These exceptions can be handled using the try and except statements.

	
try:
print(variable_no_declarada)
except:
print("Ha ocurrido una excepción")
Copy
	
Ha ocurrido una excepción

Since the try block raises an error, the except block will be executed. Without the try block, the program would freeze and generate an error.

As many exception blocks as desired can be defined, for example, if a special block of code is to be executed for a special type of error.

	
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

The word else can be used to indicate the case where no error has occurred.

	
try:
print('MaximoFN')
except NameError:
print("Ha ocurrido una excepción")
else:
print('Todo OK')
Copy
	
MaximoFN
Todo OK

with the finally keyword, the code will be executed at the end whether an exception occurred or not

	
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

This can be useful for closing objects and cleaning up resources

	
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. Create an exceptionlink image 179

As a Python developer, you can choose to raise an exception if a condition occurs. To raise (or generate) an exception, you need to use the keyword 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

You can define what type of error to generate and the text that will be displayed to the user.

	
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 or reserved wordslink image 180

Throughout this post, several occasions have featured Python reserved words or keywords, these are a series of words reserved by Python Below is a list of the 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. The ZEN of Pythonlink image 181

By importing the this module we can read the zen of Python, that is, its philosophy or principles.

	
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!

Continue reading

Last posts -->

Have you seen these projects?

Subtify

Subtify Subtify

Subtitle generator for videos in the language you want. Also, it puts a different color subtitle to each person

View all projects -->

Do you want to apply AI in your project? Contact me!

Do you want to improve with these tips?

Last tips -->

Use this locally

Hugging Face spaces allow us to run models with very simple demos, but what if the demo breaks? Or if the user deletes it? That's why I've created docker containers with some interesting spaces, to be able to use them locally, whatever happens. In fact, if you click on any project view button, it may take you to a space that doesn't work.

Flow edit

Flow edit Flow edit

FLUX.1-RealismLora

FLUX.1-RealismLora FLUX.1-RealismLora
View all containers -->

Do you want to apply AI in your project? Contact me!

Do you want to train your model with these datasets?

short-jokes-dataset

Dataset with jokes in English

opus100

Dataset with translations from English to Spanish

netflix_titles

Dataset with Netflix movies and series

View more datasets -->