Saltar la navegación

4.1. La clase es la fuente del objeto

1. Pidiendo acceso a datos

Ya hemos adelantado que el paradigma de programación POO modela los elementos como objetos que interactúan entre ellos. También hemos visto que los objetos son como cajas que contienen una serie de datos que son características (atributos) y acciones que se pueden realizar sobre ellas (métodos). Vamos a trasladarlo ahora a una concreción en el código de nuestros programas para poder trabajar con estos objetos. En grupo de trabajo, mirad atentamente la información que aparece a continuación para poder después responder a las cuestiones planteadas:

ACCESO A ATRIBUTOS

objeto.atributo

ACCESO A MÉTODOS

objeto.método(parámetros)

Para responder a las siguientes cuestiones, se recomienda trabajar en grupo consultando primero la información proporcionada en los enlaces, poniendo en común lo observado y en base a ello poder dar respuesta a lo pedido con la posterior prueba de funcionamiento del código en el IDE.

Debéis saber que en Python los tipos de datos son también objetos que tienen asociados atributos y métodos. Por ejemplo, los tipos de datos Str (cadena) y Lista (estructura de datos). Aprenderéis cómo trabajar con ellos siguiendo los pasos a continuación para dar con la respuesta pedida:

¿Conseguís obtener estos resultados?

Aparece un código en Pycharm para pasar una cadena a mayúsculas Añadir elemento a lista


  1. Consultad en la documentación de Python en español los métodos (operaciones) definidos para un objeto de tipo cadena: tipo str
  2. ¿Cómo convertiríais la cadena c = 'Python' en mayúsculas para pobtener c = 'PYTHON'? ¿Qué método utilizaríais?
  3. Consultad en la documentación de Python en español los métodos (operaciones) definidos para un objeto de tipo estructura lista: tipo estructura lista
  4. ¿Qué método utilizaríais para añadir un elemento al final de la lista?

2. De tal clase, tal objeto

En nuestro reto hablamos de crear una aplicación que verifique la seguridad de una contraseña. Para desarrollarlo, y conforme a la filosofía POO que estamos tratando, miraremos a la contraseña como a un objeto. Pero, para poder definirla como tal, necesitamos especificar sus atributos, sus métodos (lo que se puede hacer con ella) y cómo crearla. Conozcamos entonces las estructuras de código para realizar esto:

Clases

Los objetos con los mismos atributos y métodos se agrupan clases. Las clases definen los atributos y los métodos de los que constan todos los objetos que pertenezcan a ella. Se puede pensar en una clase como en un molde a partir del cuál se pueden crear objetos. Este molde o plantilla es la que contiene la información; características y capacidades que tendrá el objeto que sea creado a partir de ella.

Imagen con el código de declaración de una clase en PycharmPara declarar una clase se utiliza la palabra clave class seguida del nombre de la clase y dos puntos.
Los atributos se definen igual que las variables mientras que los métodos se definen igual que las funciones. Tanto unos como otros tienen que estar indentados por 4 espacios en el cuerpo de la clase y además, es una buena práctica comenzar el nombre de una clase con mayúsculas.

Por ejemplo

Si queremos definir la clase Persona que contenga el nombre de la persona y su nacionalidad, y te permita mostrar dicha información de la persona por pantalla, debemos escribir el código:

>>> class Persona:
nombre = ''
ciudad = ''
def imprime_nombre(self):
print (self.nombre)
def imprime_ciudad(self):
print (self.ciudad)

Instanciación de objetos

Para usar los objetos, el primer paso será declarar la clase a la cual pertenecen empleando la palabra clave class. Los objetos compartirán las características y comportamientos comunes definidos por la clase.

Para crear un objeto de una determinada clase se utiliza el nombre de la clase seguida de los parámetros (si los necesita) para crear el objeto entre paréntesis:

objeto = clase (parámetros)Cuando se crea un objeto de una clase se dice que el objeto es una instancia de la clase.

Por ejemplo

Si creamos una instancia de la clase persona definida en la pestaña anterior, escribiremos el siguiente código (¡no olvides probarlo en tu IDE!)

>>> Pepe = Persona() #Creación del objeto Pepe
>>> Pepe #Veamos su valor
<__main__.Persona object at 0x0000016219279F10> #Nos
#da la posición de memoria donde se crea el objeto
>>> type (Pepe) #Comando para saber el tipo de variable
<class '__main__.Persona'> #Clase del objeto devuelta.

Definición de métodos

Los métodos de una clase son las funciones que definen el comportamiento de los objetos de esa clase. Los métodos se definen con la palabra reservada def.

Imagen con el código de definición de un método en una claseAhora tendremos un primer parámetro especial: self. Este parámetro hace siempre referencia al objeto desde donde se llama al método y deberá aparecer como primer parámetro de todas las funciones (métodos) asociadas a una clase.

¿Por qué existe el parámetro self? Este parámetro es necesario porque cuando Python llama a un método de un objeto, el sistema llama al método definido en la clase del objeto, pasando como primer argumento el propio objeto, que es el parámetro self. (Es como si el sistema hiciese una llamada: clase.método(objeto, parámetros)).

Por ejemplo

Si queremos inicializar el atributo ciudad de la clase Persona, con la que venimos trabajando, podemos añadir un método más del siguente modo:

>>> class Persona:
nombre = ''
ciudad = ''
def imprime_nombre(self):
print (self.nombre)
def imprime_ciudad(self):
print (self.ciudad)
def actualiza_ciudad(self, ciudad):
self.ciudad=ciudad
print("La nueva ciudad es: ", self.ciudad)
>>> Pepe=Persona()
>>> Pepe.actualiza_ciudad("Burgos")
La nueva ciudad es: Burgos
ObservaATENCIÓN: Si necesitásemos acceder a los atributos o métodos de una clase en su propia definición (con class) se puede utilizar la sintaxis self.atributo o self.método.

3. Ya vienen de fábrica

En Python existen clases predefinidas para los tipos de datos primitivos. Intenta unir el nombre de cada una con el tipo de dato al que representan:

Nombre

clase

Tipo de dato
Clase de los números enteros.
Clase de los números reales.
Clase de las cadenas de caracteres.
Clase de las listas.
Clase de las tuplas.
Clase de los diccionarios

Habilitar JavaScript

4. Una contraseña con clase

Imagen en la que aparece una captura de pantalla de un  generador de contraseñas con un ejemplo de contraseña fuerteAcabamos de aprender cómo crear objetos en Python para modelar nuestros programar y crear el código. Tenemos para ellos atributos con las características y métodos con su comportamiento.

Ahora, en grupo, vais a utilizar lo visto para realizar el modelo y su código del objeto contraseña:

  • ¿Qué atributos necesitáis definir?
  • Realizad un diagrama de la clase contraseña con los atributos y métodos que consideréis que necesita. Presentad vuestro modelo al grupo clase. Para la presentación podéis elegir el formato que os resulte más apropiado: usar algún soporte tecnológico, presentar el diagrama hecho a mano, hacerlo de forma oral, o cualquier otro formato que penséis que es acertado. 

Recordad que anteriormente hemos visto la conveniencia de no tener datos prefijados, sino que su valor se especifique posteriormente desde el propio programa. Entonces:

  • Si en el propio programa instanciamos un objeto contraseña, al que llamaremos por el nombre de la clase, ¿creéis que será necesario pasarle algún parámetro?
  • ¿De qué dos maneras se os ocurre que podríamos iniciar los valores de los atributos al instanciar el objeto contraseña? Consensuad al menos dos formas de instanciar y cuántos parámetros necesitaría recibir la llamada a la clase en cada caso.

Lumen dice ¿Necesitáis una pista?

  • A la hora de seleccionar los atributos: Tened en cuenta que la contraseña debe tener cierta seguridad dada un requisito básico que nos suelen pedir en todas las aplicaciones al crearla...
  • A la hora de pensar dos formas diferentes de crear el objeto mediante llamada a clase con parámetros haced una similitud: cuando reseteáis vuestra contraseña en alguna aplicación, por olvido por ejemplo, a veces podéis elegirla y a veces no...

5. Objeto en construcción...

Imagen con un marco de cinta amarilla y negra en el que se incluye la palabra classSegún el esquema de definición de una clase visto hasta ahora, al instanciar un objeto de dicha clase éste ya dispone de un valor dado a sus atributos en la propia definición de la clase. Lo hemos visto anteriormente en el ejemplo de definición de la clase Persona que contenía dos cadenas de caracteres vacías. Estos atributos podían cambiar su valor posteriormente en el código del programa mediante la correspondiente llamada al método que los modifica.

Sin embargo, es muy frecuente querer dar valores iniciales a los atributos de un objeto en el momento de crearlo. Una alternativa más elegante que hacerlo a posteriori llamando a los correspondientes métodos, es diseñar un método especial: un constructor, que se encarga de dicha tarea. Dicho constructor es el método __init__, vamos a conocerlo:

El método __init__

En la definición de una clase suele utilizarse un método llamado __init__ que se conoce como constructor. Este método es un método especial que se llama cada vez que se instancia una clase y sirve para inicializar el objeto que se crea. Este método crea los atributos que deben tener todos los objetos de la clase y por tanto contiene los parámetros necesarios para su creación, pero no devuelve nada. Se invoca cada vez que se instancia un objeto de esa clase. A la derecha puedes ver un ejemplo de sintaxis que utiliza un constructor para la clase Tarjeta:

>>>class Tarjeta:
def __init__(self,num,cantidad = 0):
# Arriba: Inicializador-> si no se pasa cantidad, es 0
self.num = num # Creación del atributo num
self.saldo = cantidad
# Arriba: Creación del atributo saldo

def mostrar_saldo(self):
print ('El saldo es', self.saldo, '€')
# A continuación:Creación de un objeto con argumentos
>>> t = Tarjeta('123456789', 20)
# A continuación:Creación de un objeto sin argumentos
>>> t.mostrar_saldo()
El saldo es 20 €

Atributos de instancia vs atributos de clase

Los atributos que se crean dentro del método __init__ se conocen como atributos del objeto, mientras que los que se crean fuera de él se conocen como atributos de la clase. Mientras que los primeros son propios de cada objeto y por tanto pueden tomar valores distintos, los valores de los atributos de la clase son los mismos para cualquier objeto de la clase. A la derecha puedes ver un ejemplo de sintaxis que utiliza un atributo de clase SALDO y un atributo de instancia num para la clase Tarjeta:

>>>class Tarjeta:
SALDO = 0
# Arriba: Creación del atributo de clase saldo

def __init__(self,num):
# Arriba: Inicializador
self.num = num
# Arriba: Creación del atributo num
def mostrar_saldo(self):
print ('El saldo es', self.saldo, '€')
def actualiza_saldo (self, cantidad) :
self.saldo = cantidad
print ('El nuevo saldo es', self.saldo, '€')

# Creación del objeto con argumento
>>> t = Tarjeta('123456789')
# Creación del objeto sin argumento
>>> t.mostrar_saldo()
El saldo es 0 €

OJO!En general, no deben usarse atributos de clase, excepto para almacenar valores constantes. Las constantes se suelen indicar con nombres en mayúsculas.

6. Objeto mío, ¿qué contienes?

A continuación vas a realizar una práctica guiada para presentarte a otro método especial: el método __str__

Aparece el mensaje con un número extraño: Tarjeta object at 0x000001FD092CEFD0Sigue los pasos indicados a continuación:

  1. Abre tu entorno Pycharm y escribe el código de la clase Tarjeta que contiene sólo atributos de instancia del punto anterior.
  2. Instancia un objeto de dicha clase (la línea de instanciación aparece en el propio cuadro de código donde definimos la clase en el punto anterior).
  3. Imprime por pantalla la variable objeto. Es decir: si la variable la has llamado 't', ejecuta el comando print (t).

Seguramente hayas obtenido un código como el de la imagen izquierda.... ¿Sabes a qué se debe?¿Qué representa el número obtenido?

Ahora:

  1. Añade el siguiente método a tu clase:
    def __str__(self):
    return ('Tarjeta número %s con saldo %.2f €' % (self.id, self.saldo))
  2. Imprime de nuevo el objeto por pantalla como te indicábamos en el apartado 3 anterior.

¿Qué aparece ahora?¿Podrías explicar por qué ocurre esto?

Kardia dice Para saber la explicación

Otro método especial es el método llamado __str__ que se invoca cada vez que se llama a las funciones print o str. Devuelve siempre una cadena que se suele utilizar para dar una descripción informal del objeto. Si no se define en la clase, cada vez que se llama a estas funciones con un objeto de la clase, se muestra por defecto la posición de memoria del objeto.

Utilizamos la palabra clave return porque el método __str__ debe devolver una cadena de caracteres.

7. Consigue construir el constructor

¡Es tu turno! Toma tus herramientas Python y Pycharm y lánzate a crear un constructor mediante el método __init__ aprendido. A continuación tienes las especificaciones de la clase y de su inicialización.

Vas a trabajar con una clase llamada Password que usaremos para crear contraseñas. Esta clase Password no constará de momento de ningún atributo de clase como constante.

Deberás realizar 3 acciones para crear el código de este programa:

Codificamos el constructor

El constructor de la clase que vas a codificar debe cumplir las tres especificaciones siguientes:

Especificación primera

El constructor debe permitir ser llamado de dos formas: pasando una contraseña inicial elegida o ser llamado sin ningún parámetro.

Especificación segunda

Si se instancia el objeto pasando una contraseña se inicializarán sus atributos de objeto a:

  1. El atributo passwd para la contraseña toma el valor de la contraseña recibida.
  2. El atributo long para la longitud de la contraseña toma el valor de la longitud de la contraseña recibida.

Especificación tercera

Si se instancia el objeto mediante llamada al constructor sin pasar ningún parámetro, en ese caso:

  1. Se debe pedir por pantalla la longitud deseada para la clave, en ningún caso menor de 8.
  2. Se llamará al método genera_passwd() que calculará una contraseña al azar con la longitud recomendada.

Creamos el método  genera_passwd()

En este segundo pasado deberás utilizar como método el programa que creaste en el ítem 4 del apartado 3. Sumérgete en un nuevo entorno.

Tendrás que añadirle dos modificaciones:

  • La longitud es la especificada en el atributo long del objeto creado.
  • El método debe devolver la variable cadena de caracteres con la contraseña creada.

Crea el método __str__

Añade a tu clase Passwd un método __str__ con el que obtengas el siguiente resultado por pantalla:

Se obtiene como resultado por pantalla el mensaje: Contraseña O5bHkJHC con longitud 8

Lumen dice Varias pistas que ayudan...

  1. Para calcular la longitud de una cadena de caracteres, busca la función adecuada en las funciones por defecto de Python:
    https://docs.python.org/3/library/functions.html
  2. No olvides que para acceder desde un método de un objeto a un atributo del mismo objeto no hace falta que el método reciba ningún parámetro. Sólo tienes que hacer referencia al atributo mediante, por ejemplo en este caso: self.long.
  3. Recuerda que para que una función o método devuelva un valor debes utilizar el comando return seguido del nombre de la variable que se devuelve, como vimos en recursos anteriores.
  4. Prueba tu programa instanciando el objeto Passwd con los comandos:
t = Password()
print(t)
t = Password('Contraseña_ejemplo")
print(t)

Clavis dice Te ayudo a organizarte

En ejercicios de este tipo hay que intentar ser práctico porque pueden ser muy complejos si sabes muchas cosas. Por ello, es recomendable que antes responder pienses en aspectos como los siguientes:

¿Sabes lo que se pide?
¿Te acuerdas de lo que debes hacer en estos casos?
¿Se te da bien organizar?
¿Te gusta hacer las cosas de forma detallada?
¿Puedes acordarte de algún otro ejercicio parecido que hayas hecho?
¿Hay algo que ya hayas usado para un ejercicio parecido?
¿Se te da bien programar?
Pensar sobre lo que sabes hacer y comentarlo a las compañeras y compañeros facilita poner en marcha las habilidades necesarias para responder a este tipo de tareas. Recuerda que es una buena estrategia cuando te piden que crees o inventes algo.