POO: Propiedades en Python

Este documento explora las variables de instancia y de clase en Python. Se abordarán las diferencias entre estos tipos de variables, su uso adecuado y cómo afectan el comportamiento de las instancias de una clase.

POO: Propiedades en Python
poo: Propiedades en Python

Variables de Instancia

En la Programación Orientada a Objetos (POO), una variable de instancia representa un atributo propio de cada objeto, definido típicamente dentro del método constructor __init__ de la clase. Dicha variable se caracteriza por pertenecer exclusivamente a una instancia específica, lo que significa que cada objeto creado a partir de una clase posee una copia única de esta variable. Esta característica permite almacenar información particular y diferenciada para cada instancia, reflejando las características individuales de cada objeto en el contexto de la programación.

Se definen generalmente dentro del constructor de la clase, y su valor puede variar dependiendo del objeto en el que se encuentren.

Ejemplo de Uso de Variables de Instancia

                  
                    class Carro:
                        def __init__(self, marca, modelo):
                            # Variables de instancia
                            self.marca = marca
                            self.modelo = modelo
                        def mostrar_info(self):
                            print(f"Marca: {self.marca}, Modelo: {self.modelo}")
                    # Creando instancias de la clase Carro
                    carro1 = Carro("Toyota", "Corolla")
                    carro2 = Carro("Honda", "Civic")
                    # Accediendo a las variables de instancia
                    carro1.mostrar_info()  # Imprime: Marca: Toyota, Modelo: Corolla
                    carro2.mostrar_info()  # Imprime: Marca: Honda, Modelo: Civic
                  
                

En este ejemplo:

  • marca y modelo son variables de instancia, ya que se asignan a cada objeto creado de la clase Carro.
  • carro1 y carro2 son instancias de la clase, y cada una tiene sus propias versiones de marca y modelo, con valores diferentes.

Uso de Variables Privadas

En Python, cuando se utilizan dos guiones bajos (__) al inicio de una variable de instancia, se está aplicando un mecanismo llamado mangling de nombres. Este mecanismo cambia el nombre interno de la variable para evitar que sea sobrescrita o modificada accidentalmente desde fuera de la clase. Es una forma de hacer que la variable sea "privada" para la clase, aunque sigue siendo accesible internamente.

Ejemplo de Uso de Variables de Instancia con Dos Guiones Bajos

                    
                      class Carro:
                          def __init__(self, marca, modelo):
                              # Variables de instancia con mangling (privadas)
                              self.__marca = marca
                              self.__modelo = modelo
                          def mostrar_info(self):
                              print(f"Marca: {self.__marca}, Modelo: {self.__modelo}")
                          def cambiar_marca(self, nueva_marca):
                              self.__marca = nueva_marca
                      # Creando instancias de la clase Carro
                      carro1 = Carro("Toyota", "Corolla")
                      carro1.mostrar_info()  # Imprime: Marca: Toyota, Modelo: Corolla
                      # Intentando acceder a la variable de instancia directamente
                      # print(carro1.__marca)  # Esto dará error: AttributeError
                      # Accediendo a través de un método
                      carro1.cambiar_marca("Honda")
                      carro1.mostrar_info()  # Imprime: Marca: Honda, Modelo: Corolla
                    
                  

Acceso Interno

A pesar de que las variables son "privadas", Python no impide su acceso, sino que lo hace menos accesible al cambiar su nombre internamente. A través de la técnica de "name mangling", se pueden acceder de la siguiente manera:

                    
                      print(carro1._Carro__marca)  # Imprime: Honda
                    
                  

Sin embargo, no se recomienda acceder directamente a las variables privadas fuera de la clase. En lugar de eso, es preferible utilizar métodos para modificar o acceder a estos atributos.

Variables de Clase

Las variables de clase son aquellas que se definen dentro de la clase pero fuera de cualquier método. Estas variables son compartidas entre todas las instancias de la clase. Si se modifica una variable de clase, el cambio se reflejará en todas las instancias que no tengan su propia variable de instancia con el mismo nombre.

Características de las Variables de Clase

  • Valor compartido: Todas las instancias de la clase tienen acceso al mismo valor para una variable de clase.
  • Definición: Se define dentro de la clase, fuera de los métodos, con una sintaxis similar a la de cualquier otro atributo de clase.
  • Acceso: Se puede acceder a ella mediante la clase o mediante una instancia de la clase, pero si se modifica desde una instancia, esa modificación no afectará a otras instancias.

Ejemplo en Python de Variables de Clase

                  
                    class Carro:
                        # Variable de clase
                        ruedas = 4
                        def __init__(self, marca, modelo):
                            self.marca = marca
                            self.modelo = modelo
                        def mostrar_info(self):
                            print(f"{self.marca} {self.modelo} tiene {Carro.ruedas} ruedas.")
                    # Crear instancias de la clase Carro
                    carro1 = Carro("Toyota", "Corolla")
                    carro2 = Carro("Honda", "Civic")
                    # Acceder a la variable de clase
                    carro1.mostrar_info()  # Toyota Corolla tiene 4 ruedas.
                    carro2.mostrar_info()  # Honda Civic tiene 4 ruedas.
                  
                

En este ejemplo, la variable ruedas es una variable de clase, lo que significa que ambas instancias (carro1 y carro2) comparten el valor de 4 para el número de ruedas. Si se cambiara el valor de ruedas a través de la clase, todas las instancias reflejarían ese cambio.

Cambio de Valor a Variable de Clase

Para cambiar el valor de una variable de clase en Python, se puede hacer de dos maneras:

Accediendo a través de la Clase

El valor de una variable de clase se puede modificar directamente utilizando el nombre de la clase. Esta modificación afectará a todas las instancias de la clase que no hayan sobrescrito esa variable.

                    
                      class Carro:
                        # Variable de clase
                        ruedas = 4
                    # Cambiar el valor de la variable de clase
                    Carro.ruedas = 6
                    # Crear instancias de la clase Carro
                    carro1 = Carro()
                    carro2 = Carro()
                    # Ver el valor de la variable de clase
                    print(carro1.ruedas)  # 6
                    print(carro2.ruedas)  # 6
                    
                  

En este caso, la variable de clase ruedas se cambia a 6 a través de la clase Carro. Ahora, ambas instancias (carro1 y carro2) reflejan el nuevo valor de 6.

Accediendo a través de una Instancia (No Recomendado)

También es posible cambiar una variable de clase a través de una instancia de la clase. Sin embargo, este cambio no afectará a las demás instancias, ya que en realidad se creará una nueva variable de instancia para esa instancia específica.

                    
                      class Carro:
                          # Variable de clase
                          ruedas = 4
                      # Crear una instancia de la clase
                      carro1 = Carro()
                      # Cambiar la variable de clase a través de la instancia
                      carro1.ruedas = 6
                      # Crear otra instancia
                      carro2 = Carro()
                      # Ver el valor de la variable de clase
                      print(carro1.ruedas)  # 6 (modificación a nivel de instancia)
                      print(carro2.ruedas)  # 4 (variable de clase sin cambios)
                    
                  

En este caso, el valor de ruedas cambia a 6 para carro1, pero la variable de clase ruedas sigue siendo 4 para carro2. Esto sucede porque al acceder a la variable de clase a través de la instancia, Python crea una nueva variable de instancia local a esa instancia.

Diferencia con las Variables de Instancia

  • Variables de instancia: Son atributos que pertenecen a un objeto específico. Cada instancia tiene su propio valor para esas variables.
  • Variables de clase: Son compartidas por todas las instancias de una clase.

Comprobando la Existencia de un Atributo

En Python, se pueden usar varias técnicas para comprobar si un objeto o una clase tiene un atributo específico. Algunas de las formas más comunes de hacer esto son:

Usando hasattr()

La función hasattr() permite verificar si un objeto o clase tiene un atributo determinado. Devuelve True si el atributo existe y False si no.

                  
                    hasattr(objeto, "atributo")
                  
                

Ejemplo:

                  
                    class Carro:
                        def __init__(self, marca):
                            self.marca = marca
                    carro1 = Carro("Toyota")
                    # Comprobar si carro1 tiene el atributo 'marca'
                    print(hasattr(carro1, "marca"))  # True
                    # Comprobar si carro1 tiene el atributo 'modelo'
                    print(hasattr(carro1, "modelo"))  # False
                  
                

En este caso, hasattr(carro1, "marca") devuelve True porque el objeto carro1 tiene el atributo marca, mientras que hasattr(carro1, "modelo") devuelve False porque no tiene un atributo llamado modelo.

Usando getattr() con un valor por defecto

La función getattr() se utiliza para obtener el valor de un atributo, y si el atributo no existe, puede devolver un valor por defecto en lugar de lanzar una excepción. Esto también permite comprobar si el atributo existe.

                  
                    getattr(objeto, "atributo", valor_por_defecto)
                  
                

Ejemplo:

                  
                    class Carro:
                        def __init__(self, marca):
                            self.marca = marca
                    carro1 = Carro("Toyota")
                    # Usando getattr para comprobar si el atributo 'modelo' existe
                    modelo = getattr(carro1, "modelo", None)
                    # Si el atributo no existe, se devuelve 'None'
                    print(modelo)  # None
                  
                

En este caso, getattr(carro1, "modelo", None) devuelve None porque el atributo modelo no existe en carro1.

Usando __dict__

El atributo especial __dict__ de un objeto contiene todos los atributos de instancia del objeto. Puedes verificar si un atributo específico está presente en __dict__.

Ejemplo:

                  
                    class Carro:
                        def __init__(self, marca):
                            self.marca = marca
                    carro1 = Carro("Toyota")
                    # Comprobar si el atributo 'marca' existe en __dict__ de carro1
                    print("marca" in carro1.__dict__)  # True
                    # Comprobar si el atributo 'modelo' existe en __dict__ de carro1
                    print("modelo" in carro1.__dict__)  # False
                  
                

En este ejemplo, se utiliza carro1.__dict__ para comprobar si los atributos marca y modelo están en el diccionario de atributos de la instancia.

Resumen

  • codehasattr(): Comprueba si un objeto tiene un atributo determinado.
  • getattr(): Permite obtener un atributo y proporciona un valor por defecto si no existe.
  • __dict__: Proporciona un diccionario con los atributos de la instancia, que se puede usar para verificar si un atributo existe.

COMENTARIOS

Si tiene alguna inquietud, duda o ha encontrado algún error, por favor infórmelo a través del formulario disponible para este propósito.

La política de privacidad, y los términos y condiciones están disponibles en el formulario de contacto.