Contenido#



Los siguientes contenidos serán presentados en una sesión de videoconferencia. Puedes encontrar en este enlace las slides usadas como soporte.

Introducción#

Si conoces otros lenguajes es posible que esta introducción te resulte innecesaria, pero se ha escrito pensando en un lector completamente lego en programación.

Un lenguaje de programación es un conjunto de reglas sintácticas que permiten codificar la secuencia de ordenes lógicas (algoritmo) que traducido a lenguage máquina y ejecutado por el procesador de tu computadora resolverá una tarea. Para esto Python hace uso de unos mecanismos elementales comunes a cualquier lenguaje, interpretado o compilado, como es el uso del almacenamiento de información en variables, el algebra, la lógica, los iteradores, los bucles y las funciones, entre otros.

Antes de empezar#

Si estás ejecutando este Jupyter Notebook en tu computadora haciendo uso de tu Jupyter Lab, te recomendamos que lo reinicialices completamente borrando la salida de las celdas. Para ello acude al menú Kernel (top menú de la ventana) y elige la opción Restart Kernel and Clear All Outputs of All Cells…. Puede que hayamos dejado en la copia maestra de GitHub el resultado de la ejecución de las celdas, pero es sólo para que cualquiera pueda leer el notebook allí sin necesidad de ejecutarla. Pero tu no lo vas a leer. Vas a jugar con él. Así que resetéalo.

Recuerda también que para ejecutar una celda debes presionar la combinación de teclas “mayús”+”entrar” cuanto esta está seleccionada.

¿Qué es una variable?#

La variable es el objeto con el que almacenamos información en memoria. La variable se compone de tres partes:

  • Nombre

  • Valor

  • Dirección de un sector de memoria donde hemos almacenado el valor

Una vez que hemos definido una variable, podemos acceder a la lectura del valor sin más que invocar su nombre:

var1 = 3
var2 = 4.6
var3 = 'python'
var4 = True
var3
'python'
var1 + var2
7.6

Vemos que de estas variables conocemos su nombre y su valor, porque los hemos definido nosotros… pero, ¿dónde está la dirección o el identificador que nos servirá para que Python se dirija correctamente al sector de memoria adecuado?

id(var1)
140136493580592
id(var2)
140136445925552

Lenguajes como Fortran o C obligan a comenzar un programa con una sección de declaración de variables, con nombre y tipo (es número entero, es letra, es número real, etc.). Así, el uso “al vuelo” de una nueva variable a mitad del programa, si no fue declarada al inicio, provoca un error. Afortunadamente esto ya no pasa en lenguajes interpretados como Python. En Python cualquier variable que el interpretador encuentra por primera vez, y en cualquier momento, la registra como conocida y le da el tipo que tiene el valor que se le asigna.

Tipos de variables#

Hemos definido cuatro variables y como pudiste ver tienen valores de tipos distinto: un entero, un número de coma flotante, una cadena de caracteres y un valor de lógica booleana.

type(var1)
int
type(var2)
float
type(var3)
str
type(var4)
bool

Vamos con una breve descripción de cada uno de los tipos de variables que podemos manejar en Python.

Enteros#

Estas variables como su nombre indica almacenan números enteros, y en lenguaje de programación y en Python se les conoce como Integers o variables de tipo int:

var1 = 3
var1
3
type(var1)
int

Podemos hacer uso de los símbolos matemáticos para operar con ellos algebráicamente y lógicamente:

var2 = 5
var3 = 7
var1+var2
8
var3/var1
2.3333333333333335
var2 < var3
True
var1 != var2 # El símbolo '!=' significa 'distinto que'
True
var1 == var2 # El símbolo '==' significa 'igual que'
False

Números de coma flotante#

Para almacenar números reales hacemos uso de las variables de coma flotante o como se conocen en lenguaje de programación: float (floating point numbers):

var1 = 3.24386
var1
3.24386
type(var1)
float

Al igual que con los enteros, podemos hacer operaciones lógicas y algebráicas con ellos:

var2 = -15.21347
var3 = 0.125
var1*var2
-49.3503667942
var1+var3
3.36886
var2 <= var3
True

Cadenas de caracteres#

Para almacenar «texto», es decir, cadenas de caracteres, Python y el resto de lenguajes de programación hacen uso de las variables de tipo “string”.

var1 = 'hola'
var1
'hola'
type(var1)
str

Al igual que con el resto de variables, podemos hacer uso de los símbolos matemáticos… pero en este caso para realizar operaciones como:

var2 = 'manzana'
var3 = 'casa'
var1+var2
'holamanzana'
var1*3
'holaholahola'
var3 == 'casa'
True
var2 != var1
True

En el caso de las variables “string” tenemos otras funciones y atributos para trabajar con ellas. Por ejemplo:

  • podemos conocer la longitud de una cadena de caracteres

  • podemos acceder a específicamente a uno o varios de los caracteres

  • podemos comprobar si contiene o no una subcadena de caracteres

  • disponemos de una gran batería de métodos internos para por ejemplo reemplazar caracteres, transformar en mayúsculas, o comprobar si la cadena comienza o termina con una secuencia específíca.

len(var2)
7
var2[0:2]
'ma'
var2[6]
'a'
var2[-1]
'a'
'asa' in var3
True
dir(var2)
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mod__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmod__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'capitalize',
 'casefold',
 'center',
 'count',
 'encode',
 'endswith',
 'expandtabs',
 'find',
 'format',
 'format_map',
 'index',
 'isalnum',
 'isalpha',
 'isascii',
 'isdecimal',
 'isdigit',
 'isidentifier',
 'islower',
 'isnumeric',
 'isprintable',
 'isspace',
 'istitle',
 'isupper',
 'join',
 'ljust',
 'lower',
 'lstrip',
 'maketrans',
 'partition',
 'removeprefix',
 'removesuffix',
 'replace',
 'rfind',
 'rindex',
 'rjust',
 'rpartition',
 'rsplit',
 'rstrip',
 'split',
 'splitlines',
 'startswith',
 'strip',
 'swapcase',
 'title',
 'translate',
 'upper',
 'zfill']
help(var2.upper)
Help on built-in function upper:

upper() method of builtins.str instance
    Return a copy of the string converted to uppercase.
var2.upper()
'MANZANA'
var2.replace('zan','tec')
'manteca'
var2.endswith('ana')
True

Booleanos#

Las variables que menos espacio ocupan en el disco duro son las variables “booleanas” o como se le conoce en jerga de programador y en Python: “bool”. Estas variables sólo toman dos posibles valores: verdadero (True) o falso (False).

var1 = True
var1
True
type(var1)
bool

Veamos en este caso qué podemos hacer con ellas y los operadores lógicos:

var2 = False
var3 = True
var1 == var2
False
var1 or var2
True
var1 and var3
True
not var1 and not var3
False

En realidad Python entiende el valor “True” matemáticamente como 1, y “False” como 0. Mira esto…

var1+var2
1
var1*var3
1
var2 == 0
True

La función print#

La primera función de python, aunque ya hemos usado alguna (que llamamos “método “por estar vinculada a un objeto), que veremos es “print”. Usamos print para «imprimir» o sacar por pantalla el valor de una variable o un valor dado:

print('Hola!')
Hola!
var1=3
var2=6
var3='y adiós...'
print(var1, var2)
3 6
print(var1+var2)
9
print('Hola'+' '+var3)
Hola y adiós...

La función «print» requiere más explicaciones porque da mucho más juego. Pero por el momento y como presentación es suficiente. Veremos más adelante junto con la función «write» muchas otras cosas de ella.

Listas y tuplas#

Además estas variables pueden ser almacenadas en listas o tuplas. Aunque para un purista la lista y la tupla son objetos filosóficamente distintos, ambas se manejan de manera similar. Una de las pocas diferencias es que, como veremos, una puede ser mutada, y la otra no.

Veamos una tupla…

var1=3
var2='hola'
var3=True
una_tupla = (var1, var2, var3, 5.2)
type(una_tupla)
tuple
una_tupla
(3, 'hola', True, 5.2)

Y ahora veamos una lista…

una_lista = [var1, var2, var3, var4]
type(una_lista)
list
una_lista
[3, 'hola', True, True]

Como ves, ahora mismo la única diferencia es que una se define entre paréntesis y la otra entre corchetes. Veamos ahora la diferencia más relevante:

una_lista[0]
3
una_lista[0] = 8
print(una_lista)
[8, 'hola', True, True]

A una lista le podemos reasignar valor a sus elementos. Sin embargo, a una tupla no. Prueba a hacer lo anterior en la tupla y verás.

Volviendo a las cosas que una lista y una tupla tienen en común podemos añadir que ambos son objetos que permiten operaciones algebráicas:

otra_lista = ['pato','peto','pito']
requetelista = una_lista + otra_lista
print(requetelista)
[8, 'hola', True, True, 'pato', 'peto', 'pito']
[0,1,2]+[2]
[0, 1, 2, 2]
('a','b','c')*4
('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')

Además, las tuplas y las listas son objetos. Si se pueden hacer listas o tuplas de objetos, también se pueden hacer listas de listas, tuplas de tuplas, listas de tuplas o tuplas de listas, o listas de tuplas de tuplas de listas, etc.

quimera = ['a','b',[1,2,3],'d',('pato','peto','pito')]
quimera[1]
'b'
quimera[2][2]
3
quimera[4]
('pato', 'peto', 'pito')

En Python el primer elemento es siempre el cero “0”. Y al último podemos acceder con el “-1”… y al antepenúmltimo con “-2”, y así sucesivamente.

quimera[4][0]
'pato'
quimera[4][-1]
'pito'
quimera[4][-2]
'peto'

A podemos jugar con el símbolo “:” para acceder a todos los elementos, o a los posteriores o precedentes a un índice dado:

otra_lista=['aa', 'bb', 'cc', 'dd', 'ee', 'ff']
otra_lista[:]
['aa', 'bb', 'cc', 'dd', 'ee', 'ff']
otra_lista[3:]
['dd', 'ee', 'ff']
otra_lista[:3]
['aa', 'bb', 'cc']
otra_lista[2:4]
['cc', 'dd']

Sets#

En Python existe la manera de almacenar elementos sin orden, conjuntos en los que sus componentes no están jerarquizados o indexados. A este conjunto se le llama set y se define entre llaves. Estos objetos tienen incluso sus propias funciones útiles.

conjunto_A = {2, 1, 6, 3}
conjunto_B = {10, 6, 2, 12}
type(conjunto_A)
set
conjunto_A.add(0)

Y podemos realizar operaciones de teoría de conjuntos:

conjunto_A | conjunto_B # el simbolo "|" crea la unión de conjuntos
{0, 1, 2, 3, 6, 10, 12}
conjunto_A & conjunto_B # el simbolo "&" crea la intersección de conjuntos
{2, 6}

Diccionarios#

Por último Python dispone de otra clase de objetos llamada diccionario (dict). El diccionario es la relación no ordenada entre claves y valores, y se define con ayuda de las llaves:

un_diccionario = {'hello':'hola', 'apple':'manzana', 'house':'casa'}
type(un_diccionario)
dict
un_diccionario
{'hello': 'hola', 'apple': 'manzana', 'house': 'casa'}
un_diccionario.keys()
dict_keys(['hello', 'apple', 'house'])
un_diccionario.values()
dict_values(['hola', 'manzana', 'casa'])
un_diccionario['house']
'casa'
'apple' in un_diccionario  # así podemos ver si un valor está en el diccionario como clave.
True

Es la tercera vez que ves “#”. Seguramente ya habrás deducido que “#” sirve para comentar código. Aquí va otro ejemplo de código con comentarios:

# Almaceno el resultado de una operación matemática
resultado=(2+3)/2
# Y lo saco por pantalla
print(resultado)
2.5

Estructuras condicionales#

Otros elementos comunes a todo lenguaje de programación son las estructuras condicionales y los bucles. Veamos unos ejemplos.

El condicional if#

# introduce en esta variable un nombre de persona:
persona = 'Alberto'
if persona.endswith('a'):
    print('Puede que', persona, 'sea de sexo femenino.')
elif persona.endswith('o'):
    print('Puede que', persona, 'sea de sexo masculino.')
else:
    print('No sé que sexo tiene', persona)
Puede que Alberto sea de sexo masculino.

Como acabas de ver, Python tienen en su sintaxis tres palabras para imponer condicionales:

  • if: “si…”

  • elif: “si es que no entonces si…”

  • else: “si no…”

Estos condicionales se pueden anidar dando lugar a complejas estructuras lógicas:

número_patas = 4
según_lo_que_come = 'herbívoro'

if según_lo_que_come == 'carnívoro':
    if número_patas == 4:
        print('es un león')
    elif número_patas == 2:
        print('es un Tyrannosaurus rex')
    else:
        print('no sé lo que es')
elif según_lo_que_come == 'herbívoro':
    if número_patas == 4:
        print('es una vaca')
    elif número_patas == 2:
        print('es un pato')
    else:
        print('no sé lo que es')
es una vaca

El condicional case#

El condicional case es un elemento nuevo de Python incluido en su versión 3.10. A partir de esta versión, situaciones como la siguiente:

edad = 120

if edad > 90:
    print("Nunca es tarde para aprender Python")
elif edad > 65:
    print("Ojalá encuentres ahora el tiempo para hacer lo que estabas postponiendo: aprender Python.")
elif edad > 14:
    print("Se te abrirán muchas puertas con Python o cualquier otro lenguaje de programación.")
else: 
    print("Puedes encontrar en internet muchos juegos para aprender a programar.")
Nunca es tarde para aprender Python

Pueden ahora resolverse con el condicional case cuando los valores con los que se definen las condiciones son constantes:

dia = 'Miércoles'

match dia:
    case 'Lunes':
        print('Que tengas buen inicio de semana.')
    case 'Martes':
        print('Ánimo, es martes!')
    case 'Miércoles':
        print('La botella está ya medio vacia...')
    case 'Jueves':
        print('Un último empujón y ya es viernes.')
    case 'Viernes':
        print('Es viernes de culpa... seguro que no hiciste todo lo que querías.')
    case _:
        print('Es fin de semana y tu cuerpo lo sabe.')
La botella está ya medio vacia...
hora = 14

match hora:
    case 8:
        print('Deberías estar durmiendo.')

Iteradores y bucles#

El iterador for#

Otro elemento de Python para el control de flujo son los bucles o iteraciones. En todo lenguaje de programación podemos encontrar una orden que nos permite repetir un blóque de código las veces que deseemos, cambiando incluso el contenido de una variable:

for palabra in ['casa','trompeta','zapato']:
    print(palabra, 'tiene', len(palabra), 'letras')
casa tiene 4 letras
trompeta tiene 8 letras
zapato tiene 6 letras
for número in range(11):
    print(str(número),'x 8 =', número*8)
0 x 8 = 0
1 x 8 = 8
2 x 8 = 16
3 x 8 = 24
4 x 8 = 32
5 x 8 = 40
6 x 8 = 48
7 x 8 = 56
8 x 8 = 64
9 x 8 = 72
10 x 8 = 80

En esta última celda hemos hecho uso de un iterador de Python muy útil: range(). Decimos que es un iterador porque funciona como un generador de números que solito, sin iterar, no tiene sentido:

help(range)
Help on class range in module builtins:

class range(object)
 |  range(stop) -> range object
 |  range(start, stop[, step]) -> range object
 |  
 |  Return an object that produces a sequence of integers from start (inclusive)
 |  to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
 |  start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
 |  These are exactly the valid indices for a list of 4 elements.
 |  When step is given, it specifies the increment (or decrement).
 |  
 |  Methods defined here:
 |  
 |  __bool__(self, /)
 |      self != 0
 |  
 |  __contains__(self, key, /)
 |      Return key in self.
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(self, key, /)
 |      Return self[key].
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __reduce__(...)
 |      Helper for pickle.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __reversed__(...)
 |      Return a reverse iterator.
 |  
 |  count(...)
 |      rangeobject.count(value) -> integer -- return number of occurrences of value
 |  
 |  index(...)
 |      rangeobject.index(value) -> integer -- return index of value.
 |      Raise ValueError if the value is not present.
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  start
 |  
 |  step
 |  
 |  stop

range(0,10,2)
range(0, 10, 2)
print(range(0,10,2))
range(0, 10, 2)
for ii in range(0,10,2):
    print(ii)
0
2
4
6
8

Observa, como en el ejemplo de la tabla de multiplicar, que range() tiene como argumento el límite de la secuencia sin llegar a el.

cero_uno_dos = list(range(3))
print(cero_uno_dos)
[0, 1, 2]
uno_dos_tres = list(range(1,4))
print(uno_dos_tres)
[1, 2, 3]

El iterador while#

Podemos tambien repetir un bloque de código hasta que se cumpla una cierta condición:

ii = 1

while ii < 10:
    print(ii**2)
    ii+=1 # '+=' sirve para incrementar el valor de algo, sería lo mismo que ii=ii+1
1
4
9
16
25
36
49
64
81

Interrumpiendo los bucles#

Los bucles se pueden alterar con ordenes como break o continue:

for ii in range(100):
    if ii == 7:
        break
    print(ii)
0
1
2
3
4
5
6
for ii in range(567, 575):
    for jj in range(2, ii):
        if ii % jj == 0:
            print (ii, 'no es número primo porque al menos es divisible por', jj)
            break
567 no es número primo porque al menos es divisible por 3
568 no es número primo porque al menos es divisible por 2
570 no es número primo porque al menos es divisible por 2
572 no es número primo porque al menos es divisible por 2
573 no es número primo porque al menos es divisible por 3
574 no es número primo porque al menos es divisible por 2
for ii in range(1, 10):
    if ii % 2 == 0:
        print(ii, 'es número par')
        continue
    print(ii,'es número impar')
1 es número impar
2 es número par
3 es número impar
4 es número par
5 es número impar
6 es número par
7 es número impar
8 es número par
9 es número impar
for ii in range(567, 575):
    for jj in range(2, ii):
        if ii % jj == 0:
            print (ii, 'no es número primo')
            break
    else:
        print (ii, 'es número primo')
567 no es número primo
568 no es número primo
569 es número primo
570 no es número primo
571 es número primo
572 no es número primo
573 no es número primo
574 no es número primo

Funciones y argumentos de entrada#

Hemos visto que los métodos son funciones asociadas a un objeto. Pero también podemos definir funciones que trabajen independientemente, solitas:

def area_círculo(radio):
    pi = 3.14159265359
    area = pi*radio**2
    return area
mi_area = area_círculo(radio=2.5)
print(mi_area)
19.6349540849375

Esta función tiene un único argumento de entrada: radio. Podríamos hacer una función con más de un argumento de entrada:

def area_triangulo(base, altura):
    
    return 0.5*base*altura
area_triangulo(3.0, 4.0)
6.0

Los dos argumentos de la función, tal y como fueron definidos, se dicen posicionales. La función reconoce que el primero es la base y el segundo la altura. Podemos convertirlos en argumentos «nominales» si les damos además un valor por defecto:

def area_triangulo(base=1.0, altura=1.0):
    
    return 0.5*base*altura

Ahora podemos invocar la función sin darle todos los argumentos de entrada porque hemos definido para ellos valores por defecto:

area_triangulo()
0.5
area_triangulo(altura=2.0)
1.0

Y podemos dar los argumentos de entrada en cualquier orden haciendo uso de sus nombres:

area_triangulo(altura=10.0, base=100.0)
500.0

Por último, podemos definir argumentos «posicionales» y «nominales» pero siempre los posicionales deben ir antes que los nominales:

def area_triangulo(base, altura=3.0):
    
    return 0.5*base*altura
area_triangulo(1.0)
1.5

Tu primer script#

Vamos a terminar esta sesión con algo distinto a mostrar cómo funciona la sintaxis de Python. Vas a hacer tu primer script!

Escribe en un fichero de texto la siguiente linea:

print('Hola mundo!')

Vamos a suponer que hemos llamado a ese fichero con el nombre mi_script.py. Ya lo puedes ejecutar haciendo uso del interpretador Python de tu computadora! En el caso de que estés usando un sistema operativo macOS o una distribución Linux, sólo tienes que ejecutar en la terminal:

python mi_script.py