Python y JS 2021 - Clase 4 - POO
Python y JS 2021 - Clase 4 - POO
try:
numero1 = int(input("Ingrese primer numero: "))
numero2 = int(input("Ingrese segundo numero: "))
except ValueError:
print("Error: Valor no valido. ")
sys.exit(1)
try:
resultado = numero1 / numero2
except ZeroDivisionError:
print("Error: No se puede dividir por 0.")
#Salir del programa
sys.exit(1)
try:
print("Hola")
except:
print("Algo salió mal")
else:
print("Nada salió mal")
Tratamiento de Excepciones
finally
➢ El bloque finally, si se especifica, se ejecutará independientemente de si
el bloque try genera un error o no.
try:
print("Hola")
except:
print("Algo salió mal")
finally:
print("El try y except finalizó")
Tratamiento de Excepciones
finally
➢ Ejemplo intentando abrir y escribir a un archivo que es de solo lectura:
try:
f = open("arhivoejemplo.txt")
f.write("Linea de prueba dentro del archivo.")
except:
print("Algo pasó al intentar abrir el archivo.")
finally:
f.close()
Programación Orientada a Objetos
¿Qué es Programación Orientada a Objetos?
Enlaces de interés:
➢ Wikipedia: https://es.wikipedia.org/wiki/Programación_orientada_a_objetos
➢ MIT: https://ocw.mit.edu/courses/electrical-engineering-and-computer-
science/6-01sc-introduction-to-electrical-engineering-and-computer-science-i-
spring-2011/unit-1-software-engineering/object-oriented-programming/
➢ Brown University: http://cs.brown.edu/courses/cs015/
➢ Princeton: https://introcs.cs.princeton.edu/java/30oop/
Objetos
• Una entidad o “cosa” en tu programa, usualmente un sustantivo.
• Un ejemplo de un objeto sería una persona en particular.
Propiedades Comportamiento
❑ Nombre ❑ Caminar
❑ Edad ❑ Hablar
❑ Dirección ❑ Respirar
Programación Orientada a Objetos
CLASE:
Vehículo OBJETO:
Automóvil
Métodos:
Atributos/Propiedades: inyectar_combustible
marca frenar
modelo cambiar_marcha
color
Clases
• Las clases se usan para crear objetos
• Podemos crear muchos objetos desde una sola clase
• Las Clases definen el tipo de datos (type)
• El proceso de crear un objeto desde una clase se denomina instanciación.
class Perro:
pass
class Perro:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
Atributos de Clase
Por otro lado, los atributos de clase son atributos que tienen el mismo valor para todas las instancias.
Puedes definir atributos de clase declarándolos por fuera del método __init__()
Por ejemplo, en la misma clase Perro podemos asignar un atributo especie que sea siempre la misma en
todos:
class Perro:
#Atributo de clase
especie = “Canis lupus familiaris”
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
Los atributos de clase siempre se encontrarán directamente debajo de la definición del nombre de la
clase.
Instancias
Puedes instanciar rápidamente una clase en el interprete de Python tipeando el nombre
de la clase con paréntesis:
>>> Perro()
Esto hace que la instancia de Perro se coloque en una posición de memoria. Para poder
almacenarla en una variable hacemos lo siguiente:
>>> perro1 = Perro()
>>> perro2 = Perro()
Todo esto funciona de maravillas en nuestra clase Perro vacía. No en la que hicimos con
atributos en el constructor.
Instancias
Para instanciar el perro con atributos de nombre y edad hacemos lo siguiente:
>>> perro1 = Perro(“Firulais”, 8)
>>> perro2 = Perro(“Napoleón”, 5)
Obviando el parámetro self ya que es transparente al usuario en Python.
Puedes acceder a cada uno de los atributos de cada instancia mediante el nombre de la
variable y el nombre del atributo asociado (que hayas definido en la clase)
>>> perro1.edad
>>> perro2.nombre
>>> perro2.especie
Instancias
Imaginate que querramos cambiar la especie del perro:
>>> perro1.especie = “Felix silvestris”
Felix silvestris es el nombre de la especie asociada a los gatos. Esto hace que nuestro
perro1 sea un perro bastante extraño. Sin embargo en Python esto es valido.
Metodos de Instancias
Los métodos de instancia son funciones definidas dentro de una clase que solo pueden ser llamadas
desde la instancia de la clase. Como el método __init__(), en un método de instancia siempre el
primer parámetro será self.
class Perro:
#Atributo de clase
especie = “Canis lupus familiaris”
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
#Metodo de instancia
def descripcion(self):
return f“{self.nombre} tiene {self.edad} años”
#Otro metodo de instancia
def ladrar(self, sonido):
return f“{self.nombre} dice {sonido}”
¿Cómo usamos los métodos?
Para llamar a cada método simplemente utilizamos el operador unario (el punto) y entre paréntesis
pasamos los parámetros (que puede o no tener):
Ahora al realizar print(perro1) con el perro1 ya instanciado obviamente, obtendremos la descripción del mismo.
Funcionalidades “built in”
Cuando creas una clase, puedes pensar fácilmente que todo lo que obtienes es la clase. Sin embargo, Python agrega
funcionalidad incorporada (o built in) a tu clase. Por ejemplo, en la sección anterior, escribimos __class__ y vimos
que el atributo __class__ está integrado; vos no lo creaste.
Generalmente las funcionalidades que mas se requieren en todas las clases son incorporadas por defecto.
Si tipeamos: dir(MiInstancia)
Veremos el listado de funcionalidades incorporadas.
Puedes obtener mas ayuda con: help(‘__class__’)
¡Cuidado con las variables de clase!
Debes recordar que cualquier modificación al valor de una variable de clase es arrastrada hacia las instancias. Ej.:
class MiClase:
Saludo = “”
def DecirHola(self):
print(“Hola {0}”.format(self.Saludo))
➢ Evita las variables de clase cuando puedas porque son intrínsecamente inseguras.
➢ Siempre inicializa las variables de clase a un valor conocido en el código del constructor.
Metodos con argumento variables
A veces, necesitas crear métodos que puedan tomar un número variable de argumentos. Manejar este tipo de
situaciones es algo que Python hace bien. Estos son los dos tipos de argumentos variables que puedes crear:
✓ * args: proporciona una lista de argumentos sin nombre.
✓ ** kwargs: proporciona una lista de argumentos con nombre.
class MiClase:
def ImprimirLista1(*args):
for Count, Item in enumerate(args):
print("{0}. {1}".format(Count, Item))
def ImprimirLista2(**kwargs):
for Name, Value in kwargs.items():
print("{0} pertenece a {1}".format(Name, Value))
En el ejemplo anterior todos los objetos son instancias de Perro pero cada uno de ellos pertenece a una raza en
particular.
Ampliando funcionalidades
En el ejemplo de los perros, el método ladrar no es el mismo para cada Perro, es decir cada uno ladra de diferentes
maneras según su raza. Para determinar cada uno de los ladridos según la raza sobreescribimos el método ladrar
cuando creamos la clase según la raza.
class DogoArgentino(Perro):
def ladrar(self, sonido=“Arf”):
return (f“{self.nombre} dice {sonido}”
class BulldogFrances(Perro):
def ladrar(self, sonido=“Woof”):
return (f“{self.nombre} dice {sonido}”
Ademas puedes cambiar el valor del sonido durante la instancia simplemente llamando al método:
>>> ramon = DogoArgentino(“Ramon”, 5)
>>> ramon.ladrar(“Grrrrr”)
Ampliando funcionalidades
En el ejemplo de los perros, el método ladrar no es el mismo para cada Perro, es decir cada uno ladra de diferentes
maneras según su raza. Para determinar cada uno de los ladridos según la raza sobreescribimos el método ladrar
cuando creamos la clase según la raza.
class DogoArgentino(Perro):
def ladrar(self, sonido=“Arf”):
return (f“{self.nombre} dice {sonido}”
class BulldogFrances(Perro):
def ladrar(self, sonido=“Woof”):
return (f“{self.nombre} dice {sonido}”
Ademas puedes cambiar el valor del sonido durante la instancia simplemente llamando al método:
>>> ramon = DogoArgentino(“Ramon”, 5)
>>> ramon.ladrar(“Grrrrr”)
Facilitando la herencia
En algunos casos no es necesario que sobreescribamos todo el método de la clase padre, por ejemplo si necesitamos
solamente cambiar el parámetro del sonido del ladrido podemos hacer que la subclase llame al método de la clase
padre mediante super()
class DogoArgentino(Perro):
def ladrar(self, sonido=“Arf”):
return super().ladrar(sonido)
Cuando llamamos a super().ladrar(sonido) dentro de DogoArgentino Python busca un método llamado ladrar
dentro de la clase padre Perro y le pasa el atributo sonido.
Orden de Resolución de Métodos
Probablemente se habrán imaginado a esta altura que puede existir herencia multiple (puedes crear una clase que
herede de múltiples padres). Para ello Python utiliza un sistema denominado MRO o Multiple Resolution Order que se
encarga de organizar el orden en el que los métodos pueden heredar.
Puedes ver la MRO usando el atributo __mro__
Si definiéramos nuevamente nuestra clase perro de ésta manera Perro(AnimalTerrestre, Vertebrado), y
AnimalTerrestre(Mamifero), y Mamifero(Animal) y luego Animal() y quisiéramos averiguar el orden de MRO lo hacemos
mediante:
>>> Perro.__mro__
(<class 'Perro'>,
<class 'AnimalTerrestre'>,
<class 'Vertebrado'>,
<class 'Mamifero'>,
<class 'Animal'>,
<class 'object'>)
Operadores de Sobrecarga
class MiClase:
def __init__(self, *args):
self.Entrada = args
def __add__(self, other):
Salida = MiClase()
Salida.Entrada = self.Entrada + other.Entrada
return Salida
def __str__(self):
Salida = ""
for Item in self.Entrada:
Salida += Item
Salida += " "
return Salida
class Vuelo():
# Metodo para crear un nuevo vuelo con una capacidad dada
def __init__(self, capacidad):
self.capacidad = capacidad
self.pasajeros = []