0% encontró este documento útil (0 votos)
13 vistas42 páginas

Uso de la biblioteca random en Python

La biblioteca estándar de Python incluye módulos que proveen funcionalidades adicionales en áreas como matemáticas, estadísticas y más. Los módulos se importan usando la palabra import y se accede a sus funciones anteponiendo el nombre del módulo. También se pueden importar funciones individuales de un módulo usando from. Los programas pueden organizarse en múltiples módulos para una mejor estructuración.

Cargado por

hdurangarzon
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
13 vistas42 páginas

Uso de la biblioteca random en Python

La biblioteca estándar de Python incluye módulos que proveen funcionalidades adicionales en áreas como matemáticas, estadísticas y más. Los módulos se importan usando la palabra import y se accede a sus funciones anteponiendo el nombre del módulo. También se pueden importar funciones individuales de un módulo usando from. Los programas pueden organizarse en múltiples módulos para una mejor estructuración.

Cargado por

hdurangarzon
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Biblioteca estándar de Python

Todos los conceptos que hemos visto hasta ahora los hemos resuelto utilizando solo la sintaxis que
nos provee Python y un conjunto de funciones básicas que se incluyen automáticamente como por
ejemplo son print, range, len etc.

En Python se incluye una biblioteca extra de funciones, variables, clases etc. que nos facilitan la
resolución de problemas en una gran diversidad de áreas como matemáticas, estadísticas,
compresión de datos, internet, interfaces visuales etc.

Veremos en este concepto como se importa un módulo de la biblioteca estándar y como se accede a
su funcionalidad.
Problema 1:

Confeccionar un programa que simule tirar dos dados y luego muestre los valores que salieron.
Imprimir un mensaje que ganó si la suma de los mismos es igual a 7.

Para resolver este problema requerimos un algoritmo para que se genere un valor aleatorio entre 1 y
6. Como la generación de valores aleatorios es un tema muy frecuente la biblioteca estándar de
Python incluye un módulo que nos resuelve la generación de valores aleatorios.

Programa:

import random

dado1=[Link](1,6)
dado2=[Link](1,6)
print("Primer dado:",dado1)
print("Segundo dado:",dado2)
suma=dado1+dado2
if suma==7:
print("Gano")
else:
print("Perdio")

Para importar un módulo de la biblioteca estándar de Python utilizamos la palabra clave import
seguida por el nombre del módulo que necesitamos importar:

import random

Como dijimos la biblioteca estándar de Python se instala junto con Python.

Si disponemos un nombre de módulo inexistente aparecerá un error:

Traceback (most recent call last):


File "C:/programaspython/[Link]", line 1, in
import ran
ImportError: No module named 'ran'
Para acceder a todas las funciones contenidas en el módulo random es necesario primero importar el
módulo y luego dentro del algoritmo de nuestro programa anteceder primero el nombre del módulo
y seguidamente la función que queremos acceder:

dado1=[Link](1,6)

Si tratamos de acceder directamente al nombre de la función sin disponer el nombre del módulo se
produce un error:

Traceback (most recent call last):


File "C:/programaspython/[Link]", line 3, in
dado1=randint(1,6)
NameError: name 'randint' is not defined

Este error se produce porque la función randint no es una función integrada en Python como print,
range, len etc.
Entonces la sintaxis para acceder a la funcionalidad de un módulo requiere que dispongamos
primero el nombre del módulo y seguidamente el nombre de la función.
Como podemos imaginar la función randint retorna un valor aleatorio comprendido entre los dos
valores indicados en los parámetros.

La ejecución del programa tiene una salida similar a esta.


Importar algunas funcionalidades de un módulo de la biblioteca estándar de
Python

Hemos visto que para importar toda la funcionalidad de un módulo de la Biblioteca estándar de
Python utilizamos la palabra clave import y seguidamente el nombre del módulo:

import random

Con esa sintaxis todas las funcionalidades del módulo "random" pueden ser accedidas desde nuestro
módulo.

Ahora veremos que en Python tenemos otra sintaxis para las situaciones que queremos acceder a
una o pocas funcionalidades de un módulo.

Por ejemplo si queremos acceder solo a la función randint del módulo random en Python lo
podemos expresar con la siguiente sintaxis:

from random import randint

Utilizamos la palabra clave from y seguidamente el nombre del módulo de donde queremos
importar funcionalidades del mismo. Luego indicamos la palabra clave import y la funcionalidad
que queremos importar, en nuestro ejemplo la función randint.

También cambia como utilizamos la función randint dentro de nuestro módulo:

valor=randint(1,10)
print(valor)

Como vemos no le antecedemos ningún nombre de módulo y hacemos referencia directamente a la


función importada.

Si necesitamos importar más de una funcionalidad de un módulo debemos separar por comas las
funcionalidades importadas:

from random import randint,shuffle

Problema:
Confeccionar un programa que solicite la carga de un valor entero por teclado y luego nos muestre
la raíz cuadrada del número y el valor elevado al cubo.

Para resolver este problema utilizaremos dos funcionalidades que nos provee el módulo math de la
biblioteca estándar de Python. Podemos consultar el módulo math aquí
Programa:

from math import sqrt, pow

valor=int(input("Ingrese un valor entero:"))


r1=sqrt(valor)
r2=pow(valor,3)
print("La raiz cuadrada es",r1)
print("El cubo es",r2)

El módulo math tiene dos funciones llamadas sqrt (para obtener la raíz cuadrada) y la función pow
para elevar un valor a cierta potencia.
Utilizamos la sintaxis para importar solo dichas dos funcionalidades del módulo math:

from math import sqrt, pow

Una vez importadas las dos funciones podemos hacer uso de las mismas en nuestro programa
indicando directamente su nombre:

r1=sqrt(valor)

Lo mismo para llamar la función pow:

r2=pow(valor,3)

Definición de alias para una funcionalidad

Podemos definir un nombre distinto para una funcionalidad que importamos de otro módulo. Esto
puede tener como objetivo que nuestro programa sea más legible o evitar que un nombre de función
que importamos colisione con un nombre de función de nuestro propio módulo.
Resolveremos el mismo problema anterior pero definiendo dos alias para las funciones sqrt y pow
del módulo math.
Programa

from math import sqrt as raiz, pow as elevar

valor=int(input("Ingrese un valor entero:"))


r1=raiz(valor)
r2=elevar(valor,3)
print("La raiz cuadrada es",r1)
print("El cubo es",r2)

Como vemos para definir un alias a una funcionalidad que importamos de un módulo debemos
disponer la palabra clave as seguida del nuevo nombre:

from math import sqrt as raiz, pow as elevar


Luego para utilizar la funcionalidad que importamos debemos hacerlo mediante el alias y no con el
nombre definido en el módulo que importamos:

r1=raiz(valor)
r2=elevar(valor,3)
Aplicaciones propias con varios módulos

A medida que una aplicación sea más grande vimos que disponer todo el algoritmo en forma
secuencial es difícil de mantener y desarrollar. Para eso vimos que podemos resolver por partes
utilizando funciones.

Pero siempre dispusimos todas las funciones en un único archivo.


Pensemos que nuestro problema podría ser lo suficientemente complejo y grande que también por
más que lo dividamos en funciones un único archivo sea complejo de mantener.

En Python podemos agrupar funciones en distintos archivos (módulos) y luego importarlos en otros
módulos.
Así como importamos los módulos de la biblioteca estándar de Python podemos importar otros
módulos que codifiquemos nosotros.

Problema:
Confeccionar una aplicación que permita cargar por teclado una lista de enteros, obtener y mostrar
el mayor y calcular su suma. Definir un módulo con las funciones de carga, identificar el mayor y
sumar. En el módulo principal del programa importar el otro módulo y llamar a sus funciones.

Para ser un poco más ordenados crearemos una carpeta llamada proyecto1 y dentro de la misma
crearemos los dos módulos llamados:

[Link]
[Link]

El módulo [Link] contiene todas las funciones que nos permiten cargar una lista,
imprimir el mayor de una lista y sumar todos los elementos y mostrar dicho valor.
módulo: [Link]

def cargar():
lista=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
[Link](valor)
return lista

def imprimir_mayor(lista):
may=lista[0]
for x in range(1,5):
if lista[x]>may:
may=lista[x]
print("Mayor de la lista",may)

def imprimir_suma(lista):
suma=0
for elemento in lista:
suma=suma+elemento
print("Suma de todos sus elementos",suma)
El segundo archivo y desde donde realmente arrancará nuestro programa es el módulo [Link]
módulo: [Link]

import operacioneslista

lista=[Link]()
operacioneslista.imprimir_mayor(lista)
operacioneslista.imprimir_suma(lista)

Es importante indicar que cuando queremos ejecutar nuestro programa tenemos que abrir el archivo
[Link] y elegir la opción "Run Module" o presionar la tecla "F5".

Como podemos ver nuestro módulo principal solo tiene cuatro líneas.
import operacioneslista

lista=[Link]()
operacioneslista.imprimir_mayor(lista)
operacioneslista.imprimir_suma(lista)

Primero importamos el módulo operacioneslista y seguidamente llamamos a las funciones de


cargar, imprimir_mayor y imprimir_suma. Recordar que debemos anteceder el nombre del módulo
donde están definidas.

Podemos ver luego de ejecutarlo a nuestro programa que en la carpeta de nuestro proyecto1 además
de los archivo [Link] y [Link] hay una carpeta llamada __pycache__ con un
archivo con extensión *.pyc ([Link]) Este archivo lo crea
automáticamente el Python cuando ejecutamos por primera vez nuestro programa y tiene por
objetivo hacer más eficiente las ejecuciones futuras del programa.

Por ahora dispondremos todos los módulos de nuestro proyecto en la misma carpeta.

Esta característica de Python de poder disponer funcionalidades en distintos archivos es


fundamental para cuando hay que desarrollar programas en los cuales intervienen un conjunto de
programadores. Se posibilita asignar a cada programador distintas funcionalidades y que se
implementen en distintos módulos.

También nos facilita el implementar módulos con funcionalidades que pueden ser reutilizadas en
otros proyectos, así como sucede con la biblioteca estándar de Python.

Problema:
Confeccionar un módulo que implemente dos funciones, una que retorne el mayor de dos enteros y
otra que retorne el menor de dos enteros.
En el módulo principal importar solo la función que retorne el mayor, luego cargar dos enteros y
mostrar el mayor de ellos
Crear una carpeta llamada proyecto2 y dentro de la misma crear dos módulos llamados:

[Link]
[Link]

El módulo [Link] contiene las dos funciones que identifican el mayor de dos enteros por
un lado y el menor de dos enteros.
módulo: [Link]

def mayor(x1,x2):
if x1>x2:
return x1
else:
return x2

def menor(x1,x2):
if x1<x2:
return x1
else:
return x2

Por otro lado el programa principal que importa solo la función mayor es:
módulo: [Link]

from mayormenor import mayor

valor1=int(input("Ingrese primer valor:"))


valor2=int(input("Ingrese segundo valor:"))
print("El mayor de los dos valores es",mayor(valor1,valor2))

Esta sintaxis de importar funcionalidades particulares de un módulo la vimos anteriormente con la


biblioteca estándar de Python.

Conceptos de programación orientada a objetos

Python nos permite utilizar distintas metodologías de programación. Hemos implementado


inicialmente programas utilizando la programación lineal, luego vimos funciones y trabajamos con
programación estructurada.

Ahora introduciremos los conceptos de programación orientada a objetos. A partir de este concepto
mostraremos en forma sencilla la metodología de Programación Orientada a Objetos.

Se irán introduciendo conceptos de objeto, clase, atributo, método etc. y de todos estos temas se irán
planteando problemas resueltos.

Prácticamente todos los lenguajes desarrollados en los últimos 25 años implementan la posibilidad
de trabajar con POO (Programación Orientada a Objetos)

El lenguaje Python tiene la característica de permitir programar con las siguientes metodologías:

Programación Lineal: Es cuando desarrollamos todo el código sin emplear funciones. El código
es una secuencia lineal de comando.
Programación Estructurada: Es cuando planteamos funciones que agrupan actividades a
desarrollar y luego dentro del programa llamamos a dichas funciones que pueden estar dentro del
mismo archivo (módulo) o en una librería separada.
Programación Orientada a Objetos: Es cuando planteamos clases y definimos objetos de las
mismas (Este es el objetivo de los próximos conceptos, aprender la metodología de programación
orientada a objetos y la sintaxis particular de Python para la POO)

Conceptos básicos de Objetos

Un objeto es una entidad independiente con sus propios datos y programación. Las ventanas,
menúes, carpetas de archivos pueden ser identificados como objetos; el motor de un auto también es
considerado un objeto, en este caso, sus datos (atributos) describen sus características físicas y su
programación (métodos) describen el funcionamiento interno y su interrelación con otras partes del
automóvil (también objetos).

El concepto renovador de la tecnología de Orientación a Objetos es la suma de funciones a


elementos de datos, a esta unión se le llama encapsulamiento.
Por ejemplo, un objeto Auto contiene ruedas, motor, velocidad, color, etc, llamados atributos.
Encapsulados con estos datos se encuentran los métodos para arrancar, detenerse, dobla, frenar etc.
La responsabilidad de un objeto auto consiste en realizar las acciones apropiadas y mantener
actualizados sus datos internos.
Cuando otra parte del programa (otros objetos) necesitan que el auto realice alguna de estas tareas
(por ejemplo, arrancar) le envía un mensaje. A estos objetos que envían mensajes no les interesa la
manera en que el objeto auto lleva a cabo sus tareas ni las estructuras de datos que maneja, por ello,
están ocultos.
Entonces, un objeto contiene información pública, lo que necesitan los otros objetos para interactuar
con él e información privada, interna, lo que necesita el objeto para operar y que es irrelevante para
los otros objetos de la aplicación.

Declaración de una clase y creación de objetos

La programación orientada a objetos se basa en la definición de clases; a diferencia de la


programación estructurada, que está centrada en las funciones.

Una clase es un molde del que luego se pueden crear múltiples objetos, con similares
características.

Un poco más abajo se define una clase Persona y luego se crean dos objetos de dicha clase.

Una clase es una plantilla (molde), que define atributos (lo que conocemos como variables) y
métodos (lo que conocemos como funciones).

La clase define los atributos y métodos comunes a los objetos de ese tipo, pero luego, cada objeto
tendrá sus propios valores y compartirán las mismas funciones.

Debemos declarar una clase antes de poder crear objetos (instancias) de esa clase. Al crear un objeto
de una clase, se dice que se crea una instancia de la clase o un objeto propiamente dicho.

Problema:
Implementaremos una clase llamada Persona que tendrá como atributo (variable) su nombre y dos
métodos (funciones), uno de dichos métodos inicializará el atributo nombre y el siguiente método
mostrará en la pantalla el contenido del mismo.
Definir dos objetos de la clase Persona.

class Persona:

def inicializar(self,nom):
[Link]=nom

def imprimir(self):
print("Nombre",[Link])

# bloque principal

persona1=Persona()
[Link]("Pedro")
[Link]()

persona2=Persona()
[Link]("Carla")
[Link]()

Siempre conviene buscar un nombre de clase lo más próximo a lo que representa. La palabra clave
para declarar la clase es class, seguidamente el nombre de la clase y luego dos puntos.

Los métodos de una clase se definen utilizando la misma sintaxis que para la definición de
funciones.

Como veremos todo método tiene como primer parámetro el identificador self que tiene la
referencia del objeto que llamó al método.

Luego dentro del método diferenciamos los atributos del objeto antecediendo el identificador self:

[Link]=nom

Con la asignación previa almacenamos en el atributo nombre el parámetro nom, los atributos siguen
existiendo cuando finaliza la ejecución del método. Por ello cuando se ejecuta el método imprimir
podemos mostrar el nombre que cargamos en el primer método.

Decíamos que una clase es un molde que nos permite definir objetos. Ahora veamos cual es la
sintaxis para la creación de objetos de la clase Persona:

# bloque principal

persona1=Persona()
[Link]("Pedro")
[Link]()

persona2=Persona()
[Link]("Carla")
[Link]()

Definimos un objeto llamado persona1 y lo creamos asignándole el nombre de la clase con


paréntesis abierto y cerrado al final (como cuando llamamos a una función)
Luego para llamar a los métodos debemos disponer luego del nombre del objeto el operador . y por
último el nombre del método (función)

En el caso que tenga parámetros se los enviamos (salvo el primer parámetro (self) que el mismo
Python se encarga de enviar la referencia del objeto que se creó):

[Link]("Pedro")

También podemos definir tantos objetos de la clase Persona como sean necesarios para nuestro
algoritmo:

persona2=Persona()
[Link]("Carla")
[Link]()

La declaración de clases es una de las ventajas fundamentales de la Programación Orientada a


Objetos (POO), es decir reutilización de código (gracias a que está encapsulada en clases) es muy
sencilla.

Problema:
Implementar una clase llamada Alumno que tenga como atributos su nombre y su nota. Definir los
métodos para inicializar sus atributos, imprimirlos y mostrar un mensaje si está regular (nota mayor
o igual a 4)

Definir dos objetos de la clase Alumno.


Programa

class Alumno:

def inicializar(self,nombre,nota):
[Link]=nombre
[Link]=nota

def imprimir(self):
print("Nombre:",[Link])
print("Nota:",[Link])

def mostrar_estado(self):
if [Link]>=4:
print("Regular")
else:
print("Libre")

# bloque principal

alumno1=Alumno()
[Link]("diego",2)
[Link]()
alumno1.mostrar_estado()
alumno2=Alumno()
[Link]("ana",10)
[Link]()
alumno2.mostrar_estado()

Declaramos la clase Alumno y definimos sus tres métodos, en el método inicializar llegan como
parámetros a parte del self el nombre y nota del alumno:

def inicializar(self,nombre,nota):
[Link]=nombre
[Link]=nota

No hay problema que los atributos se llamen iguales a los parámetros ya que siempre hay que
anteceder la palabra "self" al nombre del atributo:

[Link]=nombre

Tener en cuenta que cuando se crean los atributos en el método inicializar luego podemos acceder a
los mismos en los otros métodos de la clase, por ejemplo en el método mostrar_estado verificamos
el valor almacenado en el atributo nota:

def mostrar_estado(self):
if [Link]>=4:
print("Regular")
else:
print("Libre")

Decimos que una clase es un molde que nos permite crear luego objetos de dicha clase, en este
problema el molde Alumno lo utilizamos para crear dos objetos de dicha clase:

# bloque principal

alumno1=Alumno()
[Link]("diego",2)
[Link]()
alumno1.mostrar_estado()

alumno2=Alumno()
[Link]("ana",10)
[Link]()
alumno2.mostrar_estado()

Es fundamental la definición de objetos de una clase para que haya tenido sentido la declaración de
dicha clase.
Método __init__ de la clase

El método __init__ es un método especial de una clase en Python. El objetivo fundamental del
método __init__ es inicializar los atributos del objeto que creamos.

Básicamente el método __init__ remplaza al método inicializar que habíamos hecho en el concepto
anterior.

Las ventajas de implementar el método __init__ en lugar del método inicializar son:

El método __init__ es el primer método que se ejecuta cuando se crea un objeto.


El método __init__ se llama automáticamente. Es decir es imposible de olvidarse de llamarlo ya
que se llamará automáticamente.
Quien utiliza POO en Python (Programación Orientada a Objetos) conoce el objetivo de este
método.
Otras características del método __init__ son:

Se ejecuta inmediatamente luego de crear un objeto.


El método __init__ no puede retornar dato.
el método __init__ puede recibir parámetros que se utilizan normalmente para inicializar
atributos.
El método __init__ es un método opcional, de todos modos es muy común declararlo.

Veamos la sintaxis del constructor:

def __init__([parámetros]):
[algoritmo]

Debemos definir un método llamado __init__ (es decir utilizamos dos caracteres de subrayado, la
palabra init y seguidamente otros dos caracteres de subrayado).

Problema:
Confeccionar una clase que represente un empleado. Definir como atributos su nombre y su sueldo.
En el método __init__ cargar los atributos por teclado y luego en otro método imprimir sus datos y
por último uno que imprima un mensaje si debe pagar impuestos (si el sueldo supera a 3000)

Programa
class Empleado:

def __init__(self):
[Link]=input("Ingrese el nombre del empleado:")
[Link]=float(input("Ingrese el sueldo:"))

def imprimir(self):
print("Nombre:",[Link])
print("Sueldo:",[Link])

def paga_impuestos(self):
if [Link]>3000:
print("Debe pagar impuestos")
else:
print("No paga impuestos")
# bloque principal

empleado1=Empleado()
[Link]()
empleado1.paga_impuestos()

Definimos el método __init__ donde cargamos por teclado el nombre del empleado y su sueldo:

def __init__(self):
[Link]=input("Ingrese el nombre del empleado:")
[Link]=float(input("Ingrese el sueldo:"))

Este método se ejecuta inmediatamente luego que se crea un objeto de la clase Empleado:

empleado1=Empleado()

Como vemos no llamamos directamente al método __init__ sino que se llama automáticamente.

Los otros dos métodos tienen por objeto mostrar los datos del empleado y mostrar una leyenda si
paga impuestos o no:

def imprimir(self):
print("Nombre:",[Link])
print("Sueldo:",[Link])

def paga_impuestos(self):
if [Link]>3000:
print("Debe pagar impuestos")
else:
print("No paga impuestos")

Desde el bloque principal donde creamos un objeto de la clase Empleado debemos llamar
explícitamente a estos dos métodos:

[Link]()
empleado1.paga_impuestos()

Problema:
Desarrollar una clase que represente un punto en el plano y tenga los siguientes métodos: inicializar
los valores de x e y que llegan como parámetros, imprimir en que cuadrante se encuentra dicho
punto (concepto matemático, primer cuadrante si x e y son positivas, si x<0 e y>0 segundo
cuadrante, etc.)
Programa
class Punto:

def __init__(self,x,y):
self.x=x
self.y=y

def imprimir(self):
print("Coordenada del punto")
print("(",self.x,",",self.y,")")

def imprimir_cuadrante(self):
if self.x>0 and self.y>0:
print("Primer cuadrange")
else:
if self.x<0 and self.y>0:
print("Segundo cuadrante")
else:
if self.x<0 and self.y<0:
print("Tercer cuadrante")
else:
if self.x>0 and self.y<0:
print("Cuarto cuadrante")

# bloque principal

punto1=Punto(10,-2)
[Link]()
punto1.imprimir_cuadrante()

En este problema el método __init__ aparte del parámetro self que siempre va tenemos otros dos
parámetros:

def __init__(self,x,y):
self.x=x
self.y=y

Desde el bloque principal donde creamos un objeto de la clase Punto pasamos los datos a los
parámetros:

punto1=Punto(10,-2)

Recordemos que pasamos dos parámetros aunque el método __init__ recibe 3. El parámetro self
recibe la referencia de la variable punto1 (es decir el objeto propiamente dicho)
Llamada de métodos desde otro método de la misma clase

Hasta ahora todos los problemas planteados hemos llamado a los métodos desde donde definimos
un objeto de dicha clase, por ejemplo:

empleado1=Empleado("diego",2000)
empleado1.paga_impuestos()

Utilizamos la sintaxis:
[nombre del objeto].[nombre del método]
Es decir antecedemos al nombre del método el nombre del objeto y el operador punto

Ahora bien que pasa si queremos llamar dentro de la clase a otro método que pertenece a la misma
clase, la sintaxis es la siguiente:

self.[nombre del método]

Es importante tener en cuenta que esto solo se puede hacer cuando estamos dentro de la misma
clase.
Es importante tener en cuenta que esto solo se puede hacer cuando estamos dentro de la misma
clase.
Problema:
Plantear una clase Operaciones que solicite en el método __init__ la carga de dos enteros e
inmediatamente muestre su suma, resta, multiplicación y división. Hacer cada operación en otro
método de la clase Operación y llamarlos desde el mismo método __init__
Programa:

class Operacion:

def __init__(self):
self.valor1=int(input("Ingrese primer valor:"))
self.valor2=int(input("Ingrese segundo valor:"))
[Link]()
[Link]()
[Link]()
[Link]()

def sumar(self):
suma=self.valor1+self.valor2
print("La suma es",suma)

def restar(self):
resta=self.valor1-self.valor2
print("La rersta es",resta)

def multiplicar(self):
multi=self.valor1*self.valor2
print("El producto es",multi)

def dividir(self):
divi=self.valor1/self.valor2
print("La division es",divi)
# bloque principal

operacion1=Operacion()

Nuestro método __init__ además de cargar los dos enteros procede a llamar a los métodos que
calculan la suma, resta, multiplicación y división de los dos valores ingresados.
La llamada de los métodos de la misma clase se hace antecediendo al nombre del método la palabra
self:

def __init__(self):
self.valor1=int(input("Ingrese primer valor:"))
self.valor2=int(input("Ingrese segundo valor:"))
[Link]()
[Link]()
[Link]()
[Link]()

El método que calcula la suma de los dos atributos cargados en el método __init__ define una
variable local llamada suma y guarda la suma de los dos atributos. Posteriormente muestra la suma
por pantalla:

def sumar(self):
suma=self.valor1+self.valor2
print("La suma es",suma)

De forma similar los otros métodos calculan la resta, multiplicación y división de los dos valores
ingresados:

def sumar(self):
suma=self.valor1+self.valor2
print("La suma es",suma)

def restar(self):
resta=self.valor1-self.valor2
print("La rersta es",resta)

def multiplicar(self):
multi=self.valor1*self.valor2
print("El producto es",multi)

def dividir(self):
divi=self.valor1/self.valor2
print("La division es",divi)

En el bloque principal de nuestro programa solo requerimos crear un objeto de la clase Operación
ya que el resto de los métodos se llama en el método __init__:
# bloque principal
operacion1=Operacion()
Problema:
Plantear una clase que administre dos listas de 5 nombres de alumnos y sus notas. Mostrar un menú
de opciones que permita:
1- Cargar alumnos.
2- Listar alumnos.
3- Mostrar alumnos con notas mayores o iguales a 7.
4- Finalizar programa.
Programa:

class Alumnos:

def __init__(self):
[Link]=[]
[Link]=[]

def menu(self):
opcion=0
while opcion!=4:
print("1- Cargar alumnos")
print("2- Listar alumnos")
print("3- Listado de alumnos con notas mayores o
iguales a 7")
print("4- Finalizar programa")
opcion=int(input("Ingrese su opcion:"))
if opcion==1:
[Link]()
elif opcion==2:
[Link]()
elif opcion==3:
self.notas_altas()

def cargar(self):
for x in range(5):
nom=input("Ingrese nombre del alumno:")
[Link](nom)
no=int(input("Nota del alumno:"))
[Link](no)

def listar(self):
print("Listado completo de alumnos")
for x in range(5):
print([Link][x],[Link][x])
print("_____________________")

def notas_altas(self):
print("Alumnos con notas superiores o iguales a 7")
for x in range(5):
if [Link][x]>=7:
print([Link][x],[Link][x])
print("_____________________")
# bloque principal

alumnos=Alumnos()
[Link]()

Si ejecutamos el programa podemos ver como aparece un menú de opciones y podemos seleccionar
para cargar, listar etc.:
El bloque principal del programa es muy sencillo, solo creamos un objeto de la clase Alumno y
llamamos posteriormente al método menu:

# bloque principal

alumnos=Alumnos()
[Link]()

Ahora analicemos la clase Alumno, en el método __init__ procedemos a crear dos atributos de tipo
lista donde se almacenarán los nombres de alumnos y sus notas:

class Alumnos:

def __init__(self):
[Link]=[]
[Link]=[]

El método menu muestra una serie de opciones y solicita al operador que elija una de ellas, según
cual de ellas selecciona procede a llamar al método respectivo:

def menu(self):
opcion=0
while opcion!=4:
print("1- Cargar alumnos")
print("2- Listar alumnos")
print("3- Listado de alumnos con notas mayores o
iguales a 7")
print("4- Finalizar programa")
opcion=int(input("Ingrese su opcion:"))
if opcion==1:
[Link]()
elif opcion==2:
[Link]()
elif opcion==3:
self.notas_altas()

Algo que no utilizamos hasta ahora del lenguaje Python son una forma simplificada de if anidados
con la sentencia elif:

if opcion==1:
[Link]()
elif opcion==2:
[Link]()
elif opcion==3:
self.notas_altas()
Nosotros hasta ahora lo resolvíamos y podemos sin problema seguir utilizando la sintaxis::

if opcion==1:
[Link]()
else:
if opcion==2:
[Link]()
else:
if opcion==3:
self.notas_altas()

Pero podemos comprobar que si hay muchos if anidados la nueva sintaxis es más clara.

El método menu se repite el while mientras no se ingrese en la variable local opcion el valor 4.

El método cargar se llama desde el método menu, en el mismo procedemos a cargar las dos listas
paralelas con los nombres de alumnos y sus notas:

def cargar(self):
for x in range(5):
nom=input("Ingrese nombre del alumno:")
[Link](nom)
no=int(input("Nota del alumno:"))
[Link](no)

El método listar muestra las dos listas paralelas por completo e imprime una línea separadora para
que se vea in forma más clara:

def listar(self):
print("Listado completo de alumnos")
for x in range(5):
print([Link][x],[Link][x])
print("_____________________")

Finalmente el método notas_altas muestra solo los elementos de las listas cuyas notas sean igual o
superior a 7:

def notas_altas(self):
print("Alumnos con notas superiores o iguales a 7")
for x in range(5):
if [Link][x]>=7:
print([Link][x],[Link][x])
print("_____________________")
Colaboración de clases

Normalmente un problema resuelto con la metodología de programación orientada a objetos no


interviene una sola clase, sino que hay muchas clases que interactúan y se comunican.

Plantearemos un problema separando las actividades en dos clases.

Problema:
Un banco tiene 3 clientes que pueden hacer depósitos y extracciones. También el banco requiere
que al final del día calcule la cantidad de dinero que hay depositado.

Lo primero que hacemos es identificar las clases:

Podemos identificar la clase Cliente y la clase Banco.

Luego debemos definir los atributos y los métodos de cada clase:

Cliente
atributos
nombre
monto
métodos
__init__
depositar
extraer
retornar_monto

Banco
atributos
3 Cliente (3 objetos de la clase Cliente)
métodos
__init__
operar
depositos_totales
Programa
class Cliente:

def __init__(self,nombre):
[Link]=nombre
[Link]=0

def depositar(self,monto):
[Link]=[Link]+monto

def extraer(self,monto):
[Link]=[Link]-monto

def retornar_monto(self):
return [Link]

def imprimir(self):
print([Link],"tiene depositado la suma
de",[Link])

class Banco:

def __init__(self):
self.cliente1=Cliente("Juan")
self.cliente2=Cliente("Ana")
self.cliente3=Cliente("Diego")

def operar(self):
[Link](100)
[Link](150)
[Link](200)
[Link](150)

def depositos_totales(self):
total=self.cliente1.retornar_monto()
+self.cliente2.retornar_monto()+self.cliente3.retornar_monto()
print("El total de dinero del banco es:",total)
[Link]()
[Link]()
[Link]()

# bloque principal

banco1=Banco()
[Link]()
banco1.depositos_totales()

Primero hacemos la declaración de la clase Cliente, en el método __init__ inicializamos los


atributos nombre con el valor que llega como parámetro y el atributo monto con el valor cero:
class Cliente:

def __init__(self,nombre):
[Link]=nombre
[Link]=0

Recordemos que en Python para diferenciar un atributo de una variable local o un parámetro le
antecedemos la palabra clave self (es decir nombre es el parámetro y [Link] es el atributo):

[Link]=nombre

El método que aumenta el atributo monto es:

def depositar(self,monto):
[Link]=[Link]+monto

Y el método que reduce el atributo monto del cliente es:

def extraer(self,monto):
[Link]=[Link]-monto

Lo más común para que otro objeto conozca el monto depositado por un cliente es la
implementación de un método que lo retorne:

def retornar_monto(self):
return [Link]

Para mostrar los datos del cliente tenemos el método:

def imprimir(self):
print([Link],"tiene depositado la suma
de",[Link])

La segunda clase de nuestro problema es el Banco. Esta clase define tres atributos de la clase
Cliente (la clase Cliente colabora con la clase Banco):

class Banco:

def __init__(self):
self.cliente1=Cliente("Juan")
self.cliente2=Cliente("Ana")
self.cliente3=Cliente("Diego")

El método operar realiza una serie de depósitos y extracciones de los clientes:

def operar(self):
[Link](100)
[Link](150)
[Link](200)
[Link](150)

El método que muestra cuanto dinero tiene depositado el banco se resuelve pidiendo a cada cliente
que retorne el monto que tiene:
def depositos_totales(self):
total=self.cliente1.retornar_monto()
+self.cliente2.retornar_monto()+self.cliente3.retornar_monto()
print("El total de dinero del banco es:",total)
[Link]()
[Link]()
[Link]()

En el bloque principal de nuestro programa en Python procedemos a crear un objeto de la clase


Banco y llamar a los dos métodos:

# bloque principal

banco1=Banco()
[Link]()
banco1.depositos_totales()

En el bloque principal no se requiere crear objetos de la clase Cliente, esto debido que los clientes
son atributos del Banco.

Problema:
Plantear un programa que permita jugar a los dados. Las reglas de juego son:
se tiran tres dados si los tres salen con el mismo valor mostrar un mensaje que "gano", sino
"perdió".

Lo primero que hacemos es identificar las clases:


Podemos identificar la clase Dado y la clase JuegoDeDados.
Luego los atributos y los métodos de cada clase:

Dado
atributos
valor
métodos
tirar
imprimir
retornar_valor

JuegoDeDados
atributos
3 Dado (3 objetos de la clase Dado)
métodos
__init__
jugar
Programa

import random

class Dado:

def tirar(self):
[Link]=[Link](1,6)

def imprimir(self):
print("Valor del dado:",[Link])

def retornar_valor(self):
return [Link]

class JuegoDeDados:

def __init__(self):
self.dado1=Dado()
self.dado2=Dado()
self.dado3=Dado()

def jugar(self):
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
if
self.dado1.retornar_valor()==self.dado2.retornar_valor() and
self.dado1.retornar_valor()==self.dado3.retornar_valor():
print("Gano")
else:
print("Perdio")

# bloque principal del programa

juego_dados=JuegoDeDados()
juego_dados.jugar()

Importamos el módulo "random" de la biblioteca estándar de Python ya que requerimos utilizar la


función randint:

import random

La clase Dado define un método tirar que almacena en el atributo valor un número aleatorio
comprendido entre 1 y 6:
class Dado:

def tirar(self):
[Link]=[Link](1,6)

Los otros dos métodos de la clase Dado tienen por objetivo mostrar el valor del dado y retornar
dicho valor a otra clase que lo requiera:

def imprimir(self):
print("Valor del dado:",[Link])

def retornar_valor(self):
return [Link]

La clase JuegoDeDados define tres atributos de la clase Dado, en el método __init__ crea dichos
objetos:

class JuegoDeDados:

def __init__(self):
self.dado1=Dado()
self.dado2=Dado()
self.dado3=Dado()

En el método jugar de la clase JuegoDeDados procedemos a pedir a cada dado que se tire, imprima
y verificamos si los tres valores son iguales:

def jugar(self):
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
[Link]()
if
self.dado1.retornar_valor()==self.dado2.retornar_valor() and
self.dado1.retornar_valor()==self.dado3.retornar_valor():
print("Gano")
else:
print("Perdio")

En el bloque principal de nuestro programa creamos un objeto de la clase JuegoDeDados:

# bloque principal del programa

juego_dados=JuegoDeDados()
juego_dados.jugar()
Acotación

Para cortar una línea en varias líneas en Python podemos encerrar entre paréntesis la condición:

if
(self.dado1.retornar_valor()==self.dado2.retornar_valor()
and
self.dado1.retornar_valor()==self.dado3.retornar_valor()):

O agregar una barra al final:

if
self.dado1.retornar_valor()==self.dado2.retornar_valor() and \

self.dado1.retornar_valor()==self.dado3.retornar_valor():

Si no utilizamos los paréntesis o la barra al final y tratamos de disponer el if en dos líneas se


produce un error sintáctico:
Herencia

Vimos en el concepto anterior que dos clases pueden estar relacionadas por la colaboración. Ahora
veremos otro tipo de relaciones entre clases que es la Herencia.

La herencia significa que se pueden crear nuevas clases partiendo de clases existentes, que tendrá
todas los atributos y los métodos de su 'superclase' o 'clase padre' y además se le podrán añadir otros
atributos y métodos propios.
clase padre

Clase de la que desciende o deriva una clase. Las clases hijas (descendientes) heredan (incorporan)
automáticamente los atributos y métodos de la la clase padre.
Subclase

Clase descendiente de otra. Hereda automáticamente los atributos y métodos de su superclase. Es


una especialización de otra clase.
Admiten la definición de nuevos atributos y métodos para aumentar la especialización de la clase.

Veamos algunos ejemplos teóricos de herencia:

1) Imaginemos la clase Vehículo. Qué clases podrían derivar de ella?

Vehículo

Colectivo Moto Auto

Ford K Renault Fluence

Siempre hacia abajo en la jerarquía hay una especialización (las subclases añaden nuevos atributos
y métodos.

2) Imaginemos la clase Software. Qué clases podrían derivar de ella?

Software

DeAplicacion DeBase

ProcesadorTexto PlanillaDeCalculo SistemaOperativo


Word WordPerfect Excel Lotus123 Linux Windows

El primer tipo de relación que habíamos visto entre dos clases, es la de colaboración. Recordemos
que es cuando una clase contiene un objeto de otra clase como atributo.
Cuando la relación entre dos clases es del tipo "...tiene un..." o "...es parte de...", no debemos
implementar herencia. Estamos frente a una relación de colaboración de clases no de herencia.
Si tenemos una ClaseA y otra ClaseB y notamos que entre ellas existe una relacion de tipo "... tiene
un...", no debe implementarse herencia sino declarar en la clase ClaseA un atributo de la clase
ClaseB.

Por ejemplo: tenemos una clase Auto, una clase Rueda y una clase Volante. Vemos que la relación
entre ellas es: Auto "...tiene 4..." Rueda, Volante "...es parte de..." Auto; pero la clase Auto no debe
derivar de Rueda ni Volante de Auto porque la relación no es de tipo-subtipo sino de colaboración.
Debemos declarar en la clase Auto 4 atributos de tipo Rueda y 1 de tipo Volante.

Luego si vemos que dos clase responden a la pregunta ClaseA "..es un.." ClaseB es posible que
haya una relación de herencia.

Por ejemplo:

Auto "es un" Vehiculo


Circulo "es una" Figura
Mouse "es un" DispositivoEntrada
Suma "es una" Operacion

Problema:

Plantear una clase Persona que contenga dos atributos: nombre y edad. Definir como
responsabilidades la carga por teclado y su impresión.
En el bloque principal del programa definir un objeto de la clase persona y llamar a sus métodos.

Declarar una segunda clase llamada Empleado que herede de la clase Persona y agregue un atributo
sueldo y muestre si debe pagar impuestos (sueldo superior a 3000)
También en el bloque principal del programa crear un objeto de la clase Empleado.
Programa

class Persona:

def __init__(self):
[Link]=input("Ingrese el nombre:")
[Link]=int(input("Ingrese la edad:"))

def imprimir(self):
print("Nombre:",[Link])
print("Edad:",[Link])

class Empleado(Persona):

def __init__(self):
super().__init__()
[Link]=float(input("Ingrese el sueldo:"))

def imprimir(self):
super().imprimir()
print("Sueldo:",[Link])

def paga_impuestos(self):
if [Link]>3000:
print("El empleado debe pagar impuestos")
else:
print("No paga impuestos")

# bloque principal

persona1=Persona()
[Link]()
print("____________________________")
empleado1=Empleado()
[Link]()
empleado1.paga_impuestos()

La clase Persona no tiene ninguna sintaxis nueva, como vemos definimos sus métodos __init__ e
imprimir, y sus dos atributos nombre y edad:

class Persona:

def __init__(self):
[Link]=input("Ingrese el nombre:")
[Link]=int(input("Ingrese la edad:"))

def imprimir(self):
print("Nombre:",[Link])
print("Edad:",[Link])

En el bloque principal creamos un objeto de la clase Persona:

# bloque principal

persona1=Persona()
[Link]()

La herencia se presenta en la clase Empleado, en la declaración de la clase indicamos entre


paréntesis el nombre de la clase de la cual hereda:

class Empleado(Persona):

Con esta sintaxis indicamos que la clase Empleado hereda de la clase Persona. Luego de esto
podemos decir que la clase Empleado ya tiene dos atributos heredados que son el nombre y la edad,
también hereda las funcionalidades __init__ e imprimir.

La clase Empleado define un nuevo atributo que es el sueldo y tres funcionalidades __init__,
imprimir y paga_impuestos.

En el método __init__ de la clase Empleado primero llamamos al método __init__ de la clase padre
y luego cargamos el sueldo:

def __init__(self):
super().__init__()
[Link]=float(input("Ingrese el sueldo:"))
Mediante la función super() podemos llamar al método __init__ de la clase padre.

Lo mismo sucede con el método imprimir donde primero llamamos al imprimir de la clase padre y
luego mostramos el sueldo del empleado:

def imprimir(self):
super().imprimir()
print("Sueldo:",[Link])

La tercer funcionalidad es:

def paga_impuestos(self):
if [Link]>3000:
print("El empleado debe pagar impuestos")
else:
print("No paga impuestos")

En el bloque principal de nuestro programa definimos un objeto de la clase Empleado y llamamos a


sus funcionalidades:

empleado1=Empleado()
[Link]()
empleado1.paga_impuestos()

Problema:
Ahora plantearemos otro problema empleando herencia. Supongamos que necesitamos implementar
dos clases que llamaremos Suma y Resta. Cada clase tiene como atributo valor1, valor2 y resultado.
Los métodos a definir son cargar1 (que inicializa el atributo valor1), carga2 (que inicializa el
atributo valor2), operar (que en el caso de la clase "Suma" suma los dos atributos y en el caso de la
clase "Resta" hace la diferencia entre valor1 y valor2), y otro método mostrar_resultado.

Si analizamos ambas clases encontramos que muchos atributos y métodos son idénticos. En estos
casos es bueno definir una clase padre que agrupe dichos atributos y responsabilidades comunes.

La relación de herencia que podemos disponer para este problema es:

Operación

Suma Resta

Solamente el método operar es distinto para las clases Suma y Resta (esto hace que no lo podamos
disponer en la clase Operación en principio), luego los métodos cargar1, cargar2 y
mostrar_resultado son idénticos a las dos clases, esto hace que podamos disponerlos en la clase
Operación. Lo mismo los atributos valor1, valor2 y resultado se definirán en la clase padre
Operación.
Programa:

class Operacion:

def __init__(self):
self.valor1=0
self.valor2=0
[Link]=0

def cargar1(self):
self.valor1=int(input("Ingrese primer valor:"))

def cargar2(self):
self.valor2=int(input("Ingrese segundo valor:"))

def mostrar_resultado(self):
print([Link])

def operar(self):
pass

class Suma(Operacion):

def operar(self):
[Link]=self.valor1+self.valor2

class Resta(Operacion):

def operar(self):
[Link]=self.valor1-self.valor2

# bloque princpipal

suma1=Suma()
suma1.cargar1()
suma1.cargar2()
[Link]()
print("La suma de los dos valores es")
suma1.mostrar_resultado()

resta1=Resta()
resta1.cargar1()
resta1.cargar2()
[Link]()
print("La resta de los valores es:")
resta1.mostrar_resultado()

En este problema la clase Operación tiene por objetivo agrupar atributos y funcionalidades que se
heredarán en otras clases.
La clase Operación inicializa en el metodo __init__ tres atributos:

class Operacion:

def __init__(self):
self.valor1=0
self.valor2=0
[Link]=0

Define dos métodos para cargar los atributos valor1 y valor2:

def cargar1(self):
self.valor1=int(input("Ingrese primer valor:"))

def cargar2(self):
self.valor2=int(input("Ingrese segundo valor:"))

Definimos un método para imprimir el atributo resultado:

def mostrar_resultado(self):
print([Link])

Como la clase Operación se trata de una clase genérica que busca agrupar funcionalidades y
atributos para otras clases podemos definir un método operar pero no podemos implementar
ninguna funcionalidad:

def operar(self):
pass

En Python para indicar que un método está vacío se utiliza la palabra clave "pass".

En el bloque principal de nuestro programa no creamos objetos de la clase Operación. La clase


Operación tiene sentido que otras clases hereden de esta.

Tanto la clase Suma y Resta heredan de la clase Operación y reescriben el método operar con la
funcionalidad que le corresponde a cada clase:

class Suma(Operacion):

def operar(self):
[Link]=self.valor1+self.valor2

class Resta(Operacion):

def operar(self):
[Link]=self.valor1-self.valor2
Finalmente en el bloque principal de nuestro programa en Python creamos un objeto de la clase
Suma y otro de la clase Resta y llamamos a sus respectivos métodos en un orden lógico:

# bloque princpipal

suma1=Suma()
suma1.cargar1()
suma1.cargar2()
[Link]()
print("La suma de los dos valores es")
suma1.mostrar_resultado()

resta1=Resta()
resta1.cargar1()
resta1.cargar2()
[Link]()
print("La resta de los valores es:")
resta1.mostrar_resultado()

Variables de clase

Hemos visto como definimos atributos en una clase anteponiendo la palabra clave self:

class Persona:

def __init__(self,nombre):
[Link]=nombre

Los atributos son independientes por cada objeto o instancia de la clase, es decir si definimos tres
objetos de la clase Persona, todas las personas tienen un atributo nombre pero cada uno tiene un
valor independiente:

class Persona:

def __init__(self,nombre):
[Link]=nombre

# bloque principal

persona1=Persona("Juan")
persona2=Persona("Ana")
persona3=Persona("Luis")

print([Link]) # Juan
print([Link]) # Ana
print([Link]) # Luis
En algunas situaciones necesitamos almacenar datos que sean compartidos por todos los objetos de
dicha clase, en esas situaciones debemos emplear variables de clase.

Para definir una variable de clase lo hacemos dentro de la clase pero fuera de sus métodos:

class Persona:

variable=20

def __init__(self,nombre):
[Link]=nombre

# bloque principal

persona1=Persona("Juan")
persona2=Persona("Ana")
persona3=Persona("Luis")

print([Link]) # Juan
print([Link]) # Ana
print([Link]) # Luis

print([Link]) # 20
[Link]=5
print([Link]) # 5

Se reserva solo un espacio para la variable "variable", independientemente que se definan muchos
objetos de la clase Persona. La variable "variable" es compartida por todos los objetos
persona1,persona2 y persona3.

Para modificar la variable de clase hacemos referencia al nombre de la clase y seguidamente el


nombre de la variable:

[Link]=5

Problema:
Definir una clase Cliente que almacene un código de cliente y un nombre.
En la clase Cliente definir una variable de clase de tipo lista que almacene todos los clientes que
tienen suspendidas sus cuentas corrientes.
Imprimir por pantalla todos los datos de clientes y el estado que se encuentra su cuenta corriente.
Programa:
class Cliente:
suspendidos=[]

def __init__(self,codigo,nombre):
[Link]=codigo
[Link]=nombre

def imprimir(self):
print("Codigo:",[Link])
print("Nombre:",[Link])
self.esta_suspendido()

def esta_suspendido(self):
if [Link] in [Link]:
print("Esta suspendido")
else:
print("No esta suspendido")
print("_____________________________")

def suspender(self):
[Link]([Link])

# bloque principal

cliente1=Cliente(1,"Juan")
cliente2=Cliente(2,"Ana")
cliente3=Cliente(3,"Diego")
cliente4=Cliente(4,"Pedro")

[Link]()
[Link]()

[Link]()
[Link]()
[Link]()
[Link]()

print([Link])

La clase Cliente define una variable de clase llamada suspendidos que es de tipo lista y por ser
variable de clase es compartida por todos los objetos que definamos de dicha clase:

class Cliente:
suspendidos=[]
En el método imprimir mostramos el código, nombre del cliente y si se encuentra suspendida su
cuenta corriente:
def imprimir(self):
print("Codigo:",[Link])
print("Nombre:",[Link])
self.esta_suspendido()
El método suspender lo que hace es agregar el código de dicho cliente a la lista de clientes
suspendidos:

def suspender(self):
[Link]([Link])

El método que analiza si está suspendido el cliente verifica si su codigo se encuentra almacenado en
la variable de clase suspendidos:

def esta_suspendido(self):
if [Link] in [Link]:
print("Esta suspendido")
else:
print("No esta suspendido")
print("_____________________________")

Para probar esta clase en el bloque principal creamos cuatro objetos de la clase Cliente:

# bloque principal

cliente1=Cliente(1,"Juan")
cliente2=Cliente(2,"Ana")
cliente3=Cliente(3,"Diego")
cliente4=Cliente(4,"Pedro")

Suspendemos dos clientes:

[Link]()
[Link]()

Y luego imprimimos los datos de cada cliente:

[Link]()
[Link]()
[Link]()
[Link]()

Podemos imprimir la variable de clase suspendidos de la clase Cliente:

print([Link])

Es importante remarcar que todos los objetos acceden a una única lista llamada suspendidos gracias
a que se definió como variable de clase.
Método especial __str__

Podemos hacer que se ejecute un método definido por nosotros cuando pasamos un objeto a la
función print o cuando llamamos a la función str (convertir a string)

¿Qué sucede cuando llamamos a la función print y le pasamos como parámetro un objeto?

class Persona:
def __init__(self,nom,ape):
[Link]=nom
[Link]=ape

persona1=Persona("Jose","Rodriguez")
print(persona1)

Nos muestra algo parecido a esto:

<__main__.Persona object at 0x03E99C90>

Python nos permite redefinir el método que se debe ejecutar. Esto se hace definiendo en la clase el
método especial __str__

En el ejemplo anterior si queremos que se muestre el nombre y apellido separados por coma cuando
llamemos a la función print el código que debemos implementar es el siguiente:

class Persona:
def __init__(self,nom,ape):
[Link]=nom
[Link]=ape

def __str__(self):
cadena=[Link]+","+[Link]
return cadena

persona1=Persona("Jose","Rodriguez")
print(persona1)

Como vemos debemos implementar el método __str__ y retornar un string, este luego será el que
imprime la función print:

def __str__(self):
cadena=[Link]+","+[Link]
return cadena

Esta característica definida en Python nos permite crear programas muy legibles y flexibles.

El método __str__ también se ejecuta si llamamos a la función str y pasamos como parámetro un
objeto que tiene definido dicho método:
class Persona:
def __init__(self,nom,ape):
[Link]=nom
[Link]=ape

def __str__(self):
cadena=[Link]+","+[Link]
return cadena

# bloque principal

persona1=Persona("Jose","Rodriguez")
persona2=Persona("Ana","Martinez")
print(str(persona1)+"-"+str(persona2)) # Jose,Rodriguez-
Ana,Martinez

Problema:
Definir una clase llamada Punto con dos atributos x e y.
Crearle el método especial __str__ para retornar un string con el formato (x,y).

Programa:

class Punto:

def __init__(self, x, y):


self.x=x
self.y=y

def __str__(self):
return "("+str(self.x)+","+str(self.y)+")"

# bloque principal

punto1=Punto(10,3)
punto2=Punto(3,4)
print(punto1)
print(punto2)

La clase Punto define dos métodos especiales. El método __init__ donde inicializamos los
atributos x e y:

class Punto:

def __init__(self, x, y):


self.x=x
self.y=y
Y el segundo método especial que definimos es el __str__ que debe retornar un string. Para generar
el string debemos concatenar valores fijos como "(" y convertir a string los atributos que son enteros
mediante la función str:

def __str__(self):
return "("+str(self.x)+","+str(self.y)+")"

Luego en el bloque principal después de definir dos objetos de la clase Punto procedemos a llamar a
la función print y le pasamos cada uno de los objetos:

# bloque principal

punto1=Punto(10,3)
punto2=Punto(3,4)
print(punto1)
print(punto2)

Hay que tener en cuenta que cuando pasamos a la función print el objeto punto1 en ese momento se
llama el método especial __str__ que tiene por objetivo retornar un string que nos haga más legible
lo que representa dicho objeto.

Problema:
Declarar una clase llamada Familia. Definir como atributos el nombre del padre, madre y una lista
con los nombres de los hijos.
Definir el método especial __str__ que retorne un string con el nombre del padre, la madre y de
todos sus hijos.

Programa:
class Familia:

def __init__(self,padre,madre,hijos=[]):
[Link]=padre
[Link]=madre
[Link]=hijos

def __str__(self):
cadena=[Link]+","+[Link]
for hi in [Link]:
cadena=cadena+","+hi
return cadena

# bloque principal

familia1=Familia("Pablo","Ana",["Pepe","Julio"])
familia2=Familia("Jorge","Carla")
familia3=Familia("Luis","Maria",["marcos"])

print(familia1)
print(familia2)
print(familia3)
Para resolver este problema el método __init__ recibe en forma obligatoria el nombre del padre,
madre y en forma opcional una lista con los nombres de los hijos:

class Familia:

def __init__(self,padre,madre,hijos=[]):
[Link]=padre
[Link]=madre
[Link]=hijos

Si no tiene hijos la familia el atributo hijos almacena una lista vacía.

El método especial __str__ genera un string con los nombres del padre, madre y todos los hijos:

def __str__(self):
cadena=[Link]+","+[Link]
for hi in [Link]:
cadena=cadena+","+hi
return cadena

En el bloque principal creamos tres objetos de la clase Familia y pasamos al método __init__
distintas composiciones de familias:
# bloque principal

familia1=Familia("Pablo","Ana",["Pepe","Julio"])
familia2=Familia("Jorge","Carla")
familia3=Familia("Luis","Maria",["marcos"])

print(familia1)
print(familia2)
print(familia3)

También podría gustarte