II 1920 Python PDF
II 1920 Python PDF
2019-2020 1
Python
1 Introducción
Lenguaje normalizado por la Python Software Foundation https://www.python.org/psf/ organización sin
ánimo de lucro, creada en 2001 y dirigida por Guido van Roussum, BDFL
(https://es.wikipedia.org/wiki/Benevolent_Dictator_for_Life) hasta 2018.
Tipado dinámico
Python 3.x es una versión del lenguaje que no mantiene compatiblidad con las versiones anteriores 2.x
Documentación en https://docs.python.org/3/index.html
2 Intérprete
Instalación https://www.python.org/downloads/
Se pueden ejecutar instrucciones Python de forma interactiva en una ventana de comandos utilizando el
intérprete python.exe
Podemos escribir un programa Python utilizando cualquier editor de texto, guardándolo en un archivo
con extensión .py
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 2
La ejecución se realiza en una máquina virtual PVM (Python Virtual Machine). Es un software que
recoge las instrucciones del bytecode y las va interpretando una a una.
Hay varias implantaciones de Python: CPython, Jython, IronPython, Stackless, PyPy. Diferentes
implantaciones ejecutan los programas de forma diferente.
La implantación estandar es CPython, basada en lenguaje C. Permite la integración con código escrito
en lenguaje C y C++.
3 IDEs
Un IDE (Integrated Development Environment) es una software que facilita la programación de
aplicaciones en un determinado lenguaje, incorporando editores de texto, gestor de proyectos,
herramientas de depuración, herramientas de gestión de bibliotecas, etc.
PyCharm es el IDE más utilizado en la actualidad para desarrollo de aplicaciones en lenguaje Python.
https://www.jetbrains.com/pycharm/
Se puede descargar una versión profesional de pago y o una versión Community gratuita. Para los
sistemas Windows, Linux y macOS.
Es posible obtener una licencia gratuita por un año para la versión profesional si se puede demostrar su
utilización para fines educativos.
Cuando se crea un nuevo proyecto, es convieniente asociarle un nuevo venv (virtual environment), con
el objetivo de mantener por separado las dependencias con respecto a los módulos externos con sus
versiones.
4 Comentarios
Con almohadilla hasta el final de línea
# comentario
""" esto es
un comentario """
4.1 print
x = 1
y = 2
z = 3
print(x) # al final añade un salto de línea: 1\n
print(x, y, z) # 1 2 3\n
print(x, y, z, end='') # al final no añade nada: 1 2 3
print(x, y, z, sep=', ') # indica separador entre datos: 1, 2, 3\n
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 4
Cada variable u objeto pertenece a un determinado tipo ó clase: número entero, número real, cadena de
caracteres, etc
Para poder acceder a variables u objetos, en el código se utilizan referencias ó atributos. Una referencia
ó atributo contiene la dirección de memoria donde se almacena la variable u objeto, se dice que la
referencia apunta al objeto.
No es necesaria una declaración previa donde se indique el tipo de dato que se va a manejar, el tipo se
deduce a partir del contexto donde se utiza el objeto
En la siguiente instrucción se crea la referencia ó atributo x que apunta a un nuevo objeto que contiene
el texto "Vigo"
x = "Vigo"
Mediante la función print() se puede visualizar en pantalla el valor de un objeto apuntado por una
referencia:
print(x)
visualiza "Vigo" en pantalla. Mediante la función id() se puede obtener el valor de una referencia:
print(id(x))
x = "Cambados"
Ahora
print(id(x))
visualiza 236143664, indicando que el objeto apuntado por la referencia x se encuentra en otro lugar.
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 5
y = x
z = "Cambados"
print(id(x))
print(id(y))
print(id(z))
Las referencias ó atributos no tienen un tipo asociado, sin embargo los objetos sí pertenecen a un tipo ó
clase determinada, que se puede obtener con la función type(). Si ahora ejecutamos:
print(type(x))
visualiza <class 'str'> en pantalla, indicando el el objeto apuntado por x pertenece a la clase str,
es decir, una cadena de caracteres.
Con isinstance() se puede comprobar si un objeto apuntado por una referencia pertenece a una clase
determinada
a = 3
esEntero = isinstance(a, int) # True
esReal = isinstance(a, float) # False
La misma referencia puede apuntar a objetos de diferentes tipos en diferentes momentos. Por ejemplo,
si a continuación ejecutamos:
x = 1000
print(id(x))
print(type(x))
visualiza 220446112 y <class 'int'> indicando que ahora el objeto apuntado por x está en otra
posición de memoria y es de tipo entero, pertenece a la clase int.
Los enteros se manejan en objetos inmutables, por lo que cualquier modificación implica la creación de
un nuevo objeto:
x = x + 1
print(x)
print(id(x))
visualiza 1001 y 220446384. Los enteros se pueden inicializar con un valor, pero no se pueden modificar
posteriormente.
x = 1000
y = 1000
print(id(x), id(y), x == y, x is y) # Visualiza 193800256 193800256 True True
y = y + 1
print(id(x), id(y), x == y, x is y) # Visualiza 193800256 186776992 False False
y = y - 1
print(id(x), id(y), x == y, x is y) # Visualiza 193800256 2478464 True False
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 6
Con varias referencias a un objeto inmutable, cualquier modificación hecha con una referencia crea otro
objeto
x = 1
y = x # apunta al mismo objeto
y = 2 # apunta a otro objeto y no modifica el apuntado por x
Con varias referencias a un objeto mutable, las modificaciones hechas con una referencia se ven desde
las demás referencias:
Si se desea trabajar con copias de objetos mutables en lugar de tener varias referencias al mismo
objeto, hay que utilizar:
x = [1, 2, 3]
y = x[:] # y apunta a una copia
y = list(x) # otra forma de hacer una copia
y = x.copy() # otra forma de hacer una copia
y[0] = 4 # no modifica x
lista = ['a', x[:], 'b'] # contiene una copia de x
diccionario = {1:x[:], 2:'hola'} # contiene una copia de x
El método copy() y utilizar [:] en listas sólo hace copia de los objetos de primer nivel en listas y
diccionarios. Si se desea hacer copia recursiva de todos los objetos en niveles más profundos, hay que
utilizar el módulo copy:
import copy
y = copy.deepcopy(x)
Existe el objeto predefinido None. Cualquier referencia puede apuntar a este objeto para indicar que no
apunta a ningún objeto útil.
x = None
if x is None:
print("No apunta a un objeto útil")
Las funciones también se manejan en objetos, las referencias pueden apuntar a funciones:
x = print
x(37)
print(id(x))
print(type(x))
6 Valores numéricos
- en un entero de longitud fija (32 o 64 bits, dependiedo de la implantación) si está dentro del rango:
Con 64 bits, desde -263 = -9.223.372.036.854.775.808 hasta 263-1 = 9.223.372.036.854.775.807
x = 35 # en decimal
x = 0o177 # en octal
x = 0x3a # en hexadecimal
x = 0b1101011 # en binario
a = 1234
cadena = str(a) # '1234'
cadenaHexadecimal = hex(a) # '0x4d2'
cadenaOctal = oct(a) # '0o2322'
cadenaBinario = bin(a) # '0b10011010010'
Para convertir desde cadena de texto expresada en cualquier base a número entero
a = int('0b11',2) # 3
Operaciones aritméticas
x = 7
y = 3
z = x + y # suma = 10
z = x - y # resta = 3
z = x * y # multiplicación = 21
z = x / y # división = 2.3333333333333335
z = x // y # división entera = 2
z = x % y # resto de la división entera = 1
z = - x # cambio de signo = -7
Los operadores aritméticos se pueden combinar con la asignación = cuando el resultado de una
operación hay que guardarlo en el primer operando. Son equivalentes:
x += 1 equivalente a x = x + 1
x /=2 equivalente a x = x / 2
x = 3
y = 5
z = x < y # Menor = True
z = x <= y # Menor o igual = True
z = x == y # Igual = False
z = x >= y # Mayor o igual = False
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 8
x = 0b1101
y = 0b1010
z = x | y # OR bit a bit, resultado 0b1111
z = x & y # AND bit a bit, resultado 0b1000
z = x ^ y # XOR bit a bit, resultado 0b111
z = ~x # negación bit a bit, resultado -0b1110
z = x << 2 # desplazamiento de bits a la izquierda dos posiciones, resultado 0b110100
z = x >> 1 # desplazamiento de bits a la derecha una posición, resultado 0b110
x = min(3, 2, 6, 9) # 2
x = max(5, 2, 6) # 6
x = sum((1, 2, 3, 4)) # 10
Clase float
Los números reales se manejan por defecto en formato IEEE de 64 bits. Si se necesita más precisión,
se pueden utilizar los módulos decimal, numpy.float128, fractions
x = 1.23
x = 1.
x = 3.2e-4
x = 4.32e38
En este formato se realizan cálculos aproximados, ya que con 64 bits no se puede representar toda la
recta real
import math
a = math.pi # Número PI
b = math.sqrt(34) # Raíz cuadrada de 34
c = math.e # Número E
d = math.cos(math.pi / 3) # coseno de PI/3
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 9
Eliminación de decimales
x = math.floor(-2.3) # -3
x = math.trunc(-2.3) # -2
Potencias
x = 2 ** 3 # 2 elevado a 3, resultado 8
x = pow(2, 3) # idem
Números aleatorios
import random
x = random.random() # Número real aleatorio entre 0 y 1, ambos inclusive
x = random.randint(1, 10) # Número entero aleatorio entre 1 y 10, ambos inclusive
7 Buleanos
Objetos de la clase bool
x = True
y = 1 > 2 # False
z = x and y # False
z = x or y # True
z = not x # False
Los valores de los objetos de cualquier clase se pueden utilizar como buleanos:
- los valores numéricos son False si valen 0, si no son True
- los demás objetos son False si están vacíos
"hola" True
"" False
[1, 2] True
[] False
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 10
{'a': 1} True
{} False
1 True
0 False
0.0 False
None False
cadena = 'hola'
if len(cadena) == 0: # comprueba si cadena vacía
vacia = True
if cadena: # alternativa
vacia = True
x = int(True) # 1
x = bool(1) # True
x = int(False) # 0
x = bool(0) # False
8 Cadenas de caracteres
Clases:
- str: cadena de caracteres Unicode en un objeto inmutable
- bytes: conjunto inmutable de bytes que puede codificar una cadena Unicode o cualquier información
binaria
- bytesarray: conjunto mutable de bytes
Una cadena es un tipo secuencia, donde los elementos son inmutables y se sitúan unos con respecto a
otros de forma ordenada, cada uno en una posición, desde la posición 0.
cadena = 'Hola'
cadena = "Hola"
Para cadenas que ocupan varias líneas se encierran entre triple comilla simple o doble:
cadena = 'Hola'
longitud = len(cadena) # 4
Indicando un único entero entre corchetes, se puede acceder a un carácter para leerlo. Si es positivo, se
cuenta desde el comienzo y la primera posición es 0. Si es negativo, se cuenta desde el final hacia atrás
y la primera posición es -1.
cadena = "Ingeniería"
caracter = cadena[2] # Carácter en la posición 2 = 'g'
caracter = cadena[-2] # Carácter en la posición 2 desde la siguiente posición al final = 'í'
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 11
Subcadenas: indicando varios valores enteros separados por : entre corchetes, se pueden obtener
partes de una cadena de varias formas
cadena = "Ingeniería"
subcadena = cadena[1:4] # Desde posición 1 a 3 = 'nge'
subcadena = cadena[:4] # Igual que cadena[0:4] = 'Inge'
subcadena = cadena[2:] # Desde posición 2 hasta el final = 'geniería'
subcadena = cadena[:-3] # Desde el comienzo y evitando 3 caracteres al final = 'Ingenie'
subcadena = cadena[1:-1] # Desde posición 1 y evitando caracter final = 'ngenierí'
subcadena = cadena[-2:] # Los dos últimos caracteres = 'ía'
subcadena = cadena[-2:-1] # El penúltimo caracter = 'í'
subcadena = cadena[::2] # De 2 en 2 caracteres = 'Igneí'
subcadena = cadena[3:7:2] # De posición 3 a 6 de 2 en 2 = 'ei'
subcadena = cadena[::-1] # En orden inverso = 'aíreinegnI'
subcadena = cadena[7:3:-1] # En orden inverso entre dos posiciones = 'rein'
Concatenación con el operador +. Cada operación de concatenación genera una nueva cadena.
cadena1 = "Ingeniería"
cadena2 = "Industrial"
total = cadena1 + " " + cadena2 # "Ingeniería Industrial"
No se pueden modificar partes de una cadena utilizando la notación con corchetes, ya que las cadenas
son objetos inmutables.
cadena = "Ingeniería"
cadena[0] = 'i' # Genera un error en el programa, operación ilegal
cadena = "Ingeniería"
cadena = 'i' + cadena[1:]
# Concatena la cadena 'i' con la cadena 'ngeniería', resultado 'ingeniería'
También se puede utilizar el método replace(), que reemplaza la subcadena indicada como primer
parámetro por la que se indica como segundo parámetro, en cualquier caso siempre generando un
nuevo objeto de la clase str:
cadena = "Ingeniería"
cadena = cadena.replace('I', 'i') # "ingeniería"
cadena = "Ingeniería"
texto = cadena * 5 # "IngenieríaIngenieríaIngenieríaIngenieríaIngeniería"
Se puede utilizar in para comprobar si una cadena forma parte de otra. Genera un buleano:
Partir una cadena en una lista de subcadenas con el método split() al que se le indica el separador:
cadena = '23,52,-11'
partes = cadena.split(',') # ['23', '52', '11']
A mayúsculas y minúsculas
cadena = 'Ingeniería'
texto = cadena.upper() # 'INGENIERÍA'
texto = cadena.lower() # 'ingeniería'
numProductos = 11
numCajas = 7
x = 27
cadena = str(x) # Conversión de entero a texto, resultado '27'
y = int(cadena) # Conversión de texto a entero, resultado 27
x = 27.3
cadena = str(x) # Conversión de real a texto, resultado '27.3'
y = float(cadena) # Conversión de texto a real, resultado 27.3
También se puede comprobar si contiene un cierto texto a partir de una cierta posición y hasta otra
posición:
cadena = 'Hola mundo'
resultado = cadena.startswith('mu', 5, 7) # True
resultado = cadena.endswith('mu', 5, 7) # True
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 14
9 Listas
Objetos de la clase list
Es una secuencia, las referencias se ordenan de la primera a la última y se les asigna una posición
correlativa comenzando en 0.
Cuando se añade un objeto a una lista no se carga una copia del objeto, se carga una referencia al
objeto original.
L = [123, 'hola', 1.23] # Una lista con referencias a 3 objetos de clases diferentes
n = len(L) # Número de elementos en la lista = 3
L = [1, 2]
print(L[2])
Se puede crear una lista con referencias a None y posteriormente se pueden guardar referencias a otros
objetos
L = [None] * 10
L[3] = 'hola'
if L[4] is None:
print('No está')
lista = [1, 2, 3, 4, 5]
parte = lista[2:] # [3, 4, 5]
parte = lista[:2] # [1, 2]
parte = lista[2:4] # [3, 4]
parte = lista[-2:] # [4, 5]
parte = lista[:-2] # [1, 2, 3]
L = [1, 2, 3, 4, 5]
esta1 = 1 in L # True
esta7 = 7 in L # False
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 15
lista = [1, 2, 3, 4, 5]
lista[0] = 10 # [10, 2, 3, 4, 5]
lista[2:5] = [30, 40, 50] # [10, 2, 30, 40, 50]
lista[2:3] = ["uno", "dos", "tres"] # [10, 2, 'uno', 'dos', 'tres', 40, 50]
Los int son inmutables y las listas son mutables, por lo que:
Se puede crear una nueva lista como copia de una lista existente:
lista = [1, 2, 3, 4, 5]
lista[2:5] = [] # [1, 2]
lista = [1, 2, 3, 4, 5]
x = lista.pop(2) # x = 3, lista = [1, 2, 4, 5]
x = lista.pop() # x = 5, lista = [1, 2, 4]
del lista[0] # [2, 4]
lista = [1, 2, 3, 4, 5]
del lista[2:] # [1, 2]
datos = [1, 2, 3]
suma = 0
for dato in datos:
suma += dato
print(suma) # 6
10 Diccionarios
Son objetos de la clase dict
Las claves tienen que ser referencias a objetos inmutables: cadena, número, tupla.
También pueden ser objetos de clases que sean hashables.
Los valores pueden pertenecer todos a la misma clase o a clases diferentes. Las claves también.
consumos['fresadora'] = 750
c = consumos['amoladora'] # 1200
c = consumos.get('rebarbadora', 0) # 0
consumoTotal = 0
for maquina in consumos:
consumoTotal += consumos[maquina]
print(consumoTotal) # 2815
Las claves no están ordenadas, si se quiere recorrer el diccionario por clave de menor a mayor:
maquinas = list(consumos.keys())
# ['taladro', 'soldador', 'amoladora', 'caladora', 'fresadora']
persona = {
'identidad': {'nombre': 'Juan', 'apellido1': 'Alonso', 'apellido2': 'Gómez'},
'puestos': ['ingeniero', 'gerente'],
'edad': 35
}
print(persona['identidad']) # {'nombre':'Juan', 'apellido1':'Alonso', 'apellido2':'Gómez'}
print(persona['identidad']['nombre']) # Juan
print(persona['puestos'][-1]) # gerente
persona['puestos'].append('jefe de ventas') # añade a la lista de puestos
print(persona['puestos']) # ['ingeniero', 'gerente', 'jefe de ventas']
Copia de diccionarios
D1 = {'a': 1, 'b': 2, 'c': 3}
D2 = D1 # la referencia D2 apunta al mismo diccionario apuntado por la referencia D1
print(D1) # {'a': 1, 'b': 2, 'c': 3}
print(D2) # {'a': 1, 'b': 2, 'c': 3}
D1['a'] = 10 # modifica también el diccionario apuntado por D2
print(D2) # {'a': 10, 'b': 2, 'c': 3}
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 18
La función copy() del módulo copy hace una copia de las referencias de primer nivel
import copy
Para crear un duplicado de un diccionario a todos los niveles hay que utilizar la función deepcopy()
import copy
Borrar entradas
D1 = {'a':1, 'b':2, 'c':3}
valor = D1.pop('a') # 1
print(D1) # {'b': 2, 'c': 3}
del D1['b']
print(D1) # {'c': 3}
11 Tuplas
Una tupla es un objeto de la clase tuple
Es una lista ordenada inmutable de referencias a objetos de cualquier clase, incluso de diferentes
clases
Creación:
Número de elementos
T = (10, 20, 30)
n = len(T) # 3
Concatenación
T1 = (1, 2, 3, 4)
T2 = T1 + (5, 6) # (1, 2, 3, 4, 5, 6)
T = (1, 2, 3, 4)
T[0] = 2 # genera un error en el programa
T = (2,) + T[1:] # (2, 2, 3, 4)
Repetición
T = (1, 2) * 3 # (1, 2, 1, 2, 1, 2)
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 20
12 Conjuntos
Clase set
Cada valor aparece sólo una vez, aunque se añada varias veces.
Añadir elementos
x = {1, 2, 3}
x.add(4) # {1, 2, 3, 4}
x.add(2) # {1, 2, 3, 4} los elementos no se repiten
Operaciones lógicas
x = {1, 2, 3}
y = {3, 4}
z = x | y # unión, resultado {1, 2, 3, 4}
z = x & y # intersección, resultado {3}
z = x ^ y # elementos no comunes, resultado {1, 2, 4}
x = {1, 2, 3}
y = {1, 2}
a = x < y # False
a = x > y # True
a = x < x # False
a = x <= x # True
Diferencias
x = {1, 2, 3}
y = {3, 4}
z = x - y # {1, 2}
z = y - x # {4}
13 Comparaciones en colecciones
El operador de comparación == compara el valor de los objetos (recursivamente si son colecciones que
contienen colecciones)
Las comparaciones de menor o mayor utilizan los valores de los objetos y en listas y tuplas pueden
recorrer recursivamente varios niveles, dentro del mismo nivel de izquierda a derecha
L1 = [1, (2, 'a')]
L2 = [1, (2, 'b')]
(menor, menorOIgual, igual, mayorOIgual, mayor) = (L1 < L2, L1 <= L2, L1 == L2, L1 >= L2, L1 >
L2) # True, True, False, False, False
En conjuntos:
- C1 == C2 devuelve True si C1 y C2 tienen los mismos elementos.
- C1 <= C2 devuelve True si los elementos de C1 están en C2
- C1 >= C2 devuelve True si los elementos de C2 están en C1
- C1 < C2 devuelve True si los elementos de C1 están en C2 y C2 tiene algún elemento más que C1
- C1 > C2 devuelve True si los elementos de C2 están en C1 y C1 tiene algún elemento más que C2
C1 = {1, 2, 3, 4, 5}
C2 = {4, 5}
(menor, menorOIgual, igual, mayorOIgual, mayor) = (C1 < C2, C1 <= C2, C1 == C2, C1 >= C2, C1 >
C2) # False, False, False, True, True
En diccionarios sólo se puede aplicar el operador == para comprobar si tienen los mismos valores en
sus pares no ordenados clave:valor
14 Instrucciones
El final de línea indica fin de instrucción
Alternativamente se puede utilizar un punto y coma ; para marcar el final de cada instrucción, así se
pueden escribir varias instrucciones en la misma línea
x = 1; y = 2;
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 22
Para incluir una o varias instrucciones dentro de otra instrucción, se utiliza la sangría
lista = []
finalizar = False
while not finalizar:
cadena = input('Introduce una cadena: ')
if cadena == 'fin':
finalizar = True
else:
lista.append(cadena)
Si una instrucción es larga, se pueden utilizar paréntesis en una expresión para poder escribirla en
varias líneas
if a == b and b == c and c == d:
print('iguales')
if (a == b and
b == c and
c == d):
print('iguales')
O se puede utilizar la barra invertida para indicar que la instrucción continúa en la siguiente línea:
if a == b and \
b == c and \
c == d:
print('iguales')
x = 1 + 2 + 3 \
+ 4
pass para indicar una instrucción vacía. Ejemplo: esperar mientras una entrada digital está a 1:
while entrada() == 1:
pass
14.1 if
x = 3
y = 5
if x > y:
maximo = x
else:
maximo = y
x = 3
if x < 0:
resultado = 'negativo'
elif x == 0:
resultado = 'nulo'
else:
resultado = 'positivo'
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 23
14.2 while
14.3 for
Ejemplos:
suma = 0
for x in [1, 2, 3, 4, 5]:
suma += x
Suele utilizarse la clase range para iterar en un cierto rango de valores o para crear una lista de valores
a partir de un rango:
for i in range(3):
print(i) # visualiza 0 1 2
15 Funciones
Las funciones se definen mediante la ejecución de la instrucción def.
Sólo existe el pase de parámetros por referencia, no existe el pase de parámetros por valor.
En Python no se manejan valores en el código, se utilizan referencias a objetos que contienen valores.
Cuando se importa un módulo, se ejecutan una sola vez todas las instrucciones que figuran a nivel
externo (no incluidas en funciones ni en métodos de clases), incluso las instrucciones def.
Los parámetros se pueden indicar por posición o por nombre y pueden tener valores por defecto
x = 7
y = 5
a = minimo(x, y) # a = 5
b = maximo(x, y) # b = 7
(a, b) = minmax(x, y) # a = 5, b = 7
a, b = minmax(x, y) # a = 5, b = 7, para recoger el resultado se pueden obviar los paréntesis
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 25
def visualiza(x):
print(x)
visualiza('hola')
Aunque el pase de parámetros siempre se realiza por referencia, cuando se pasan referencias a objetos
inmutables, la función no puede modificarlos, tiene que devolver copias con nuevos valores.
a = 5
actualiza(a) # resultado a = 5
a = 5
a = actualiza(a) # resultado a = 6
a = [1]
actualiza(a) # resultado: a = [1, 2]
Se pueden ejecutar instrucciones def dentro de instrucciones if, dentro de bucles y dentro de otros def.
version = 2
if version == 1:
def modifica(x):
return 2 * x;
else:
def modifica(x):
return 2 + x;
y = modifica(5)
El identificador asignado a una función es en realidad una referencia a un objeto que representa a esa
función. Estas referencias a funciones se pueden utilizar en instrucciones, por ejemplo en asignaciones:
f = suma
a = f(3, 2)
f = multiplica
b = f(3, 2)
a = opera(suma, 3, 2)
b = opera(multiplica, 3, 2)
Debido a que los parámetros no tienen tipo, se puede hacer fácilmente polimorfismo: las mismas
instrucciones ejecutan acciones diferentes si se aplican a tipos de datos diferentes
a = suma(3, 2)
b = suma('hola ', 'Pepe')
- Si se modifica una referencia dentro de una función utilizando el operador de asignación = , es una
referencia local a la función
- Si se utiliza una referencia en una función pero no se modifica, es una referencia global
- Si se quiere modificar una referencia global dentro de una función, hay que marcarla previamente
con la palabra reservada global
Ejemplo:
def f1():
print(x) # en f1 no se modifica la referencia x, por defecto es global, visualiza 1
def f2():
x = 7 # modifica la referencia, entonces por defecto es local
print(x) # visualiza 7
def f3():
global x # indica que la referencia x es global
x = 5 # apunta a un objeto con el valor 5
print(x) # visualiza 5
def f4():
print(x) # error: está intentando utilizar una referencia local que aún no se creó
x = 5
f1()
print(x) # visualiza 1
f2()
print(x) # visualiza 1
f3()
print(x) # visualiza 5
f4() # genera un error
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 27
lista = [1, 2, 3]
def f():
lista.append(4)
# Utiliza la referencia global porque no la modifica, está modificando el
# objeto apuntado por la referencia
f()
print(lista) # visualiza [1, 2, 3, 4]
16 Excepciones
Instrucción try para la ejecución de un algoritmo con captura de excepciones. Ejemplo:
try:
x = float(input("X=")) # introduce un float por consola
y = float(input("Y=")) # introduce un float por consola
z = x + y
print("x+y=", z) # visualiza la suma
except Exception as e: # si hay algún problema, captura la excepción
print("Error: " + str(e)) # mensaje de error si algún dato es incorrecto
Ejecución:
def KelvinACelsius(kelvin):
if kelvin < 0:
raise Exception("No puede ser negativa")
return kelvin - 273.15
try:
kelvin = -1
celsius = KelvinACelsius(kelvin)
print(celsius)
except Exception as e:
print(e)
17 Módulos
En un módulo A.py se pueden utilizar los recursos definidos en otro módulo B.py importándolo
import B
Un módulo es un espacio de nombres donde se definen recursos (objetos, funciones, clases, etc). Para
utilizar cada recurso se emplea una referencia ó atributo.
texto = "hola"
este módulo se puede importar en otro módulo y se puede utilizar esa referencia:
import modulo
print(modulo.texto)
Cuando se recoge el atributo con la instrucción from, se crea otra referencia en el espacio de nombres
del módulo donde se realiza la importación:
Hay que tener en cuenta que las referencias pueden apuntar a objetos mutables o inmutables.
Ejemplo: archivo m1.py
dato = 11
lista = [12]
import m1
from m1 import dato, lista
Si se quiere preparar un módulo para que se pueda importar de forma que todo o parte no se ejecute en
la importación, hay que utilizar
if __name__ == "__main__":
instrucciones
La variable predefinida __name__ toma el valor "__main__" en el caso de que el módulo sea el módulo
principal (ejecutado con python modulo.py), pero toma el nombre del módulo en el caso de que este
módulo sea importado por otro.
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 29
18 Paquetes
Los módulos se pueden organizar en directorios.
En un import se puede indicar un archivo Python para poder importar un módulo, pero también se
puede indicar un directorio para importar un paquete.
Un paquete consiste en un directorio donde hay otros paquetes (otros directorios) y/o módulos (archivos
con extensión .py con código Python).
Ejemplo: directorio paquete1 con el archivo modulo.py y directorio paquete2 con el archivo modulo.py
En otro módulo:
En el directorio de un paquete se suele definir el módulo __init__.py que se importa cuando se importa
el paquete completo. Ejemplo:
x = 10
En paquete2\__init__.py
x = 20
En otro módulo:
import paquete1
import paquete2
print(paquete1.x, paquete2.x) # visualiza 10 20
En https://pypi.org se puede consultar un repositorio de paquetes (PyPI - Python Package Index) que se
pueden descargar e instalar utlizando el programa pip.exe
Ejemplo: instalación del paquete numpy con recursos para cálculo matricial
El paquete numpy dispone del módulo linalg con operaciones de cálculo matricial en el que está
definida la función inv para invertir matrices cuadradas. Ejemplo:
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 30
ai = linalg.inv(a)
print(ai)
# Utiliza la función inv del módulo numpy.linalg para calcular la inversa de la matriz
# y la visualiza
b = a.dot(ai)
print(b)
# Calcula la multiplicación de la matriz por su inversa utilizando el método dot() de
# la clase array y visualiza el resultado
19 Clases
En una aplicación sólo se puede instanciar un módulo una única vez. Sin embargo, pueden instanciarse
varios objetos pertenecientes a la misma clase.
Para crear atributos dentro de una clase, hay que utilizarlos precedidos de self. Cada atributo es una
referencia a un objeto. Cada objeto de una clase tiene sus propios atributos.
Para crear un objeto de una clase, hay que utilizar el constructor de la clase, es el método __init__
Cada método de la clase recibe como primer parámetro self, que es una referencia al mismo objeto
sobre el que se ejecuta el método.
Ejemplo:
class Contador:
# Cada objeto de esta clase representa a un contador que mantiene un valor entero
self.valor = valorInicial
# Crea el atributo valor y lo inicializa apuntando al entero que expresa el valor
# inicial del contador
def incrementa(self):
# Método para incrementar el valor del contador
self.valor = self.valor + 1
# Actualiza el atributo valor para que apunte a un entero con el valor incrementado
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 31
def decrementa(self):
# Método para decrementar el valor del contador
self.valor = self.valor - 1
# Actualiza el atributo valor para que apunte a un entero con el valor decrementado
a = Contador()
# Referencia a un nuevo objeto de la clase Contador creado mediante la llamada al
# constructor de esa clase, inicializando su valor a 0
a.incrementa()
# Ejecuta el método incrementa() sobre el objeto apuntado por la referencia 'a'
# para incrementar su valor
print(a.valor)
# Visualiza el entero apuntado por el atributo 'valor' del objeto apuntado por 'a'
b = Contador(100)
b.decrementa()
print(b.valor)
Aquellos atributos que se desea manejar de forma privada dentro de la clase, suelen nombrarse
precedidos por dos barras bajas __
Ejemplo:
class Contador:
# Cada objeto de esta clase representa a un contador que mantiene un valor entero
self.__valor = valorInicial
# Crea el atributo __valor y lo inicializa apuntando al entero que expresa el valor
# inicial del contador
def incrementa(self):
# Método para incrementar el valor del contador
self.__valor = self.__valor + 1
# Actualiza el atributo __valor para que apunte a un entero con el valor incrementado
def decrementa(self):
# Método para decrementar el valor del contador
self.__valor = self.__valor - 1
# Actualiza el atributo __valor para que apunte a un entero con el valor decrementado
def getValor(self):
# Método para obtener el valor del contador
return self.__valor
# devuelve el atributo __valor
a = Contador()
# Referencia a un nuevo objeto de la clase Contador creado mediante la llamada al
# constructor de esa clase, inicializando su valor a 0
a.incrementa()
# Ejecuta el método incrementa() sobre el objeto apuntado por la referencia 'a'
# para incrementar su valor
print(a.getValor())
# Visualiza el valor del objeto apuntado por la referencia 'a'
b = Contador(100)
b.decrementa()
print(b.getValor())
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 32
Con cada llamada a un método sobre un objeto objeto.metodo(), el itérprete Python busca la clase y
luego ejecuta clase.metodo(objeto), por eso los métodos en la clase reciben self como parámetro.
Para el ejemplo anterior son equivalentes
a.incrementa()
Contador.incrementa(a)
En Python no existe la sobrecarga de métodos (varios métodos con el mismo identificador pero
diferente número y/o tipo de parámetros), por lo que en una clase sólo puede haber un único constructor
class Punto:
# Un objeto de esta clase representa a un punto en 2D con sus coordenadas x e y
# guardadas en los atributos __x e __y
if ey is None:
ey = ex
if ex == 1 and ey == 1:
return
if origen.__x == self.__x and origen.__y == self.__y:
return
self.__x = origen.__x + (self.__x - origen.__x) * ex
self.__y = origen.__y + (self.__y - origen.__y) * ey
if angulo == 0.0:
return
if origen.__x == self.__x and origen.__y == self.__y:
return
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 33
t = Punto(3, 2)
p1.traslada(t) # Traslada p1 utilizando las coordenadas de t, resultado (13, 22)
p2.escala(Punto(10, 10), 3)
# Escala por 3 el punto p2 con respecto a (10, 10), resultado (10, 40)
class PuntoInmutable:
# Un objeto de esta clase representa a un punto en 2D con sus coordenadas x e y
# guardadas en los atributos __x e __y. Es inmutable, se puede inicializar pero
# no se puede modificar posteriormente
if ey is None:
ey = ex
if ex == 1 and ey == 1:
return self
if origen.__x == self.__x and origen.__y == self.__y:
return self
return PuntoInmutable(origen.__x + (self.__x - origen.__x) * ex,
origen.__y + (self.__y - origen.__y) * ey)
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 34
if angulo == 0.0:
return self
if origen.__x == self.__x and origen.__y == self.__y:
return self
coseno = math.cos(angulo * math.pi / 180);
seno = math.sin(angulo * math.pi / 180);
return PuntoInmutable(
origen.__x + (self.__x - origen.__x) * coseno - (self.__y - origen.__y) * seno,
origen.__y + (self.__x - origen.__x) * seno + (self.__y - origen.__y) * coseno)
t = PuntoInmutable(3, 2)
p2 = p1.traslada(t) # Traslada p1 utilizando las coordenadas de t, resultado (13, 22)
p2 = p1.escala(PuntoInmutable(10, 10), 3)
# Escala por 3 el punto p2 con respecto a (10, 10), resultado (10, 40)
19.3 Herencia
Mediante herencia se puede crear una clase derivada a partir de una o varias clases base.
La clase derivada recibe todos los métodos y atributos de sus clases base.
La clase derivada puede añadir más métodos y atributos y también puede redefinir los que recibe de
sus clases base.
Aquellos atributos privados de las clases base que se vayan a utilizar en las clases derivadas se les
asignará identificadores que comienzan con una barra baja _
Ejemplo:
class Punto:
# Un objeto de esta clase representa a un punto en 2D con sus coordenadas x e y
# guardadas en los atributos _x e _y
if e == 1:
return
if origen._x == self._x and origen._y == self._y:
return
self._x = origen._x + (self._x - origen._x) * e
self._y = origen._y + (self._y - origen._y) * e
if angulo == 0.0:
return
if origen._x == self._x and origen._y == self._y:
return
coseno = math.cos(angulo * math.pi / 180);
seno = math.sin(angulo * math.pi / 180);
dx = self._x - origen._x
dy = self._y - origen._y
nuevoX = origen._x + dx * coseno - dy * seno
nuevoY = origen._y + dx * seno + dy * coseno
self._x = nuevoX
self._y = nuevoY
class Circulo(Punto):
# Clase Circulo derivada de la clase base Punto
# Cada objeto Circulo dispone de los atributos _x e _y recibidos de la clase Punto
# para representar las coordenadas de su centro
# Se añade el atributo __radio para representar a su radio
self.__radio = radio
# Añade el atributo __radio para guardar el radio del círculo
Punto.escala(self, origen, e)
# Aplica el método escala() de la clase base Punto para aplicar el escalado
# al centro representado por _x e _y
self.__radio = self.__radio * e
# Añade esta instrucción para escalar también el radio
c2 = c1.clona()
# Crea otro objeto como copia del primero
c1.traslada(Punto(1, 2))
# Traslada el círculo con un vector de traslación (1, 2), como resultado el centro
# se traslada a (11, 22)
c1.escala(Punto(10, 0), 3)
# Escala el círculo con respecto a (10, 0) con un factor de 3, como resultado el
# centro termina en (13, 66) y con radio 3
Para esta clase Circulo no es necesario definir los métodos traslada() ni rota(), debido a que los
mismos métodos que se reciben de la clase base Punto son válidos para Circulo, ya que en esas
operaciones no es necesario modificar el radio.
Los datos creados dentro de una clase y fuera de métodos, son datos estáticos
Los métodos marcados con @staticmethod son métodos estáticos, que sólo pueden acceder a datos
estáticos
Ejemplo:
class Automovil:
def getMatricula(self):
return self.__matricula
a = Automovil("1234 ABC")
b = Automovil("9876 XYZ")
print(a.getMatricula())
print(Automovil.getContador())
Cuando se codifican clases, es frecuente añadir métodos que permiten obtener cierta información
(getters) y métodos que permite modificarla (setters). Mediante las instrucciones de este código se
puede controlar cómo se realizan estas operaciones.
Ejemplo: clase para manejar ángulos que siempre se representan con un valor comprendido entre 0 y
360 grados
import math
class Angulo:
# Clase para almacenar un ángulo entre 0 y 360 grados
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 37
a = Angulo(90)
print(a.getGrados(), a.getRadianes()) # 90 1.5707963267948966
a.setGrados(370)
print(a.getGrados(), a.getRadianes()) # 10 0.17453292519943295
a.setGrados(-20)
print(a.getGrados(), a.getRadianes()) # 340 5.934119456780721
a.setRadianes(math.pi / 2)
print(a.getGrados(), a.getRadianes()) # 90.0 1.5707963267948966
Es posible añadir propiedades para poder realizar estas operaciones de lectura/escritura de información
como si fuesen variables:
class Angulo:
# Clase para almacenar un ángulo entre 0 y 360 grados
a = Angulo(90)
print(a.grados, a.radianes) # 90 1.5707963267948966
a.grados = 370
print(a.grados, a.radianes) # 10 0.17453292519943295
a.grados = -20
print(a.grados, a.radianes) # 340 5.934119456780721
a.radianes = math.pi / 2
print(a.grados, a.radianes) # 90.0 1.5707963267948966
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 38
- se pueden expresar valores numéricos con o sin signo, con o sin parte decimal. Ej: 45.782
- matrices con varios valores del mismo tipo separados por comas y delimitadas entre corchetes.
Ej: ["blanco", "negro"]
- objetos diccionario indicados entre llaves, conteniendo uno o varios pares clave:valor, donde la
clave es una cadena de caracteres y el valor puede ser de cualquier tipo.
Ej: {"herramienta":"taladro", "coste":249.32}
Ejemplo:
[
{
"dni": 123456,
"nombre": "Ana",
"direccion": "Vigo",
"email": "[email protected]"
},
{
"dni": 654321,
"nombre": "Juan",
"direccion": "Monforte",
"email": "[email protected]"
}
]
D2 = json.loads(cadena)
# Realiza la operación inversa: partiendo de una cadena con texto
# en formato JSON, crea un diccionario
Python. Informática Industrial. Escuela de Ingeniería Industrial, Vigo. 2019-2020 39
objeto = {
'completo': {'nombre': 'Juan', 'apellido1': 'Gómez', 'apellido2': 'Alonso'},
'empleo': ['ingeniero', 'gerente'],
'edad': 30}
# Crea un diccionario
{
"completo": {
"nombre": "Juan",
"apellido": "G\u00f3mez"
},
"empleo": [
"ingeniero",
"gerente"
],
"edad": 30
}
La letra acentuada 'ó' de 'Gómez' se indica con su código UNICODE \u00f3 expresado en hexadecimal
con el objetivo de que en el archivo JSON haya sólamente caracteres ASCII. En el caso de que se
desee que no se realice esta conversión, se puede añadir el parámetro ensure_ascii=False