Introduction to Python
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. Summary
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.
2. Python data types
There are 7 data types in Python
- Of type text:
str
- Numeric:
int
,float
,complex
. - Sequences:
list
,tuple
,range
. - Mapping:
dict
. - Sets:
set
,frozenset
. - Booleans:
bool
. - Binaries:
bytes
,bytearray
,memoryview
.
We can obtain the data type by means of the type()
function
type(5.)
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 = 5type(a)
int
a = 'MaximoFN'type(a)
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
(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. Strings
Strings are character strings, they can be defined with double quotation marks "
or single quotation marks '
.
string = "MaximoFN"string
'MaximoFN'
string = 'MaximoFN'string
'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 decomo estoy introduciendo un stringen varias lineas"""string
'Este es un ejemplo de como estoy introduciendo un string en varias lineas'
string = '''Este es un ejemplo decomo estoy introduciendo un stringen varias lineas'''string
'Este es un ejemplo de como estoy introduciendo un string en varias lineas'
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)
Este es un ejemplo decomo estoy introduciendo un stringen 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 lineaprint(string[i], end='')
Este es un
We can obtain the length of our string using the len()
function
len(string)
73
Check if there is a certain string inside our string
'ejemplo' in string
True
Strings have certain useful attributes, such as capitalizing everything.
print(string.upper())
ESTE ES UN EJEMPLO DECOMO ESTOY INTRODUCIENDO UN STRINGEN VARIAS LINEAS
All in lowercase
print(string.lower())
este es un ejemplo decomo estoy introduciendo un stringen varias lineas
Replace characters
print(string.replace('o', '@'))
Este es un ejempl@ dec@m@ est@y intr@duciend@ un stringen varias lineas
Get all words
print(string.split())
['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
'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\"")
Este es el blog de "MaximoFN"
The same with the single quotation mark, we add '`'.
print('Este es el blog de \'MaximoFN\'')
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\\')
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')
Este es el blog deMaximoFN
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')
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')
Este es el blog de MaximoFN
We can erase a character with ``b`.
print('Este es el blog de \bMaximoFN')
Este es el blog deMaximoFN
We can add the code ASCII in octal by ``ooo`.
print('\115\141\170\151\155\157\106\116')
MaximoFN
Or add the code ASCII in hexadecimal by xhh
.
print('\x4d\x61\x78\x69\x6d\x6f\x46\x4e')
MaximoFN
Finally, we can convert another data type to string
n = 5print(type (n))string = str(n)print(type(string))
<class 'int'><class 'str'>
2.2. Numbers
2.2.1. Integers
Numbers of integer type
n = 5n, type(n)
(5, int)
2.2.2.2. Float
Floating point type numbers
n = 5.1n, type(n)
(5.1, float)
2.2.3. Complexes
Complex numbers
n = 3 + 5jn, type(n)
((3+5j), complex)
2.2.4. Conversion
You can convert between number types
n = 5n = float(n)n, type(n)
(5.0, float)
n = 5.1n = complex(n)n, type(n)
((5.1+0j), complex)
n = 5.1n = int(n)n, type(n)
(5, int)
Cannot convert a complex
number to type int
or type float
.
2.3. Sequences
2.3.1. Lists
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
['item0', 'item1', 'item2', 'item3', 'item4', 'item5']
We can obtain the length of a list using the len()
function.
len(lista)
6
Lists can have items of different types
lista = ['item0', 1, True, 5.3, "item4", 5, 6.6]lista
['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]
'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]
6.6
If instead of the last position in the list we want the penultimate one
lista[-2]
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]
[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]
['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:]
[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]
['item4', 5]
You can check if an item is in the list
'item4' in lista
True
2.3.1.1.1. Editing lists
Lists in Python are dynamic, that is, they can be modified. For example, you can modify the third item
lista[2] = Falselista
['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
['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
['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
['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
['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
['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
['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
['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
['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
['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
[]
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)
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)
0
2.3.1.2. List comprehension
We can operate through the list
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]newlist = []# Iteramos por todos los items de la listafor x in fruits:# Si el item contiene el caracter "a" lo añadimos a newlistif "a" in x:newlist.append(x)newlist
['apple', 'banana', 'mango']
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
['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
['APPLE', 'BANANA', 'MANGO']
2.3.1.3. Sorting lists
To sort lists we use the sort()
method.
lista = [5, 8, 3, 4, 9, 5, 6]lista.sort()lista
[3, 4, 5, 5, 6, 8, 9]
It also orders them allphabetically
lista = ["orange", "mango", "kiwi", "pineapple", "banana"]lista.sort()lista
['banana', 'kiwi', 'mango', 'orange', 'pineapple']
When sorting alphabetically, distinguish between upper and lower case letters
lista = ["orange", "mango", "kiwi", "Pineapple", "banana"]lista.sort()lista
['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
[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 - 50return abs(n - 50)lista = [100, 50, 65, 82, 23]lista.sort(key = myfunc)lista
[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
['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
[6, 5, 9, 4, 3, 8, 5]
2.3.1.4. Copying lists
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 = lista1lista1[0] = Truelista2
[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] = Truelista2
[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] = Truelista2
[5, 8, 3, 4, 9, 5, 6]
2.3.1.5. Concatenating lists
Lists can be concatenated using the +
operator.
lista1 = [5, 8, 3, 4, 9, 5, 6]lista2 = ['a', 'b', 'c']lista = lista1 + lista2lista
[5, 8, 3, 4, 9, 5, 6, 'a', 'b', 'c']
Or by using the extend method
lista1 = [5, 8, 3, 4, 9, 5, 6]lista2 = ['a', 'b', 'c']lista1.extend(lista2)lista1
[5, 8, 3, 4, 9, 5, 6, 'a', 'b', 'c']
Another way to concatenate is to repeat the tuple X times using the *
operator.
lista1 = ['a', 'b', 'c']lista2 = lista1 * 3lista2
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']
2.3.2. Tuples
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
('item0', 1, True, 3.3, 'item4', True)
Its length can be obtained using the len()
function.
len (tupla)
6
To create tuples with a single element it is necessary to add a comma
tupla = ('item0',)tupla, type(tupla)
(('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])
item0True(True, 3.3)(True, 3.3)
We can check if there is an item in the tuple
'item4' in tupla
True
2.3.2.1. Modifying tuples
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
('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 tuplaif 'tupla' not in locals():print("tupla eliminada")
tupla eliminada
2.3.2.2.2. Unpacking tuples
When we create tuples, we are actually packaging data.
tupla = ('item0', 1, True, 3.3, 'item4', True)tupla
('item0', 1, True, 3.3, 'item4', True)
but we can unpack them
item0, item1, item2, item3, item4, item5 = tuplaitem0, item1, item2, item3, item4, item5
('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 = tuplaitem0, item1, item2, item3
('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 = tuplaitem0, item1, item2, item5
('item0', 1, [True, 3.3, 'item4'], True)
2.3.2.3. Concatenate tuples
You can concatenate tuples using the +
operator.
tupla1 = ("a", "b" , "c")tupla2 = (1, 2, 3)tupla3 = tupla1 + tupla2tupla3
('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 * 3tupla2
('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')
2.3.2.2.4. Tuple Methods
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)
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)
0
2.3.3.3. Range
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='')
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='')
2 3 4
for i in range(-2, 5):print(f'{i} ', end='')
-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='')
0 2 4 6 8
2.4. Dictionaries
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
{'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"]
2000
Its length can be obtained using the len()
function.
len(diccionario)
4
As you can see the length is 4 and not 5, since year
is counted only once.
2.4.1. Accessing Items
To access an item we can do it through its key
.
diccionario["model"]
'Mustang'
It can also be accessed through the get()
method.
diccionario.get("model")
'Mustang'
To know all the keys
s of the dictionaries, you can use the keys()
method
diccionario.keys()
dict_keys(['brand', 'model', 'year', 'colors'])
A variable can be used to point to the keys
s 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 keysx = diccionario.keys()print(x)# Se añade una nueva keydiccionario["color"] = "white"# Se consulta la variable que apunta a las keyprint(x)
dict_keys(['brand', 'model', 'year'])dict_keys(['brand', 'model', 'year', 'color'])
To obtain the dictionary values you can use the method 'values()'.
diccionario.values()
dict_values(['Ford', 'Mustang', 1964, 'white'])
You can use a variable to point to the values
s 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 valuesx = diccionario.values()print(x)# Se modifica un valuediccionario["year"] = 2020# Se consulta la variable que apunta a los valuesprint(x)
dict_values(['Ford', 'Mustang', 1964])dict_values(['Ford', 'Mustang', 2020])
If what you want are the item
s integers, that is key
s and value
s you have to use the items()
method.
diccionario.items()
dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 2020)])
A variable can be used to point to the item
s 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 itemsx = diccionario.items()print(x)# Se modifica un valuediccionario["year"] = 2020# Se consulta la variable que apunta a los itemsprint(x)
dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 1964)])dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 2020)])
You can check if a key
exists in the dictionary.
"model" in diccionario
True
2.4.2. Modifying the items
An item
can be modified by accessing it directly
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se modifica un itemdiccionario["year"] = 2020diccionario
{'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 itemdiccionario.update({"year": 2020})diccionario
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}
2.4.3. Adding items
You can add an item
by adding it without further ado.
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se modifica un itemdiccionario["colour"] = "blue"diccionario
{'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 itemdiccionario.update({"colour": "blue"})diccionario
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964, 'colour': 'blue'}
2.4.4. Delete items
An item
with a specific key
can be removed using the pop()
method.
diccionario = {"brand": "Ford","model": "Mustang","year": 1964}# Se elimina un itemdiccionario.pop("model")diccionario
{'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 itemdel diccionario["model"]diccionario
{'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 itemdel diccionarioif 'diccionario' not in locals():print("diccionario eliminado")
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 introducidodiccionario.popitem()diccionario
{'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
{}
2.4.5. Copy dictionaries
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 = diccionario1diccionario1["year"] = 2000diccionario2["year"]
2000
So you have to use the copy()
method.
diccionario1 = {"brand": "Ford","model": "Mustang","year": 1964}diccionario2 = diccionario1.copy()diccionario1["year"] = 2000diccionario2["year"]
1964
Or you have to use the dictionary constructor dict()
.
diccionario1 = {"brand": "Ford","model": "Mustang","year": 1964}diccionario2 = dict(diccionario1)diccionario1["year"] = 2000diccionario2["year"]
1964
2.4.6. Nested dictionaries
Dictionaries can have items
s 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
{'child1': {'name': 'Emil', 'year': 2004},'child2': {'name': 'Tobias', 'year': 2007},'child3': {'name': 'Linus', 'year': 2011}}
child1 = {"name" : "Emil","year" : 2004}child2 = {"name" : "Tobias","year" : 2007}child3 = {"name" : "Linus","year" : 2011}diccionario_nested = {"child1" : child1,"child2" : child2,"child3" : child3}diccionario_nested
{'child1': {'name': 'Emil', 'year': 2004},'child2': {'name': 'Tobias', 'year': 2007},'child3': {'name': 'Linus', 'year': 2011}}
2.4.7. Dictionary methods
These are the methods that may be used in dictionaries
2.4.8. Dictionary comprehension
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
{4: 16, 6: 36}
2.5. Sets
2.5.1. Set
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_
{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_
{1, 5, 5.3, 6.6, 'item0', 'item4'}
The length of the set
can be obtained using the len()
function.
len(set_)
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_
True
2.5.1.1. Add items
An item can be added to the set using the add()
method.
set_.add(8.8)set_
{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_
{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_
{1, 10, 11.2, 5, 5.3, 6.6, 7, 8.8, 'item0', 'item4', 'item5', 'item6', 'item9'}
2.5.1.2. Delete items
A given item can be removed using the remove()
method.
set_.remove('item9')set_
{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_
{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 set
s 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}")
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_
set()
Finally, with del
you can delete the set
del set_if 'set_' not in locals():print("set eliminado")
set eliminado
2.5.1.3. Linking Items
One way to join sets is through the union()
method.
set1 = {"a", "b" , "c"}set2 = {1, 2, 3}set3 = set1.union(set2)set3
{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
{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
{'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
{'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
{'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
{'banana', 'cherry', 'google', 'microsoft'}
2.5.1.4. Set methods
These are the methods that can be used in the sets
2.5.2. Frozenset
The frozenset
s are like the set
s but with the exception that they are immutable, just as the tuple
s are like the list
s but immutable. So we will not be able to add or delete items
2.6. Booleans
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))
TrueTrueFalse
2.6.1. Other data types True or False
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(""))
TrueFalse
print(bool(3))print(bool(0))
TrueFalse
lista = [1, 2, 3]print(bool(lista))lista = []print(bool(lista))
TrueFalse
tupla = (1, 2, 3)print(bool(tupla))tupla = ()print(bool(tupla))
TrueFalse
diccionario = {"brand": "Ford","model": "Mustang","year": 1964,"colors": ["red", "white", "blue"]}print(bool(diccionario))diccionario.clear()print(bool(diccionario))
TrueFalse
set_ = {'item0', 1, 5.3, "item4", 5, 6.6}print(bool(set_))set_.clear()print(bool(set_))
TrueFalse
2.7. Binaries
2.7.1. Bytes
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
b'MaximoFN'
They can also be created using its bytes()
contructor.
byte = bytes(10)byte
b' '
byte = bytes(range(10))byte
b' '
Bytes can be concatenated using the +
operator.
byte1 = b'DeepMax'byte2 = b'FN'byte3 = byte1 + byte2byte3
b'DeepMaxFN'
Or by repeating with the operator *
.
byte1 = b'MaximoFN 'byte2 = byte1 * 3byte2
b'MaximoFN MaximoFN MaximoFN '
We can check if a character is inside the string
b'D' in byte1
False
These are the methods that can be used in the bytes
.
2.7.2. Bytearray
The bytearray
s are the same as bytes
only they are mutable.
byte_array = bytearray(b'MaximoFN')byte_array
bytearray(b'MaximoFN')
2.7.3. Memoryview
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]= 74print(f'Después de acceder a la memoria: {byte_array}')
Antes de acceder a la memoria: bytearray(b'XYZ')Después de acceder a la memoria: bytearray(b'XYJ')
3. Operators
3.1. Arithmetic operators
Sum operator +
3 + 5
8
Oeprador subtracts -
3 - 5
-2
Multiplication operator *
3 * 5
15
Operator division /
3 / 5
0.6
Modulo operator %
. Returns the remainder of a division
25 % 2
1
Exponent operator **
5 ** 2
25
Integer division operator //
25 // 2
12
3.2. Comparison operators
Operator equals ==
1 == 1
True
Operator is different !=
1 != 2
True
Operator is greater than >
3 > 2
True
Operator is less than <
2 < 3
True
Operator is greater than or equal to >=
.
3 >= 3
True
Operator is less than or equal to <=
.
3 <= 3
True
3.3. Logical operators
Operator and
True and True
True
Operator or
True or False
True
Operator not
not False
True
3.4. Identity operators
Operator is
5.3 is 5.3
True
is not` operator
5.3 is not 5
True
3.5. Membership operators
Operator in
x = ["apple", "banana"]"banana" in x
True
Not in` operator
x = ["apple", "banana"]"orange" not in x
True
3.6. Bitwise operators
AND operator &
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101c = a & b; # 12 = 0000 1100c
12
OR operator |
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101c = a | b; # 61 = 0011 1101c
61
XOR operator ^
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101c = a ^ b; # 49 = 0011 0001c
49
NOT operator ~
a = 60 # 60 = 0011 1100c = ~a; # -61 = 1100 0011c
-61
Operator shift left <<
operator
a = 60 # 60 = 0011 1100c = a << 2; # 240 = 1111 0000c
240
Right shift operator >>>
.
a = 60 # 60 = 0011 1100c = a >> 2; # 15 = 0000 1111c
15
3.7. Assignment operators
Operator =
a = 5a
5
Operator +=
. x += y
is equivalent to x = x + y
.
a += 5a
10
Operator -=
. x -= y
is equivalent to `x = x - y
a -= 5a
5
Operator *=
. x *= y
is equivalent to `x = x * y
a *= 3a
15
Operator /=
. x /= y
is equivalent to `x = x / y
a /= 3a
5.0
Operator %=
. x %= y
is equivalent to `x = x % y
a = 25a %= 2a
1
Operator //=
. x //= y
is equivalent to `x = x // y
a = 25a //= 2a
12
Operator **=
. x **= y
is equivalent to `x = x ** ** y
a = 5a **= 2a
25
Operator &=
. x &= y
is equivalent to `x = x & y
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101a &= b; # 12 = 0000 1100a
12
Operator |=
. x |= y
is equivalent to `x = x | y
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101a |= b; # 61 = 0011 1101a
61
Operator ^=
. x ^= y
is equivalent to `x = x ^ y
a = 60 # 60 = 0011 1100b = 13 # 13 = 0000 1101a ^= b; # 49 = 0011 0001a
49
Operator >>=
. x >>= y
is equivalent to `x = x >> y
a = 60 # 60 = 0011 1100a <<= 2; # 240 = 1111 0000a
240
Operator <<=
. x <<= y
is equivalent to `x = x <<< y
a = 60 # 60 = 0011 1100a >>= 2; # 15 = 0000 1111a
15
Flow control
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.
If
Using if
we can create conditions
if len('MaximoFN') == 8:print('MaximoFN tiene 8 caracteres')
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')
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')
MaximoFN tiene 8 caracteres
If we want to write everything on a single line
if len('MaximoFN') == 8: print('MaximoFN tiene 8 caracteres')
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')
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:passelse:print('MaximoFN tiene 8 caracteres')
MaximoFN tiene 8 caracteres
4.2. While
The while
loop is executed as long as the condition is True
.
i = 0string = 'MaximoFN'while len(string) > i:print(string[i], end='')i += 1
MaximoFN
If we want the loop to stop for some condition we use break
.
i = 0string = 'MaximoFN'while len(string) > i:if string[i] == 'F':breakprint(string[i], end='')i += 1
Maximo
If we want one of the iterations not to be executed for some reason we use continue
.
i = 0string = 'Maximo FN'while len(string) > i:if string[i] == ' ':i += 1continueprint(string[i], end='')i += 1
MaximoFN
Using else
you can execute a code block if the while
condition is not True
.
i = 0string = 'MaximoFN'while len(string) > i:print(string[i], end='')i += 1else:print("\nSe ha terminado el while")
MaximoFNSe ha terminado el while
4.3. For
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='')
MaximoFN
lista = ['M', 'a', 'x', 'i', 'm', 'o', 'F', 'N']for x in lista:print(x, end='')
MaximoFN
tupla = ('M', 'a', 'x', 'i', 'm', 'o', 'F', 'N')for x in tupla:print(x, end='')
MaximoFN
string = 'MaximoFN'for i in range(len(string)):print(string[i], end='')
MaximoFN
diccionario = {"letra1": "M","letra2": "a","letra3": "x","letra4": "i","letra5": "m","letra6": "o","letra7": "F","letra8": "N",}for x in diccionario.values():print(x, end='')
MaximoFN
You can also iterate through the set
s, 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='')
NximoaMF
If we want the loop to stop for some condition we use break
.
string = 'MaximoFN'for x in string:if x == 'F':breakprint(x, end='')
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 == ' ':continueprint(x, end='')
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")
MaximoFNSe 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:passprint('Interior del for no codificado')
Interior del for no codificado
5. Functions
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')
To call the function it is only necessary to type its name
def funcion():print('MaximoFN')funcion()
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")
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")
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")
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")
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")
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"])
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 stringprint(funcion(["Blog", "de", "MaximoFN"]))
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, string2dato0, dato1, dato2 = funcion(["Blog", "de", "MaximoFN"])print(dato0 + ' ' + dato1 + ' ' + dato2)
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)
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():passfuncion()
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():passfuncion()def factorial(n):if n == 0 or n == 1:return 1else:return n * factorial(n-1)factorial(5)
120
5.1. Built in functions
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)
5
The following is a list of these functions
import builtinsdir(builtins)
['ArithmeticError','AssertionError','AttributeError','BaseException','BlockingIOError','BrokenPipeError','BufferError','BytesWarning','ChildProcessError','ConnectionAbortedError','ConnectionError','ConnectionRefusedError','ConnectionResetError','DeprecationWarning','EOFError','Ellipsis','EnvironmentError','Exception','False','FileExistsError','FileNotFoundError','FloatingPointError','FutureWarning','GeneratorExit','IOError','ImportError','ImportWarning','IndentationError','IndexError','InterruptedError','IsADirectoryError','KeyError','KeyboardInterrupt','LookupError','MemoryError','ModuleNotFoundError','NameError','None','NotADirectoryError','NotImplemented','NotImplementedError','OSError','OverflowError','PendingDeprecationWarning','PermissionError','ProcessLookupError','RecursionError','ReferenceError','ResourceWarning','RuntimeError','RuntimeWarning','StopAsyncIteration','StopIteration','SyntaxError','SyntaxWarning','SystemError','SystemExit','TabError','TimeoutError','True','TypeError','UnboundLocalError','UnicodeDecodeError','UnicodeEncodeError','UnicodeError','UnicodeTranslateError','UnicodeWarning','UserWarning','ValueError','Warning','ZeroDivisionError','__IPYTHON__','__build_class__','__debug__','__doc__','__import__','__loader__','__name__','__package__','__spec__','abs','all','any','ascii','bin','bool','breakpoint','bytearray','bytes','callable','chr','classmethod','compile','complex','copyright','credits','delattr','dict','dir','display','divmod','enumerate','eval','exec','filter','float','format','frozenset','get_ipython','getattr','globals','hasattr','hash','help','hex','id','input','int','isinstance','issubclass','iter','len','license','list','locals','map','max','memoryview','min','next','object','oct','open','ord','pow','print','property','range','repr','reversed','round','set','setattr','slice','sorted','staticmethod','str','sum','super','tuple','type','vars','zip']
5.2. Documentation of a function
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"Nonehelp(funcion)
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__
'Esta es la explicación de la función'
5.3. Decorators
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 envoltoriodef funcion():print("MaximoFN")funcion_envoltorio = decorador(funcion)print('Función sin decoradores: ')funcion()print('\nFunción con decoradores: ')funcion_envoltorio()
Función sin decoradores:MaximoFNFunción con decoradores:==================MaximoFN==================
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@decorador2def funcion2():print("MaximoFN")print('Función con decoradores: ')funcion2()
Función con decoradores:==================MaximoFN==================
5.4. *args
and **kwargs
.
*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
.
*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")
Hola, AliciaHola, RobertoHola, Carlos
5.4.2. **kwargs
.
**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)
Hola Juan, tu edad es 22 añosHola Maria, tu edad es 32 añosHola Pedro, tu edad es 25 años
Additional functions
6.1. Functions *call
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 + 10print(x(5))
15
x = lambda a, b, c : a + b + cprint(x(5, 6, 2))
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 * nmydoubler = myfunc(2)mytripler = myfunc(3)print(f"mydoubler: {mydoubler(11)}")print(f"mytripler: {mytripler(11)}")
mydoubler: 22mytripler: 33
6.2. Map function
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 + 1lista_modificada = list(map(funcion_mas_1, lista))lista_modificada
[2, 3, 4]
This is equivalent to using list comprehension
.
lista_modificada = [funcion_mas_1(x) for x in lista]lista_modificada
[2, 3, 4]
6.3. Filter function
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 == 0lista_filtrada = list(filter(esPar, lista))lista_filtrada
[2, 4, 6]
This is equivalent to using list comprehension
.
lista_filtrada = [x for x in lista if esPar(x)]lista_filtrada
[2, 4, 6]
6.4. Function reduce
.
The reduce
function allows cumulative tasks to be performed on iterable structures.
from functools import reducelista = [1, 22, 33]def acumular(valor, acumulador):print(f'valor = {valor}, acumulador = {acumulador}, acumulacion = {valor + acumulador}')return valor + acumuladoracumulacion = reduce(acumular, lista)print(f'\nacumulacion = {acumulacion}')
valor = 1, acumulador = 22, acumulacion = 23valor = 23, acumulador = 33, acumulacion = 56acumulacion = 56
6.5. Zip function
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
[('Manolo', 181), ('Andres', 178), ('Fernando', 180)]
6.5. Generators
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 igenerador = iterador_custom(20)for i in generador:print(i)
0369121518
We have just made an iterator for numbers multiples of 3
6.6. High order functions
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 + 1def hof(f, x):return 2*f(x)print(hof(increment, 3))
8
7. Classes and objects
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'
Once the class has been created, you can create an object of this class
class Clase:variable = 'MaximoFN'objeto = Clase()Clase.variable
'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 = nombreself.edad = edadobjeto_persona = Persona("Miguel", 36)print(objeto_persona.nombre)print(objeto_persona.edad)
Miguel36
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 = nombreself.edad = edaddef saludar(self):print(f'Hola mi nombre es {self.nombre} y tengo {self.edad} años')objeto_persona = Persona("Miguel", 36)objeto_persona.saludar()
Hola mi nombre es Miguel y tengo 36 años
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 = nombreyo_mismo.edad = edaddef saludar(yo_mismo):print(f'Hola mi nombre es {yo_mismo.nombre} y tengo {yo_mismo.edad} años')objeto_persona = Persona("Miguel", 36)objeto_persona.saludar()
Hola mi nombre es Miguel y tengo 36 años
Object variables can be modified
objeto_persona.nombre = 'Marta'objeto_persona.saludar()
Hola mi nombre es Marta y tengo 36 años
Even eliminate them
del objeto_persona.nombre
You can also delete the entire object
del objeto_persona.nombredel objeto_persona
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.nombredel objeto_personaclass Persona:passobjeto_persona = Persona()
7.1. Inheritance
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.nombredel objeto_personaclass Persona:passobjeto_persona = Persona()class Persona:def __init__(self, nombre, apellido):self.nombre = nombreself.apellido = apellidodef imprimir_nombre(self):print(f'Me llamo {self.nombre} {self.apellido}')objeto_padre = Persona("Laura", "Perez")objeto_padre.imprimir_nombre()
Me llamo Laura Perez
To create the child class you must indicate in parentheses, when declaring the class, which class it inherits from
class Estudiante(Persona):pass
And when creating the object of the child class, the parameters that the parent class needs are passed to it
class Estudiante(Persona):passobjeto_hijo = Estudiante("Mariano", "Sanz")objeto_hijo.imprimir_nombre()
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()
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()
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 = cursodef imprimir_nombre(self):Persona.imprimir_nombre(self)print(f'Estoy en el curso número {self.curso}')objeto_hijo = Estudiante("Mariano", "Sanz", 4)objeto_hijo.imprimir_nombre()
Me llamo Mariano SanzEstoy en el curso número 4
Finally, new methods can be added
class Estudiante(Persona):def __init__(self, nombre, apellido, curso):Persona.__init__(self, nombre, apellido)self.curso = cursodef imprimir_nombre(self):Persona.imprimir_nombre(self)print(f'Estoy en el curso número {self.curso}')def imprimir_estudiante(self):print(f"Soy un estudiante del curso número {self.curso}")objeto_hijo = Estudiante("Mariano", "Sanz", 4)objeto_hijo.imprimir_nombre()objeto_hijo.imprimir_estudiante()
Me llamo Mariano SanzEstoy en el curso número 4Soy un estudiante del curso número 4
7.2. Operator overload
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 = xself.y = ydef __add__(self, other):return Vector(self.x + other.x, self.y + other.y)def __mul__(self, other):return Vector(self.x * other.x, self.y * other.y)def __str__(self):return f"Vector ({self.x}, {self.y})"v1 = Vector(1, 2)v2 = Vector(3, 4)print(v1 + v2) # Vector (4, 6)print(v1 * v2) # Vector (3, 8)
Vector (4, 6)Vector (3, 8)
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 thedivmod()
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 theabs()
function.__invert__(self)
: overloads the inversion operator (~
).__complex__(self)
: overloads thecomplex()
function.__int__(self)
: overloads theint()
function.__float__(self)
: overloads thefloat()
function.
7.3. Custom Iterators
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)) # 10print(iterator[0]) # 0print(iterator[1]) # 1
1001
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
0 1 2 3 4 5 6 7 8 9
7.4. Calling objects as functions
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 = basedef __call__(self, potencia):return self.base ** potenciapotencia_cuadrado = potencia(2)print(potencia_cuadrado(3)) # 8
8
7.5. Private attributes and functions
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.__privadodef setPrivado(self, valor):self.__privado = valordef __funcion_privada(self):return "Soy una función privada"def funcion_publica(self):return self.__funcion_privada()privados = Privados()print("Acceso al atributo publico: ", end="")try:print(f"{privados.publico}")except:print("\tNo se puede acceder al atributo privado")print("Acceso al atributo privado: ", end="")try:print(f"{privados.__privado}")except:print("\tNo se puede acceder al atributo privado")print("Acceso al atributo privado mediante el accesor: ", end="")try:print(f"{privados.getPrivado()}")except:print("\tNo se puede acceder al atributo privado mediante el accesor")print("Llamada a la función privada: ", end="")try:print(f"{privados.__funcion_privada()}")except:print("\tNo se puede llamar a la función privada")print("Llamada a la función pública: ", end="")try:print(f"{privados.funcion_publica()}")except:print("\tNo se puede llamar a la función pública")
Acceso al atributo publico: Soy públicoAcceso al atributo privado: No se puede acceder al atributo privadoAcceso al atributo privado mediante el accesor: Soy privadoLlamada a la función privada: No se puede llamar a la función privadaLlamada a la función pública: Soy una función privada
8. Iterators
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))
manzanaplátanocereza
string = "plátano"iterable = iter(string)print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')print(next(iterable), end=' ')
p l á t a n o
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)
manzanaplátanocereza
string = "plátano"for x in string:print(x, end=' ')
p l á t a n o
8.1. Create an iterator object
To create an object/class as an iterator, the __iter__()
and __next__()
methods must be implemented.
class Numeros:def __iter__(self):self.a = 1return selfdef __next__(self):x = self.aself.a += 1return xobjeto_iterador = Numeros()iterador = iter(objeto_iterador)print(next(iterador), end=' ')print(next(iterador), end=' ')print(next(iterador), end=' ')print(next(iterador), end=' ')print(next(iterador), end=' ')
1 2 3 4 5
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 = 1return selfdef __next__(self):if self.a <= 20:x = self.aself.a += 1return xelse:raise StopIterationobjeto_iterador = Numeros()iterador = iter(objeto_iterador)for x in iterador:print(x, end=' ')
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
8.2. Iterate obtaining the index and value
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}")
En la posición 0, está el caracter MEn la posición 1, está el caracter aEn la posición 2, está el caracter xEn la posición 3, está el caracter iEn la posición 4, está el caracter mEn la posición 5, está el caracter oEn la posición 6, está el caracter FEn la posición 7, está el caracter N
8.3. Iterate through two iterable objects at the same time.
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}")
En el primer string hay M, en el segundo string hay PEn el primer string hay a, en el segundo string hay yEn el primer string hay x, en el segundo string hay tEn el primer string hay i, en el segundo string hay hEn el primer string hay m, en el segundo string hay oEn el primer string hay o, en el segundo string hay nEn el primer string hay F, en el segundo string hay PEn el primer string hay N, en el segundo string hay oEn el primer string hay _, en el segundo string hay sEn el primer string hay _, en el segundo string hay t
9. Scope of variables
A variable is only available within the region in which it is created. This is called scope.
9.1. Local Scope
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 = 300print(x)funcion()
300
The variable x
is not available outside the function, but it is available for any function inside the function.
def funcion():x = 300def funcion_interna():print(x)funcion_interna()funcion()
300
9.2. Global Scope
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 = 300def funcion():print(f'Ámbito local: {x}')funcion()print(f'Ámbito global: {x}')
Á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 = 300def funcion():x = 200print(f'Variable local: {x}')funcion()print(f'Variable global: {x}')
Variable local: 200Variable 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 xx = 300funcion()print(f'Variable global: {x}')
Variable global: 300
In addition, the use of the global
keyword makes a change to a global variable within a function.
x = 300def funcion():global xx = 200funcion()print(f'Variable global: {x}')
Variable global: 200
10. Modules
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
/home/wallabot/Documentos/web/portafolio/posts
We will create a folder to create our modules with the command mkdir
(make directory)
!mkdir introduccion_python
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
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.pydef funcion_del_modulo(nombre):print("Hola, " + nombre)
Writing introduccion_python/modulo1.py
We go back to see what files are in our folder
!ls introduccion_python
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.modulo1introduccion_python.modulo1.funcion_del_modulo('MaximoFN')
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 mod1mod1.funcion_del_modulo('MaximoFN')
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.pydef funcion1_del_modulo(nombre):print("Hola, " + nombre + ", funcion 1")def funcion2_del_modulo(nombre):print("Hola, " + nombre + ", funcion 2")def funcion3_del_modulo(nombre):print("Hola, " + nombre + ", funcion 3")
Writing introduccion_python/modulo2.py
from introduccion_python.modulo2 import funcion2_del_modulofuncion2_del_modulo('MaximoFN')
Hola, MaximoFN, funcion 2
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 platformx = platform.system()x
'Linux'
10.1. Entry points: files as modules and not as scripts
We are now going to create a file called modulo3.py
.
%%writefile introduccion_python/modulo3.pyprint("Hola desde modulo3")def funcion_del_modulo():return "Hola desde la función del modulo3"
Overwriting introduccion_python/modulo3.py
If we now import module3.py
to use the module_function
function let us see what happens
import introduccion_python.modulo3 as mod3print(mod3.funcion_del_modulo())
Hola desde modulo3Hola 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
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.pyprint("Hola desde modulo3")def funcion_del_modulo():return "Hola desde la función del modulo3"if __name__ == "__main__":funcion_del_modulo()
Overwriting introduccion_python/modulo3.py
If I now call main.py
from another module, the print
will no longer be executed.
import introduccion_python.modulo3 as mod3print(mod3.funcion_del_modulo())
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
Hola desde modulo3
11. Packages
In python we can create our own packages by creating a folder with the package name
!mkdir mi_paquete_de_python
We now create two files inside
!mkdir mi_paquete_de_python!touch mi_paquete_de_python/modulo1.py mi_paquete_de_python/modulo2.py
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.pydef funcion1():print("Hola desde la función 1 del módulo 1")def funcion2():print("Hola desde la función 2 del módulo 1")
Overwriting mi_paquete_de_python/modulo1.py
%%writefile mi_paquete_de_python/modulo2.pydef funcion1():print("Hola desde la función 1 del módulo 2")def funcion2():print("Hola desde la función 2 del módulo 2")
Overwriting mi_paquete_de_python/modulo2.py
Now we can call the functions of our package
from mi_paquete_de_python import modulo1 as mod1from mi_paquete_de_python import modulo2 as mod2mod1.funcion1()mod1.funcion2()mod2.funcion1()mod2.funcion2()
Hola desde la función 1 del módulo 1Hola desde la función 2 del módulo 1Hola desde la función 1 del módulo 2Hola desde la función 2 del módulo 2
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
!touch mi_paquete_de_python/__init__.py%%writefile mi_paquete_de_python/__init__.pyimport modulo1import modulo2
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_paquetemi_paquete.modulo1.funcion1()mi_paquete.modulo1.funcion2()mi_paquete.modulo2.funcion1()mi_paquete.modulo2.funcion2()
Hola desde la función 1 del módulo 1Hola desde la función 2 del módulo 1Hola desde la función 1 del módulo 2Hola desde la función 2 del módulo 2
In this way we only have to do an import
.
12. Try... Except
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")
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")
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')
MaximoFNTodo 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")
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
Ha ocurrido una excepción
12.1. Creating an exception
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/denominadorprint(division(10, 0))
---------------------------------------------------------------------------Exception Traceback (most recent call last)<ipython-input-16-33fb6066fa78> in <module>5 return numerador/denominador6----> 7 print(division(10, 0))<ipython-input-16-33fb6066fa78> in division(numerador, denominador)1 def division(numerador, denominador):2 if denominador == 0:----> 3 raise Exception("El denominador no puede ser 0")45 return numerador/denominadorException: El denominador no puede ser 0
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/denominadorprint(division(10, 0))
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-17-26bfa63ae44c> in <module>5 return numerador/denominador6----> 7 print(division(10, 0))<ipython-input-17-26bfa63ae44c> in division(numerador, denominador)1 def division(numerador, denominador):2 if denominador == 0:----> 3 raise TypeError("El denominador no puede ser 0")45 return numerador/denominadorTypeError: El denominador no puede ser 0
13. Keywords or reserved words
During this post in several occasions Python reserved words or keyword
s have appeared, these are a series of words reserved by Python.
The following is a list of the keyword
s
import keywordkeyword.kwlist
['False','None','True','and','as','assert','async','await','break','class','continue','def','del','elif','else','except','finally','for','from','global','if','import','in','is','lambda','nonlocal','not','or','pass','raise','return','try','while','with','yield']
14. The Zen of Python
By importing the this
module we can read the zen
of Python, that is, its philosophy or principles.
import this
The Zen of Python, by Tim PetersBeautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!