Métodos estáticos y de clase
Parte de la sección Programación orientada a objetos del Journey de Python de Coddy. Lección 39 de 64.
Además de los métodos de instancia habituales, las clases pueden tener métodos estáticos y métodos de clase que cumplen distintas funciones.
Aquí tienes un ejemplo de un método estático:
class MathHelper:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def is_even(number):
return number % 2 == 0Los métodos estáticos no necesitan self y funcionan como funciones normales. Llámalos directamente desde la clase:
result = MathHelper.add(5, 3)
print(result)
check = MathHelper.is_even(10)
print(check)Aquí tienes un ejemplo de un método de clase:
class Person:
count = 0 # Variable de clase
def __init__(self, name):
self.name = name
Person.count += 1
@classmethod
def get_count(cls):
return cls.count
@classmethod
def create_anonymous(cls):
return cls("Anonymous")Los métodos de clase reciben la propia clase (cls) como primer parámetro:
person1 = Person("Alice")
person2 = Person("Bob")
print(Person.get_count()) # 2Usa métodos de clase como constructores alternativos:
anonymous = Person.create_anonymous()
print(anonymous.name) # Anonymous
print(Person.get_count()) # 3Compara los tres tipos de métodos en una sola clase:
class Calculator:
brand = "Python Calc"
def __init__(self, owner):
self.owner = owner
# Método de instancia - necesita self y accede a los datos de la instancia
def show_owner(self):
return f"Owned by {self.owner}"
# Método de clase - necesita cls y accede a los datos de la clase
@classmethod
def get_brand(cls):
return cls.brand
# Método estático - no necesita ninguno de los dos; es solo una función auxiliar
@staticmethod
def multiply(x, y):
return x * ycalc = Calculator("Alice")
print(calc.show_owner()) # Propiedad de Alice
print(Calculator.get_brand()) # Python Calc
print(Calculator.multiply(4, 5)) # 20Salida:
8
True
2
Anonymous
3
Owned by Alice
Python Calc
20También puedes llamar a métodos de clase y estáticos desde instancias:
calc = Calculator("Bob")
print(calc.get_brand()) # Python Calc
print(calc.multiply(2, 3)) # 6Diferencias clave:
- Métodos de instancia: Necesitan
selfy acceden a los datos de la instancia - Métodos de clase: Necesitan
cls, acceden a los datos de la clase y son útiles para constructores alternativos - Métodos estáticos: No necesitan ninguno de los dos; son simplemente funciones de utilidad relacionadas con la clase
Punto clave: Usa @staticmethod para funciones auxiliares que pertenecen lógicamente a la clase, pero no necesitan datos de la clase ni de la instancia. Usa @classmethod cuando necesites acceder a la propia clase, por ejemplo, para constructores alternativos o para acceder a variables de clase.
Desafío
FácilEn este desafío, implementarás una clase Temperature con funcionalidades específicas y aprovecharás un marco de pruebas completo.
Debes editar solo el archivo temperature.py, siguiendo los comentarios TODO que guían tu implementación. La clase debe incluir:
- Una variable de clase para llevar un registro de las lecturas de temperatura
- Un método estático para convertir temperaturas
- Métodos de clase para añadir lecturas y calcular promedios
Pruébalo tú mismo
from temperature import Temperature
# Gestor de casos de prueba para realizar pruebas exhaustivas
test_case = input()
if test_case == "default_test":
# Prueba la funcionalidad básica
Temperature.celsius_readings = []
Temperature.add_reading(25)
Temperature.add_reading(30)
Temperature.add_reading(27)
print(f"Average reading: {Temperature.average_reading()}")
print(f"22°C is {Temperature.celsius_to_fahrenheit(22)}°F")
elif test_case == "empty_readings":
# Prueba average_reading sin lecturas
Temperature.celsius_readings = []
print(f"Average reading: {Temperature.average_reading()}")
elif test_case == "single_reading":
# Prueba con una sola lectura
Temperature.celsius_readings = []
Temperature.add_reading(100)
print(f"Average reading: {Temperature.average_reading()}")
elif test_case == "negative_values":
# Prueba con valores de temperatura negativos
Temperature.celsius_readings = []
Temperature.add_reading(-10)
Temperature.add_reading(-20)
Temperature.add_reading(-30)
print(f"Average reading: {Temperature.average_reading()}")
print(f"-15°C is {Temperature.celsius_to_fahrenheit(-15)}°F")
elif test_case == "zero_value":
# Prueba con una lectura de 0°C
print(f"0°C is {Temperature.celsius_to_fahrenheit(0)}°F")
elif test_case == "extreme_values":
# Prueba con valores de temperatura extremos
absolute_zero = -273.15 # cero absoluto en grados Celsius
sun_surface = 5500 # temperatura aproximada de la superficie del Sol en grados Celsius
print(f"{absolute_zero}°C is {Temperature.celsius_to_fahrenheit(absolute_zero)}°F")
print(f"{sun_surface}°C is {Temperature.celsius_to_fahrenheit(sun_surface)}°F")
elif test_case == "reset_readings":
# Prueba el restablecimiento de las lecturas
Temperature.celsius_readings = []
Temperature.add_reading(10)
Temperature.add_reading(20)
Temperature.add_reading(30)
print(f"Average reading before reset: {Temperature.average_reading()}")
Temperature.celsius_readings = []
print(f"Average reading after reset: {Temperature.average_reading()}")
elif test_case == "decimal_values":
# Prueba con valores decimales
Temperature.celsius_readings = []
Temperature.add_reading(36.5) # Temperatura corporal normal
Temperature.add_reading(37.2) # Fiebre leve
Temperature.add_reading(36.9) # Variación normal
print(f"Average reading: {Temperature.average_reading()}")
elif test_case == "many_readings":
# Prueba con muchas lecturas
Temperature.celsius_readings = []
for i in range(1, 101):
Temperature.add_reading(i)
print(f"Average reading with 100 values: {Temperature.average_reading()}")Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de la POO
Introducción a la POOArchivos externosClases vs. objetosEl parámetro selfMétodosAtributosMétodo constructor (__init__)Repaso: calculadora sencilla4Herencia
Herencia básicaLa función super()Sobrescritura de métodosHerencia múltipleOrden de resolución de métodosRepaso: jerarquía de empleados7Métodos especiales
Introducción a los métodos mágicosSobrecarga de operadoresMétodos mágicos de contenedoresRepaso: lista personalizada10Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy2Decoradores
Introducción a los decoradoresDecorador de propiedadDecorador de método estáticoDecorador de método de clase5Polimorfismo
Repaso de la sobrescritura de métodosTipado patoClases y métodos abstractosDiseño de interfacesRepaso: calculadora de formas8Conceptos avanzados de POO
Composición frente a herenciaMixinsMétodos estáticos y de claseDecoradores de claseGestores de contexto11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Propiedades de clase
Variables de instancia vs. variables de claseDecoradores de propiedadesAtributos privadosRepaso: gestor de cuentas bancariasPractica por tu cuenta: Compilador de Python online