You've already forked Curso-lenguaje-python
Restructure content and add notes from HolaMundo
Signed-off-by: Manuel Vergara <manuel@vergaracarmona.es>
This commit is contained in:
28
python-total/dia_07/01_clases.py
Normal file
28
python-total/dia_07/01_clases.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
Clases
|
||||
"""
|
||||
|
||||
# La mínima clase es poner pass
|
||||
|
||||
|
||||
class Pajaro:
|
||||
pass
|
||||
|
||||
|
||||
# mi_pajaro es una instancia de Pajaro,
|
||||
# que en este punto se considera un objeto
|
||||
mi_pajaro = Pajaro()
|
||||
|
||||
# Si intentamos mostrar la expresión mínima nos dirá
|
||||
# que es un objeto guardado en cierto espacio de memoria
|
||||
print(mi_pajaro)
|
||||
|
||||
# Si mostramos el tipo nos dirá __main__
|
||||
print(type(mi_pajaro))
|
||||
|
||||
# Podemos crear más objectos y serán distintos de la misma clase
|
||||
otro_pajaro = Pajaro()
|
||||
|
||||
# Mostrando en pantalla nos mostrará que se guarda
|
||||
# en otro espacio de memoria
|
||||
print(otro_pajaro)
|
||||
34
python-total/dia_07/02_atributos.py
Normal file
34
python-total/dia_07/02_atributos.py
Normal file
@@ -0,0 +1,34 @@
|
||||
"""
|
||||
Atributos
|
||||
"""
|
||||
|
||||
|
||||
# Sintaxis:
|
||||
# def tipo/método (tipo_parámetro, parámetro):
|
||||
# tipo_parámetro.atributo = parámetro
|
||||
|
||||
# Creamos la clase
|
||||
|
||||
|
||||
class Pajaro:
|
||||
# Atributos de clase
|
||||
# Para valores comunes entre todos los objetos de la clase
|
||||
alas = True
|
||||
|
||||
# Atributos de instancia
|
||||
# Constructor de la clase pajaro --> Con el método__init__
|
||||
def __init__(self, color, especie): # En el paréntesis pasamos dos parámetros
|
||||
self.color = color # Le damos la instancia que vamos a crear con el atributo
|
||||
self.especie = especie
|
||||
|
||||
|
||||
# Creamos la instancia. Si dejamos vacios los paréntesis dará error.
|
||||
# por que pajaro exige un argumento, debe ser un valor para el atributo.
|
||||
mi_pajaro = Pajaro('negro', 'Tucan')
|
||||
|
||||
# Con el punto podremos ver el atributo entre otras propiedades
|
||||
print(
|
||||
f'Mi pajaro es de color {mi_pajaro.color} y de la especie {mi_pajaro.especie}')
|
||||
|
||||
# Los atributos de clases se pueden dar a la clase y a la instancia:
|
||||
print(Pajaro.alas, mi_pajaro.alas)
|
||||
61
python-total/dia_07/03_metodos.py
Normal file
61
python-total/dia_07/03_metodos.py
Normal file
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
Métodos
|
||||
"""
|
||||
|
||||
# self es un argumento obligatorio
|
||||
# hace referencia a cada instancia de la clase
|
||||
|
||||
|
||||
class Pajaro:
|
||||
|
||||
alas = True
|
||||
|
||||
def __init__(self, color, especie):
|
||||
self.color = color
|
||||
self.especie = especie
|
||||
|
||||
# Cuando se hace referencia a un atributo se debe poner self por delante
|
||||
# para que se asocie correctamente
|
||||
def piar(self):
|
||||
print('pio, mi color es {}'.format(self.color))
|
||||
|
||||
def volar(self, metros):
|
||||
print(f'El pajaro ha volado {metros} metros')
|
||||
|
||||
|
||||
piolin = Pajaro('amarillo', 'canario')
|
||||
|
||||
piolin.piar()
|
||||
|
||||
piolin.volar(50)
|
||||
|
||||
# Otro ejemplo
|
||||
|
||||
|
||||
class Persona:
|
||||
especie = "humano"
|
||||
|
||||
def __init__(self, nombre, edad):
|
||||
self.nombre = nombre
|
||||
self.edad = edad
|
||||
|
||||
def saludar(self):
|
||||
print(f'Hola, mi nombre es {self.nombre}')
|
||||
|
||||
def cumplir_anios(self, estado_humor):
|
||||
print(f'Cumplir {self.edad + 1} años me pone {estado_humor}')
|
||||
|
||||
|
||||
juan = Persona("Juan", 37)
|
||||
juan.saludar()
|
||||
juan.cumplir_anios("feliz")
|
||||
|
||||
|
||||
class Alarma:
|
||||
def postergar(self, cantidad_minutos):
|
||||
print(f"La alarma ha sido pospuesta {cantidad_minutos} minutos")
|
||||
|
||||
|
||||
sonar = Alarma()
|
||||
|
||||
sonar.postergar(10)
|
||||
90
python-total/dia_07/04_tipos_metodos.py
Normal file
90
python-total/dia_07/04_tipos_metodos.py
Normal file
@@ -0,0 +1,90 @@
|
||||
"""
|
||||
Tipos de métodos
|
||||
|
||||
# Decoradores:
|
||||
- Métodos de instancia:
|
||||
|
||||
def mi_metodo(self):
|
||||
print('algo')
|
||||
mi_metodo
|
||||
|
||||
- Acceden y modifican atributos del objeto.
|
||||
- Acceden a otro métodos.
|
||||
- Pueden modificar el estado de la clase.
|
||||
|
||||
- Métodos de clase @classmethod:
|
||||
|
||||
def mi_metodo(cls):
|
||||
print('algo')
|
||||
|
||||
- No están asociados a las instancias de la clase, sino a la clase en si misma
|
||||
- Pueden ser llamados desde la instancia y desde la clase
|
||||
- No pueden acceder a los atributos de instancia pero si a los de la clase
|
||||
|
||||
- Métodos estáticos @staticmethod:
|
||||
|
||||
@staticmethod
|
||||
def mi_metodo():
|
||||
print('algo')
|
||||
|
||||
- No acepta como parámetro ni self ni cls
|
||||
- No pueden modificar ni el estado de la clase ni de la instancia
|
||||
- Pueden aceptar parámetros de entrada
|
||||
"""
|
||||
|
||||
|
||||
class Pajaro:
|
||||
|
||||
alas = True
|
||||
|
||||
def __init__(self, color, especie):
|
||||
self.color = color
|
||||
self.especie = especie
|
||||
|
||||
# Cuando se hace referencia a un atributo se debe poner self por delante
|
||||
# para que se asocie correctamente
|
||||
def piar(self):
|
||||
print('pio, mi color es {}'.format(self.color))
|
||||
|
||||
def volar(self, metros):
|
||||
print(f'El pajaro ha volado {metros} metros')
|
||||
# De instancia - Acceden a otro métodos
|
||||
self.piar()
|
||||
|
||||
# De instancia - Acceden y modifican atributos del objeto
|
||||
def pintar_negro(self):
|
||||
self.color = 'negro'
|
||||
print(f'Ahora el pájaro es {self.color}')
|
||||
|
||||
# Métodos de clase. Necesita el decorador
|
||||
@classmethod
|
||||
def poner_huevos(cls, cantidad):
|
||||
print(f'Puso {cantidad} huevos')
|
||||
# No pueden acceder a los métodos de instancia
|
||||
# print(f'Es de color {self.color}')
|
||||
# Pero si que puede acceder a los métodos de clase
|
||||
cls.alas = False
|
||||
print(Pajaro.alas)
|
||||
|
||||
@staticmethod
|
||||
def mirar():
|
||||
# No accede ni a métodos de instancia ni de clase
|
||||
# self.color = 'rojo'
|
||||
# cls.alas = 2
|
||||
# Así te aseguras que no se modifiquen los métodos
|
||||
print('El pajaro mira')
|
||||
|
||||
|
||||
Pajaro.poner_huevos(3)
|
||||
|
||||
Pajaro.mirar()
|
||||
|
||||
piolin = Pajaro('amarillo', 'canario')
|
||||
|
||||
piolin.pintar_negro()
|
||||
|
||||
piolin.volar(45)
|
||||
|
||||
# De instancia - Pueden modificar el estado de la clase
|
||||
piolin.alas = False
|
||||
print(piolin.alas)
|
||||
57
python-total/dia_07/05_herencia.py
Normal file
57
python-total/dia_07/05_herencia.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""
|
||||
Herencia
|
||||
|
||||
D ONT'T
|
||||
R EPEAT
|
||||
Y OURSELF
|
||||
|
||||
No repitas el código!
|
||||
|
||||
"""
|
||||
|
||||
# Ejemplo
|
||||
|
||||
|
||||
class Animal:
|
||||
|
||||
# Atributos
|
||||
def __init__(self, edad, color):
|
||||
self.edad = edad
|
||||
self.color = color
|
||||
|
||||
# Métodos
|
||||
def nacer(self):
|
||||
print("Este animal ha nacido")
|
||||
|
||||
def morir(self):
|
||||
pass
|
||||
|
||||
def respirar(self):
|
||||
pass
|
||||
|
||||
|
||||
class Pajaro(Animal):
|
||||
pass
|
||||
|
||||
|
||||
class Mamifero(Animal):
|
||||
pass
|
||||
|
||||
|
||||
class Insecto(Animal):
|
||||
pass
|
||||
|
||||
|
||||
# Podemos ver de donde vienen las clase con __bases__
|
||||
print(Pajaro.__bases__)
|
||||
|
||||
# Podemos ver las subclases de una clase
|
||||
print(Animal.__subclasses__())
|
||||
|
||||
# Creamos una instancia de pájaro y debe tener los atributos de Animal
|
||||
piolin = Pajaro(2, "negro")
|
||||
|
||||
print(f'Piolin tiene {piolin.edad} años y es de color {piolin.color}')
|
||||
|
||||
# La instancia de Pájaro ha heredado los métodos de Animal
|
||||
piolin.nacer()
|
||||
85
python-total/dia_07/06_herencia_extendida.py
Normal file
85
python-total/dia_07/06_herencia_extendida.py
Normal file
@@ -0,0 +1,85 @@
|
||||
"""
|
||||
Herencia Extendidad
|
||||
|
||||
D ONT'T
|
||||
R EPEAT
|
||||
Y OURSELF
|
||||
|
||||
No repitas el código!
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class Animal:
|
||||
|
||||
def __init__(self, edad, color):
|
||||
self.edad = edad
|
||||
self.color = color
|
||||
|
||||
def nacer(self):
|
||||
print("Este animal ha nacido")
|
||||
|
||||
def hablar(self):
|
||||
print("Este animal emite un sonido")
|
||||
|
||||
|
||||
class Pajaro(Animal):
|
||||
|
||||
def __init__(self, edad, color, altura_vuelo):
|
||||
super().__init__(edad, color)
|
||||
self.altura_vuelo = altura_vuelo
|
||||
|
||||
def hablar(self):
|
||||
print("pio")
|
||||
|
||||
def volar(self, metros):
|
||||
print(f'El pájaro vuela {metros} metros')
|
||||
|
||||
|
||||
# Declarar variables
|
||||
piolin = Pajaro(3, 'amarillo', 500)
|
||||
|
||||
mi_animal = Animal(19, 'negro')
|
||||
|
||||
piolin.hablar()
|
||||
|
||||
piolin.volar(100)
|
||||
|
||||
mi_animal.hablar()
|
||||
|
||||
# otro ejemplo
|
||||
|
||||
|
||||
class Padre:
|
||||
def hablar(self):
|
||||
print('Hola')
|
||||
|
||||
|
||||
class Madre:
|
||||
def reir(self):
|
||||
print('ja ja ja')
|
||||
|
||||
def hablar(self):
|
||||
print('Que tal')
|
||||
|
||||
|
||||
class Hijo(Padre, Madre):
|
||||
pass
|
||||
|
||||
|
||||
class Nieto(Hijo):
|
||||
pass
|
||||
|
||||
# Nieto es capaz de hablar y reir aunque no herede directamente
|
||||
|
||||
|
||||
mi_nieto = Nieto()
|
||||
|
||||
mi_nieto.reir()
|
||||
|
||||
# El método que hereda es el primero que se encuentra en sus atributos
|
||||
mi_nieto.hablar()
|
||||
|
||||
# Podemos ver el orden de las herencias con __mro__
|
||||
|
||||
print(Nieto.__mro__)
|
||||
55
python-total/dia_07/07_polimorfismo.py
Normal file
55
python-total/dia_07/07_polimorfismo.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
Polimorfismo
|
||||
|
||||
Distintas clases pueden tener el mismo método
|
||||
pero se aplicará de manera distinta para cada clase
|
||||
"""
|
||||
|
||||
|
||||
class Vaca:
|
||||
|
||||
def __init__(self, nombre):
|
||||
self.nombre = nombre
|
||||
|
||||
def hablar(self):
|
||||
print(self.nombre + " dice muuu")
|
||||
|
||||
|
||||
class Oveja:
|
||||
|
||||
def __init__(self, nombre):
|
||||
self.nombre = nombre
|
||||
|
||||
def hablar(self):
|
||||
print(self.nombre + " dice beee")
|
||||
|
||||
|
||||
vaca1 = Vaca('Aurora')
|
||||
oveja1 = Oveja('Jacinta')
|
||||
|
||||
# Dos classes distintas con el mismo método
|
||||
# que dicen cosas distintas
|
||||
vaca1.hablar()
|
||||
oveja1.hablar()
|
||||
|
||||
|
||||
print()
|
||||
# Ahora en una lista para iterar
|
||||
# Cuidao! Es genial!
|
||||
animales = [vaca1, oveja1]
|
||||
|
||||
for animal in animales:
|
||||
animal.hablar()
|
||||
|
||||
print()
|
||||
# También en funciones.
|
||||
# Impresionante!
|
||||
|
||||
|
||||
def animal_habla(animal):
|
||||
|
||||
animal.hablar()
|
||||
|
||||
|
||||
animal_habla(vaca1)
|
||||
animal_habla(oveja1)
|
||||
66
python-total/dia_07/08_metodos_especiales.py
Normal file
66
python-total/dia_07/08_metodos_especiales.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
Métodos especiales
|
||||
|
||||
Se han visto:
|
||||
__init__
|
||||
__mro__
|
||||
__bases__
|
||||
__subclasses__
|
||||
|
||||
Vamos a ver:
|
||||
__str__
|
||||
__len__
|
||||
"""
|
||||
|
||||
mi_lista = [1, 1, 1, 1, 1, 1, 1, 1]
|
||||
|
||||
# print(len(mi_lista))
|
||||
|
||||
|
||||
class Objeto:
|
||||
pass
|
||||
|
||||
|
||||
mi_objeto = Objeto()
|
||||
# No se puede aplicar len
|
||||
# print(len(mi_objeto))
|
||||
|
||||
# Tampoco podemos ver el objeto
|
||||
# print(mi_objeto)
|
||||
|
||||
# Otro ejemplo
|
||||
|
||||
|
||||
class CD:
|
||||
def __init__(self, autor, titulo, canciones):
|
||||
self.autor = autor
|
||||
self.titulo = titulo
|
||||
self.canciones = canciones
|
||||
|
||||
# Vamos a modif el comportamiento del método especial __str__
|
||||
# cada vez que se llame para mostrar lo que se quiera
|
||||
def __str__(self):
|
||||
return f'Albun: {self.titulo} de {self.autor}'
|
||||
|
||||
# Comportamiento de len
|
||||
def __len__(self):
|
||||
return self.canciones
|
||||
|
||||
# Podemos añadir un mensaje cuando usemos la función del
|
||||
def __del__(self):
|
||||
print("Se ha eliminado el cd")
|
||||
|
||||
|
||||
mi_cd = CD('Pink Floyd', 'The Wall', 24)
|
||||
|
||||
# Ahora sí que veremos el return modificado
|
||||
print(mi_cd)
|
||||
|
||||
# También len, hemos modificado su uso para
|
||||
# que muestre el número de canciones
|
||||
print(len(mi_cd))
|
||||
|
||||
# Podemos eliminar con la función del
|
||||
del mi_cd
|
||||
# Si lo intentamos imprimir nos dirá que no existe
|
||||
# print(mi_cd)
|
||||
167
python-total/dia_07/09_programa07.py
Normal file
167
python-total/dia_07/09_programa07.py
Normal file
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
Programa día 7 - Cuenta bancaria
|
||||
|
||||
ESTAFA BANK
|
||||
"""
|
||||
import os
|
||||
|
||||
|
||||
""" Variables """
|
||||
limpiar = 'clear'
|
||||
sleep = 'sleep 2'
|
||||
|
||||
""" Clases """
|
||||
|
||||
|
||||
class Persona:
|
||||
|
||||
# Atributos: nombre y apellido
|
||||
def __init__(self, nombre, apellido):
|
||||
self.nombre = nombre
|
||||
self.apellido = apellido
|
||||
|
||||
|
||||
class Cliente(Persona):
|
||||
|
||||
# atributos propios: número de cuenta y balance
|
||||
# es decir, el saldo que tiene en su cuenta bancaria.
|
||||
def __init__(self, nombre, apellido, num_cuenta, balance):
|
||||
super().__init__(nombre, apellido)
|
||||
self.num_cuenta = num_cuenta
|
||||
self.balance = float(round(balance, 2))
|
||||
|
||||
# tres métodos
|
||||
# # método especial que permite que podamos imprimir a nuestro cliente
|
||||
def __str__(self):
|
||||
return f'*** CLIENTE ESTAFA BANK ***\n\n\tCliente: \t{self.nombre} {self.apellido}\n\tNº Cuenta: \t{self.num_cuenta}\n\tBalance: \t{self.balance} pesos'
|
||||
|
||||
# # Método Depositar que permita decidir cuánto dinero quiere agregar a su cuenta
|
||||
|
||||
def depositar(self, cantidad_ingreso):
|
||||
self.balance += cantidad_ingreso
|
||||
self.balance = round(self.balance, 2)
|
||||
print(
|
||||
f'\nHa ingresado {cantidad_ingreso} Pesos.\n')
|
||||
|
||||
# # Método llamado Retirar que permita decidir cuánto dinero quiere sacar de su cuenta
|
||||
|
||||
def retirar(self, cantidad_a_retirar):
|
||||
if (self.balance - cantidad_a_retirar) < 0:
|
||||
print(
|
||||
f'\nDisculpa, no tienes tanto dinero.\nBalance: {self.balance} pesos')
|
||||
else:
|
||||
self.balance -= cantidad_a_retirar
|
||||
self.balance = round(self.balance, 2)
|
||||
print(
|
||||
f'\nHa retirado {cantidad_a_retirar} Pesos.\n')
|
||||
|
||||
|
||||
""" Funciones """
|
||||
|
||||
|
||||
def clearConsole():
|
||||
# Función limpiar consola
|
||||
os.system(limpiar)
|
||||
|
||||
|
||||
def bienvenida():
|
||||
|
||||
clearConsole()
|
||||
|
||||
# bienvenida al usuario
|
||||
print(
|
||||
'\n',
|
||||
'#' * 39,
|
||||
'\n # Bienvenid@ a tu cuenta bancaria #\n',
|
||||
'#' * 39)
|
||||
|
||||
os.system(sleep)
|
||||
|
||||
clearConsole()
|
||||
|
||||
# Iniciar programa pidiendo datos del cliente
|
||||
crear_cliente()
|
||||
|
||||
# Pedir operaciones a realizar - PROGRAMA
|
||||
operaciones()
|
||||
|
||||
|
||||
def despedida():
|
||||
clearConsole()
|
||||
|
||||
print('Gracias por usar los servicios de ESTAFA BANK, su banco sincero.\n\n¡Ciao!\n')
|
||||
|
||||
|
||||
def crear_cliente():
|
||||
|
||||
nombre_cliente = input("Dime tu nombre: ")
|
||||
apellido_cliente = input("Dime tu/s apelludo/s: ")
|
||||
|
||||
global cliente1
|
||||
|
||||
cliente1 = Cliente(
|
||||
nombre_cliente,
|
||||
apellido_cliente,
|
||||
'324789563417896324',
|
||||
0)
|
||||
|
||||
|
||||
def operaciones():
|
||||
|
||||
# PROGRAMA
|
||||
# Pedir al usuario que elija si quiere hacer depósitos o retiros.
|
||||
|
||||
operacion = ''
|
||||
while operacion.lower() != 's':
|
||||
print(
|
||||
f'\n',
|
||||
cliente1,
|
||||
'\n\n Indicar la operación a realizar:\n',
|
||||
'\n\t- i\t-->\tIngresar'
|
||||
'\n\t- r\t-->\tRetirar'
|
||||
'\n\t- s\t-->\tSalir\n')
|
||||
|
||||
operacion = input()
|
||||
|
||||
operacion = operacion.lower()
|
||||
|
||||
if operacion == "i":
|
||||
cantidad_a_ingresar = preguntar_cantidad('ingresar')
|
||||
cliente1.depositar(cantidad_a_ingresar)
|
||||
continue
|
||||
|
||||
elif operacion == "r":
|
||||
cantidad_a_retirar = preguntar_cantidad('retirar')
|
||||
cliente1.retirar(cantidad_a_retirar)
|
||||
continue
|
||||
|
||||
elif operacion == "s":
|
||||
break
|
||||
|
||||
else:
|
||||
clearConsole()
|
||||
print('Disculpa, ingresa un valor valido\n')
|
||||
continue
|
||||
despedida()
|
||||
|
||||
|
||||
def preguntar_cantidad(ope):
|
||||
|
||||
clearConsole()
|
||||
|
||||
print(
|
||||
f'\nSu balance actual es de {cliente1.balance} Pesos.\n\n',
|
||||
f'¿Qué cantidad quiere {ope}?')
|
||||
|
||||
cantidad = input()
|
||||
|
||||
cantidad = round(float(cantidad), 2)
|
||||
|
||||
return cantidad
|
||||
|
||||
|
||||
""" Programa - Se inicia a través de la función de bienvenida """
|
||||
|
||||
|
||||
# Bienvenida e iniciar programa
|
||||
bienvenida()
|
||||
237
python-total/dia_07/README.md
Normal file
237
python-total/dia_07/README.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# Día 7 - Programa una cuenta bancaria
|
||||
Principios de la programación orientada a objetos (POO):
|
||||
- Herencia
|
||||
- Polimorfismo
|
||||
- Cohesión
|
||||
- Abstracción
|
||||
- Acoplamiento
|
||||
- Encapsulamiento
|
||||
## Índice
|
||||
- [Día 7 - Programa una cuenta bancaria](#día-7---programa-una-cuenta-bancaria)
|
||||
- [Índice](#índice)
|
||||
- [7.1. - Clases](#71---clases)
|
||||
- [7.2. - Atributos](#72---atributos)
|
||||
- [7.3. - Métodos](#73---métodos)
|
||||
- [7.4. - Tipos de métodos](#74---tipos-de-métodos)
|
||||
- [7.5. - Herencia](#75---herencia)
|
||||
- [7.6. - Herencia extendida](#76---herencia-extendida)
|
||||
- [7.7. - Polimorfismo](#77---polimorfismo)
|
||||
- [7.8. - Pilares de la Programación Orientada a Objetos](#78---pilares-de-la-programación-orientada-a-objetos)
|
||||
- [7.9. - Métodos especiales](#79---métodos-especiales)
|
||||
- [7.10. - Proyecto del Día 7](#710---proyecto-del-día-7)
|
||||
- [Ficheros y documentación](#ficheros-y-documentación)
|
||||
|
||||
## 7.1. - Clases
|
||||
|
||||
Python es un lenguaje de Programación Orientado a Objetos (POO). Como tal, utiliza y manipula objetos, a través de sus métodos y propiedades. Las clases son las herramientas que nos permiten crear objetos, que "empaquetan" datos y funcionalidad juntos.
|
||||
Podemos pensar a las clases como el "plano" o "plantilla" a partir del cual podemos crear objetos individuales, con propiedades y métodos asociados:
|
||||
|
||||

|
||||
|
||||
Las clases se definen con la palabra reservada `class`, seguida del nombre de la clase, y dos puntos. Por convención, los nombres de las clases se escriben con la primera letra en mayúscula, y el resto en minúsculas. Por ejemplo, `MiClase`.
|
||||
|
||||
## 7.2. - Atributos
|
||||
|
||||
Los atributos son variables que pertenecen a la clase. Existen **atributos de clase** (compartidos por todas las instancias de la clase), **y de instancia** (que son distintos en cada instancia de la clase).
|
||||
|
||||

|
||||
|
||||
Todas las clases tienen una función que se ejecuta al instanciarla, llamada `__init__()`, y que se utiliza para asignar valores a las propiedades del objeto que está siendo creado. self: representa a la instancia del objeto que se va a crear.
|
||||
|
||||
## 7.3. - Métodos
|
||||
|
||||
Los objetos creados a partir de clases también contienen métodos. Dicho de otra manera, los métodos son funciones que pertenecen al objeto.
|
||||
```python
|
||||
class Persona:
|
||||
especie = "humano"
|
||||
def __init__(self, nombre, edad):
|
||||
self.nombre = nombre
|
||||
self.edad = edad
|
||||
def saludar(self):
|
||||
print(f'Hola, mi nombre es {self.nombre}')
|
||||
def cumplir_anios(self, estado_humor):
|
||||
print(f'Cumplir {self.edad + 1} años me pone {estado_humor}')
|
||||
|
||||
juan = Persona("Juan", 37)
|
||||
|
||||
juan.saludar()
|
||||
|
||||
juan.cumplir_anios("feliz")
|
||||
```
|
||||
|
||||
Hola, mi nombre es Juan
|
||||
Cumplir 38 años me pone feliz
|
||||
|
||||
Cada vez que un atributo del objeto sea invocado (por ejemplo, en una función), debe incluirse self, que refiere a la instancia en cuestión, indicando la pertenencia de este atributo.
|
||||
|
||||
## 7.4. - Tipos de métodos
|
||||
|
||||
Los métodos estáticos y de clase anteponen un decorador específico, que indica a Python el tipo de método que se estará definiendo
|
||||
|
||||
| | | @classmethod | @staticmethod |
|
||||
| -------------------------------------------: | :------------------: | :--------------: | :---------------: |
|
||||
| | Métodos de instancia | Métodos de clase | Métodos estáticos |
|
||||
| Acceso a métodos y atrbitutos de la clase | Sí | Sí | No |
|
||||
| Requiere una instancia | Sí | No | No |
|
||||
| Acceso a métodos y atributos de la instancia | Sí | No | No |
|
||||
|
||||
|
||||
Así como los métodos de instancia requieren del parámetro **self** para acceder a dicha instancia, los métodos de clase requieren del parámetro **cls** para acceder a los atributos de clase. Los métodos estáticos, dado que no pueden acceder a la instancia ni a la clase, no indican un parámetro semejante.
|
||||
|
||||
Resumen sobre Decoradores:
|
||||
- **Métodos de instancia**:
|
||||
```python
|
||||
def mi_metodo(self):
|
||||
print('algo')
|
||||
mi_metodo
|
||||
```
|
||||
- Acceden y modifican atributos del objeto.
|
||||
- Acceden a otro métodos.
|
||||
- Pueden modificar el estado de la clase.
|
||||
|
||||
- **Métodos de clase** - *@classmethod*:
|
||||
```python
|
||||
def mi_metodo(cls):
|
||||
print('algo')
|
||||
```
|
||||
|
||||
- No están asociados a las instancias de la clase, sino a la clase en si misma
|
||||
- Pueden ser llamados desde la instancia y desde la clase
|
||||
- No pueden acceder a los atributos de instancia pero si a los de la clase
|
||||
|
||||
- **Métodos estáticos** - *@staticmethod*:
|
||||
```python
|
||||
def mi_metodo():
|
||||
print('algo')
|
||||
```
|
||||
|
||||
- No acepta como parámetro ni self ni cls
|
||||
- No pueden modificar ni el estado de la clase ni de la instancia
|
||||
- Pueden aceptar parámetros de entrada
|
||||
|
||||
|
||||
|
||||
## 7.5. - Herencia
|
||||
|
||||
La herencia es el proceso mediante el cual una clase puede tomar métodos y atributos de una clase superior, evitando repetición del código cuando varias clases tienen atributos o métodos en común.
|
||||
Es posible crear una clase "hija" con tan solo pasar como parámetro la clase de la que queremos heredar:
|
||||
```python
|
||||
class Personaje:
|
||||
def __init__(self, nombre, herramienta):
|
||||
self.nombre = nombre
|
||||
self.arma = arma
|
||||
|
||||
class Mago(Personaje):
|
||||
pass
|
||||
hechicero = Mago("Merlín", "caldero")
|
||||
```
|
||||
|
||||
Una clase "hija" puede sobreescribir los métodos o atributos, así como definir nuevos, que sean específicos para esta clase.
|
||||
|
||||
## 7.6. - Herencia extendida
|
||||
|
||||
Las clases "hijas" que heredan de las clases superiores, pueden crear nuevos métodos o sobrescribir los de la clase "padre". Asimismo, una clase "hija" puede heredar de una o más clases, y a su vez transmitir herencia a clases "nietas".
|
||||
|
||||
Si varias superclases tienen los mismos atributos o métodos, la subclase sólo podrá heredar de una de ellas. En estos casos Python dará prioridad a la clase que se encuentre más a la izquierda.
|
||||
|
||||
Del mismo modo, si un mismo método se hereda por parte de la clase "padre", e "hija", la clase "nieta" tendrá preferencia por aquella más próxima ascendente (siguiendo nuestro esquema, la tomará de la clase "hija").
|
||||
|
||||

|
||||
|
||||
**`Clase.__mro__`** - devuelve el orden de resolución de métodos
|
||||
|
||||
**`super().__init__(arg1, arg2,...)`** - hereda atributos de las superclases de manera compacta
|
||||
|
||||
## 7.7. - Polimorfismo
|
||||
|
||||
El polimorfismo es el pilar de la POO mediante el cual un mismo método puede comportarse de diferentes maneras según el objeto sobre el cual esté actuando, en función de cómo dicho método ha sido creado para la clase en particular.
|
||||
|
||||
El método len( ) funciona en distintos tipos de objetos: listas, tuplas, strings, entre otros. Esto se debe a que para Python, lo importante no son los tipos de objetos, sino lo que pueden hacer: sus métodos.
|
||||
```python
|
||||
class Perro:
|
||||
def hablar(self):
|
||||
print("Guau!")
|
||||
|
||||
class Gato:
|
||||
def hablar(self):
|
||||
print("Miau!")
|
||||
|
||||
hachiko = Perro()
|
||||
|
||||
garfield = Gato()
|
||||
|
||||
for animal in [hachiko, garfield]:
|
||||
animal.hablar()
|
||||
```
|
||||
|
||||
Guau!
|
||||
Miau!
|
||||
|
||||
## 7.8. - Pilares de la Programación Orientada a Objetos
|
||||
Se ha visto Herencia y Polimorfismo en las prácticas anteriores. Información conceptual del resto:
|
||||
- Cohesión: https://escueladirecta-blog.blogspot.com/2021/09/cohesion-pilares-de-la-programacion.html
|
||||
- Acoplamiento: https://escueladirecta-blog.blogspot.com/2021/10/acoplamiento-pilares-de-la-programacion.html
|
||||
- Abstracción: https://escueladirecta-blog.blogspot.com/2021/10/abstraccion-pilares-de-la-programacion.html
|
||||
- Encapsulamiento: https://escueladirecta-blog.blogspot.com/2021/10/encapsulamiento-pilares-de-la.html
|
||||
|
||||
## 7.9. - Métodos especiales
|
||||
|
||||
Puedes encontrarlos con el nombre de métodos mágicos o dunder methods (del inglés: dunder = double underscore, o doble guión bajo). Pueden ayudarnos a sobrescribir métodos incorporados de Python sobre nuestras clases para controlar el resultado devuelto.
|
||||
```python
|
||||
class Libro:
|
||||
def __init__(self, autor, titulo, cant_paginas):
|
||||
self.autor = autor
|
||||
self.titulo = titulo
|
||||
self.cant_paginas = cant_paginas
|
||||
|
||||
def __str__(self):
|
||||
return f'Título: "{self.titulo}", escrito por {self.autor}'
|
||||
|
||||
def __len__(self):
|
||||
return self.cant_paginas
|
||||
|
||||
libro1 = Libro("Stephen King", "It", 1032)
|
||||
|
||||
print(str(libro1))
|
||||
|
||||
print(len(libro1))
|
||||
```
|
||||
|
||||
Título: "It", escrito por Stephen King
|
||||
1032
|
||||
|
||||
## 7.10. - Proyecto del Día 7
|
||||
|
||||
Crear un código que le permita a una persona realizar operaciones en su cuenta bancaria. No te asustes que la consigna va a estar bien definida para que puedas hacerlo en poco tiempo.
|
||||
|
||||
Primero vas a crear una clase llamada Persona, y Persona va a tener solo dos atributos: nombre y apellido. Luego, vas a crear una segunda clase llamada Cliente, y Cliente va a heredar de Persona, porque los clientes son personas, por lo que el Cliente va a heredar entonces los atributos de Persona, pero también va a tener atributos propios, como número de cuenta y balance, es decir, el saldo que tiene en su cuenta bancaria.
|
||||
|
||||
Pero eso no es todo: Cliente también va a tener tres métodos. El primero va a ser uno de los métodos especiales y es el que permite que podamos imprimir a nuestro cliente. Este método va a permitir que cuando el código pida imprimir Cliente, se muestren todos sus datos, incluyendo el balance de su cuenta. Luego, un método llamado Depositar, que le va a permitir decidir cuánto dinero quiere agregar a su cuenta. Y finalmente, un tercer método llamado Retirar, que le permita decidir cuánto dinero quiere sacar de su cuenta.
|
||||
|
||||
Una vez que hayas creado estas dos clases, tienes que crear el código para que tu programa se desarrolle, pidiéndole al usuario que elija si quiere hacer depósitos o retiros. El usuario puede hacer tantas operaciones como quiera hasta que decida salir del programa. Por lo tanto, nuestro código tiene que ir llevando la cuenta de cuánto dinero hay en el balance, y debes procurar, por supuesto, que el cliente nunca pueda retirar más dinero del que posee. Esto no está permitido.
|
||||
|
||||
Recuerda que ahora que sabes crear clases y objetos que son estables y que retienen información, no necesitas crear funciones que devuelvan el balance, ya que la instancia de cliente puede saber constantemente cuál es su saldo debido a que puede hacer sus operaciones llamando directamente a este atributo y no a una variable separada.
|
||||
|
||||
Para que tu programa funcione, puedes organizar tu código como quieras, hay muchas formas de hacerlo, pero mi recomendación es que básicamente, luego de crear las dos clases que te he mencionado, crees dos funciones una que se encarguen de crear al cliente pidiéndole al usuario toda la información necesaria y devolviendo, a través del return, un objeto cliente ya creado.
|
||||
|
||||
La otra función (que puede llamarse inicio, o algo por el estilo), es la función que organiza la ejecución de todo el código: primero llama a la función “crear cliente” y luego se encarga de mantener al usuario en un loop que le pregunte todo el tiempo si quiere depositar, retirar o salir del programa y demostrarle el balance, cada vez que haga una modificación.
|
||||
|
||||
Para que este programa no se te haga súper largo o complejo, te propongo que esta vez no nos fijemos tanto en los controles, para ver si el usuario ha puesto opciones permitidas o no, si ha puesto números o no, si ha puesto mayúsculas o minúsculas, y creemos el código confiando en que el usuario va a ingresar siempre información apropiada. Por supuesto que si tú prefieres incluir todos esos controles, está genial.
|
||||
|
||||
## Ficheros y documentación
|
||||
|
||||
- [01_clases.py](01_clases.py)
|
||||
- [02_atributos.py](02_atributos.py)
|
||||
- [03_metodos.py](03_metodos.py)
|
||||
- [04_tipos_metodos.py](04_tipos_metodos.py)
|
||||
- [05_herencia.py](05_herencia.py)
|
||||
- [06_herencia_extendida.py](06_herencia_extendida.py)
|
||||
- [07_polimorfismo.py](07_polimorfismo.py)
|
||||
- [08_metodos_especiales.py](08_metodos_especiales.py)
|
||||
- [09_programa07.py](09_programa07.py)
|
||||
|
||||
[Documentación del día](../doc_curso/07_cuenta_bancaria/)
|
||||
|
||||
---
|
||||
|
||||
Enlaces a todos los días: [dia 1 - creador de nombres](../dia_01/README.md) / [dia 2 - calculador de comisiones](../dia_02/README.md) / [dia 3 - analizador de texto](../dia_03/README.md) / [dia 4 - juego "adivina el número"](../dia_04/README.md) / [dia 5 - juego "El ahorcado"](../dia_05/README.md) / [dia 6 - recetario](../dia_06/README.md) / [dia 7 - cuenta bancaria](../dia_07/README.md) / [dia 8 - consola de turnos](../dia_08/README.md) / [dia 9 - buscador de números de serie](../dia_09/README.md) / [dia 10 - juego "Invasión espacial"](../dia_10/README.md) / [dia 11 - web scraping](../dia_11/README.md) / [dia 12 - gestor de restaurantes](../dia_12/README.md) / [dia 13 - asistente de voz](../dia_13/README.md) / [dia 14 - controlador de asistencia](../dia_14/README.md) / [dia 15 - machine learning](../dia_15/README.md) / [dia 16 - aplicación web de tareas pendientes](../dia_16/README.md)
|
||||
Reference in New Issue
Block a user