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.

This notebook has been automatically translated to make it accessible to more people, please let me know if you see any typos.

1. Summarylink image 92

We are going to make a brief introduction to Python, explaining the types of data we have, the operators, the use of functions and classes. We will also see how to use iterable objects, how to use modules, etc.

python

2. Python data typeslink image 93

There are 7 data types in Python

  1. Of type text:str
  2. Numeric: int, float, complex.
  3. Sequences: list, tuple, range.
  4. Mapping: dict.
  5. Sets: set, frozenset.
  6. Booleans: bool.
  7. Binaries: bytes, bytearray, memoryview.

We can obtain the data type by means of the type() function

	
type(5.)
Copy
	
float

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

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

Python types the variables for you, but if you want to type them yourself it can be done

	
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 to type int, we see that it is of type int and also its value is 5.

2.1. Stringslink image 94

Strings are character strings, they can be defined with double quotation marks " or single quotation marks '.

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

To write a very long string and not have a row that takes up a lot of space, you can enter it in several 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 can see that in the middle the character n has been inserted, this character indicates the line break. If we use the print() function we will see how it does not appear anymore.

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

As we have said, strings are character strings, 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 obtain the length of our string using the len() function

	
len(string)
Copy
	
73

Check if there is a certain string inside our string

	
'ejemplo' in string
Copy
	
True

Strings have certain useful attributes, such as capitalizing everything.

	
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 words

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

You can see all the methods of the strings in this link

Another useful thing you can do with the strings is to concatenate them

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

Earlier we explained that the n character corresponded to a line break, this special character corresponds to a series of special characters called Escape Characters. Let's see others

If we declare a string with double quotation marks and we want to add a double quotation mark 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 quotation mark, 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 scape character, since as we have seen it is an escape character, so we solve it by putting double backslash slash.

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

We have already seen before the escape character of new line 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 erase a character with ``b`.

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

We can add the code ASCII in octal by ``ooo`.

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

Or add the code ASCII in hexadecimal by xhh.

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

Finally, we can convert another data type to 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

Numbers of integer type

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

2.2.2.2. Floatlink image 97

Floating point type numbers

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

2.2.3. Complexeslink image 98

Complex numbers

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

2.2.4. Conversionlink image 99

You can convert between number 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)

Cannot convert a complex number 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 obtain 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 we start counting from position 0, that is, if we want to obtain the first position 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 through [2:5].

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

If the first number of the range is omitted it means that we want from the first item of 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 of the range is omitted it means that we want from the indicated item to the last one, i.e. if we want from the third item to the last one we use [3:].

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

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

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

You can check if an item is in the list

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

Lists in Python are dynamic, that is, 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]

You can also modify a range of values

	
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 given 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 by another list, it can be done by another iterable Python data type (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 delete a given 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 deleted.

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

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

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

The del() function can also be used to remove 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 indicated, the entire list is deleted.

With the clear() method leaves the list empty.

	
lista.clear()
lista
Copy
	
[]

The number of items with a given 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 given value by 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']

Another powerful feature of Python is list comprehension, which allows you to do everything in a single 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]

You can take advantage of this opportunity 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 sort 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 orders them allphabetically

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

When sorting alphabetically, distinguish between upper and lower case letters

	
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 sorted in any order 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]

You can take advantage of this so that, for example, when ordering, it does not distinguish between upper and lower case letters.

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

You can flip the list 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() list constructor.

	
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 by 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 cannot be modified or reordered. They are defined by (), with items separated by commas.

Not being able to be modified makes tuples run a little faster than lists, so if you don't need to modify the data it is 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 a tuple element, proceed in the same way as for 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 modifiable, 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 you can do is to delete the entire tuple

	
del tupla
if 'tupla' not in locals():
print("tupla eliminada")
Copy
	
tupla eliminada
2.3.2.2.2. Unpacking 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 get less data 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])

You can put the asterisk * elsewhere if, for example, what you want is the last item

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

You can concatenate tuples 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.2.2.4. Tuple Methodslink image 111

The tuples have two methods, the first is the count() method that returns the number of times an item exists 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 in the tuple.

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

2.3.3.3. Rangelink image 112

With range() we can create a sequence of numbers, starting from 0 (by default), 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 the 5)

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

If, for example, we do not 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

Finally, if we do not want it to increment by 1. If for example 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:data pairs. They are modifiable, unordered and do not allow duplicates. They are defined by 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 mentioned above, duplicity is 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 you can see the length is 4 and not 5, since year is counted only once.

2.4.1. Accessing Itemslink image 114

To access an item we can do it through its key.

	
diccionario["model"]
Copy
	
'Mustang'

It can also be accessed through the get() method.

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

To know all the keyss of the 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 keyss of the dictionary, so calling it once is required

	
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 obtain the dictionary values you can use the method 'values()'.

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

You can use a variable to point to the valuess of the dictionary, so 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 items integers, that is keys and values you have to 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 calling it once is required

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

You can check if a key exists in the dictionary.

	
"model" in diccionario
Copy
	
True

2.4.2. Modifying 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

You can add an item by adding it without further ado.

	
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. Delete 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 by del indicating the name of the key between the [] symbols.

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

The entire dictionary is deleted 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 you want to delete the last item entered, you can use the popitem() method.

	
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 clean the dictionary you must use the clear() method.

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

2.4.5. Copy dictionarieslink image 118

It is not possible to copy dictionaries using dictionary1 = dictionary2, because if dictionary1 is modified, dictionary2 is also 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. Nested dictionarieslink image 119

Dictionaries can have itemss of any type of data, including other dictionaries. Such 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 may be used in dictionaries

2.4.8. Dictionary comprehensionlink image 121

Just as we could make lists comprehensions using the syntax

list_comprehension = [expression for item in iterable if condition == True]
      ```
      
      We can make `disctionarys comprehensions` using the following syntax
      
      ``` python
      dictionary_comprehension = [key expression: value expression for item in iterable if condition == True].
      ```
      
      Let's see 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 set of items in a single variable. You can store items of different types. They are unordered and have no index.

They differ from lists in that they have neither order nor index.

They are declared by means of the symbols {}.

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

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

There can be no duplicate items, if any duplicate item is found, only one item 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 you can see the length of the set is 6 and not 7, since it remains with only one 'item0'.

You can check if an item is in the set.

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

An item can be added to the 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'}

You can also add items from Python iterable data types

	
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. Delete itemslink image 125

A given 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 by using the discard() method

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

Using the pop() method you can remove the last item, but since the sets are not sorted there is no way to know which is the last item. The pop() method returns the deleted 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

By means of the clear() method, the set can be emptied.

	
set_.clear()
set_
Copy
	
set()

Finally, with del you can delete the set

	
del set_
if 'set_' not in locals():
print("set eliminado")
Copy
	
set eliminado
2.5.1.3. Linking Itemslink image 126

One way to join 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 you add one set to another, not create a new one.

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

These union methods remove duplicates, but if we want to get the duplicate items in two sets we 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 items in two sets, but without creating a new set, we use the intersection_update() method.

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

Now the other way around, if we want to keep the non-duplicates we use the symmetric_difference() method.

The difference between that and the union between two sets is that in the union it keeps all the items, but the ones that are duplicated it only takes them once. Now we are left with the ones 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 keep the non-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. Set methodslink image 127

These are the methods that can be used in the sets

2.5.2. Frozensetlink image 128

The frozensets are like the sets but with the exception that they are immutable, just as the tuples are like the lists but immutable. So we will not be able to add or delete items

2.6. Booleanslink image 129

There are only two Booleans in Python: True and False.

Using the bool() function, you can evaluate whether 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 or Falselink image 130

The following data are True:

  • Any string that is not empty
  • Any number except 0
  • Any non-empty list, tuple, dictionary, or set
	
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. Only ASCII characters are supported. Bytes can also be represented by integers whose values must satisfy 0 <= x < 256.

To create a byte type we must first enter the character b.

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

They can also be created using its bytes() contructor.

	
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'

Or by repeating with the operator *.

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

We can check if a character is inside the string

	
b'D' in byte1
Copy
	
False

These are the methods that can be used in the bytes.

2.7.2. Bytearraylink image 133

The bytearrays are the same as bytes only they are mutable.

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

2.7.3. Memoryviewlink image 134

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 generate large performance gains when operating on large objects, since it does not create a copy when cutting.

Buffer protocol, you can create another access object to modify large data without copying it. This makes the program use less memory and increases 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

Sum operator +

	
3 + 5
Copy
	
8

Oeprador subtracts -

	
3 - 5
Copy
	
-2

Multiplication operator *

	
3 * 5
Copy
	
15

Operator division /

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

	
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

is not` operator

	
5.3 is not 5
Copy
	
True

3.5. Membership operatorslink image 140

Operator in

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

Not in` operator

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

3.6. Bitwise operatorslink image 141

AND operator &

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

OR operator |

	
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

NOT operator ~

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

Operator shift left << 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 equivalent to `x = 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 equivalent to `x = x / y

	
a /= 3
a
Copy
	
5.0

Operator %=. x %= y is equivalent to `x = 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

Flow controllink image 143

To be able to use the flow control tools it is necessary to add the statement, colon : and in a new line write the code with indentation

Unlike other languages, Python requires indentation (adding whitespace) to define the code inside a flow control tool.

Iflink image 144

Using if we can create conditions

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

If we want to create more than one condition we can use 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

If what we want is that something is executed in case none of the indicated conditions is fulfilled, 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 on a single line

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

The same, if we want to write everything in one line, but with several 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 make the if structure but we do not want, for the moment, to code one of the conditions 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 is executed 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 for 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 be executed for some reason 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

Using else you can execute a code block if the while condition 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 through a sequence, this sequence can be any iterable Python element (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

You can also iterate through the sets, but since they are unordered elements, you have 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 for 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 be executed for some reason we use continue.

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

Using else you can execute a code block if the while condition 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, for example, we want to make the for structure but we do not want to code the interior for the moment, 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 piece of code that can be executed as many times as you want. It can be passed arguments and can return data as a result.

To define a function, start with the reserved word def followed by the function name, parentheses (), colon : and then in a new line indented the function code

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

To call the function it is only necessary to type its name

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

You can pass as many arguments as you want to the functions, inside the parenthesis and separated by commas.

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

When calling the function you must pass the same number of arguments that have been declared, if you pass more or less you will get an error.

If we do not know the arguments that the function is going to receive, we can use *args, that is, putting an * before the arguments indicates that the number of arguments is free.

This is done by passing a tuple (remember that it is immutable) with the arguments

	
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 we do not know the order of the arguments of a function, we can indicate the argument we want to pass to it 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 name, but in case you don't know how many arguments will be passed, you can use **kargs. In this case a dictionary with the arguments will be passed to you.

	
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 we can indicate it between the parenthesis of the function. This way if at the time of calling the function this argument is not passed, this in the function will have the value by default

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

You can pass any type of data as an argument, for example if you pass a list as an argument, inside the function, this 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 by means of 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

More than one data can be returned

	
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 we are not interested in one of the returned data, we can skip it by _.

	
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 make the structure of the function but we do not want, for the moment, to code the interior we can use pass.

	
def funcion():
pass
funcion()
Copy

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

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

	
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 148

There are a number of functions already defined in Python that can be used, for example 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. Documentation of a functionlink image 149

An explanation of a function that we create can be added by means of a comment at the beginning of the function, this way when we call the built in function help() it will show us this 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 explanation of the function is to use the __doc__ method of the function

	
funcion.__doc__
Copy
	
'Esta es la explicación de la función'

5.3. Decoratorslink image 150

Decorators are a Python feature that allow you to add new features to a function.

A decorator function is created that has another function as parameter. The decorator function then adds the new feature to the function it receives

	
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 name before the function.

That is, the decorator is first defined and then a function is called with the defined decorator

	
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 **kwargs.link 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
      

5.4.1. *args.link image 152

*args is used to send a variable number of arguments to a function. By using *args, you can send a variable number of arguments to the function without having to specify the exact number of arguments the function needs. The arguments are received by 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

5.4.2. **kwargs.link image 153

**kwargs is used in the same way, but to send a variable number of keyword arguments to a function. By 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 by 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

Additional functionslink image 154

6.1. Functions *calllink image 155

A call function is a small anonymous function.

A call function can take any number of arguments, but it can only have one expression.

The 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 shown when you use it as an anonymous function inside another function.

	
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 you to apply a function to each element of an iterable structure.

	
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 you to select the elements of an iterable structure that meet a characteristic.

	
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. Function reduce.link image 158

The reduce function allows cumulative tasks to be performed 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 compress several iterable structures into a single one, that is, you can group several Ax structures into a single B structure. The B structure is formed by tuples of the elements of the Ax structures.

	
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. Generatorslink image 160

Suppose we want to iterate over a sequence of numbers, but in a special way that does not offer us any kind of loop, we can solve this with the generators. To be able to do this, the generator function does not have to return the value with return, but with yield so that it knows that it has 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 have just made an iterator for numbers multiples of 3

6.6. High order functionslink image 161

We can create functions that receive other functions as parameters, so that the function that receives another function as parameter is called a 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 properties and methods.

A class is like an object constructor or a "blueprint" for creating objects.

To create a class you use the reserved word class.

	
class Clase:
variable = 'MaximoFN'
Copy

Once the class has been created, you can create an object of this class

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

Normally classes have an initial function, which is executed when an object of the class is created. This function is called dunder init and is written __init__(). The function dunder init must always be passed the variable self, which indicates the class itself, and then, the variables that you want

This function is used to initialize the variables of the classes, or to execute the code required 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 must always be passed the 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

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 we usually use 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

Object variables can be modified

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

Even eliminate them

	
del objeto_persona.nombre
Copy

You can also delete the entire object

	
del objeto_persona.nombre
del objeto_persona
Copy

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

	
del objeto_persona.nombre
del objeto_persona
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 of another class.

The parent class is the class from which it is inherited, also called base class.

The child class is the class that inherits from another class, also called derived class.

We create a parent class

	
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

To create the child class you must indicate in 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 to it

	
class Estudiante(Persona):
pass
objeto_hijo = Estudiante("Mariano", "Sanz")
objeto_hijo.imprimir_nombre()
Copy
	
Me llamo Mariano Sanz

So far the child class has inherited the functions of the parent class, but we can modify them by rewriting them. For example by rewriting the duder init function.

If the dunder init function is rewritten, if we want the dunder init function of the parent class to be called, it must be called.

There are two ways to do this, one is through the name of the parent class, in this case you have to pass the variable self to it.

	
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 it is not necessary to pass the 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

New code can be added when modifying functions

	
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

Finally, 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 overloadlink image 164

We can define basic operations, such as addition, between several 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 overload operations 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 rounding division operator (//).
  • __mod__(self, other): overloads the module 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 comparison operator less than (<).
  • __le__(self, other): overloads the comparison operator less than or equal to (<=).
  • __eq__(self, other): overloads the comparison operator equal to (==).
  • __ne__(self, other): overloads the comparison operator other than (!=).
  • __gt__(self, other): overloads the comparison operator greater than (>).
  • __ge__(self, other): overloads the comparison operator greater than or equal to (>=).
  • __neg__(self): overloads the negation operator (-).
  • __pos__(self): overloads the position 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 make our own iterable class, as long as it has the __len__ and __getitem__ functions.

	
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 with the object of our class with for loops e.g.

	
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 may be interested in calling an object of a function as 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 and not accessible from outside the class, for this we must add __ before the attribute to class

	
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 that can be iterated over, which means that it can traverse all values.

Technically, in Python, an iterator is an object that implements the iterator protocol, which consists of the __iter__() and __next__() methods.

Lists, tuples, dictionaries and sets are all iterable objects. They are iterable containers from which you can get an iterator.

All these objects have a iter() method that is used to obtain 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 executes the next() method for each loop.

	
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, the __iter__() and __next__() methods must be implemented.

	
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 above example would continue forever if you 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 generate an error if the iteration is performed a specified 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. Iterate obtaining the index and valuelink image 170

We can iterate through an iterable object obtaining in each iteration its index and its value by means of 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. Iterate through two iterable objects at the same time.link image 171

If we have two iterable objects, whose length is the same, we can iterate through 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. Scope of variableslink image 172

A variable is only available within the region in which 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 for any function inside the function.

	
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 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 you need to create a global variable, but it is declared in the local scope, you can use the global keyword.

The global keyword 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 makes 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 containing 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 you type the ! character before a command you can execute console commands

First we are going to see in which directory we are, for that we use the pwd command (print working directory)

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

We will create a folder to create our modules with the command mkdir (make directory)

	
!mkdir introduccion_python
Copy

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

	
!mkdir introduccion_python
!ls introduccion_python
Copy

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

	
!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

We go back to see what files are in our folder

	
!ls introduccion_python
Copy
	
modulo1.py __pycache__

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

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

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

If we want the module to have a specific name in 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 by using the words from and import. The form would be

from <module> import <function>

In this case it is not necessary to indicate the name of the module 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 use not only modules created by us, but also modules already installed (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

We are now going to 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 module3.py to use the module_function function let us 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 of modulo3.py has been executed, but it is not what we wanted, this is because when the file modulo3.py is called, python executes it as a script.

But what if we want to run introduction_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 module_function function. If we want to have the duality of functionality of the module3.py file, that is, we can import it from another module without running it as a script and run it alone and execute the function we want, we use an entry point. That is, use the condition if __name__ == '__main__': and then indicate what we want to be executed. Let's see it with an example, I am going to rewrite the file 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

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 module_function function will be executed.

	
!python introduccion_python/modulo3.py
Copy
	
Hola desde modulo3

11. Packageslink image 177

In python we can create our own packages by creating a folder with the package name

	
!mkdir mi_paquete_de_python
Copy

We now create two files inside

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

And we write on them

	
!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

Now we can call the functions of 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, we would have to import all the files one by one. To avoid this, you can create a __init__.py file inside the package where all this file import is done.

	
!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

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

	
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

In this way we only have to do an import.

12. Try... Exceptlink image 178

When an error occurs, or an exception as it is actually called, Python will normally stop 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 generates an error, then the except block will be executed.

Without the try block, the program would crash and generate an error.

You can define as many exception blocks as you want, for example, if you want to execute a special code block for a special error type

	
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 an error has not occurred.

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

with the word finally a 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 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. Creating an exceptionlink image 179

As a Python developer, you can choose to throw an exception if a condition occurs.

To throw (or generate) an exception, you must use the raise keyword

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

During this post in several occasions Python reserved words or keywords have appeared, these are a series of words reserved by Python.

The following 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

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

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

Have you ever talked to an LLM and they answered you something that sounds like they've been drinking machine coffee all night long 😂 That's what we call a hallucination in the LLM world! But don't worry, because it's not that your language model is crazy (although it can sometimes seem that way 🤪). The truth is that LLMs can be a bit... creative when it comes to generating text. But thanks to DoLa, a method that uses contrast layers to improve the feasibility of LLMs, we can keep our language models from turning into science fiction writers 😂. In this post, I'll explain how DoLa works and show you a code example so you can better understand how to make your LLMs more reliable and less prone to making up stories. Let's save our LLMs from insanity and make them more useful! 🚀

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.

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