Explicación de @classmethod y @staticmethod de Python

E

Python es un lenguaje único en el sentido de que es bastante fácil de aprender, dada su sintaxis sencilla, pero aún extremadamente poderoso. Hay muchas más funciones bajo el capó de las que te imaginas. Si bien podría estar refiriéndome a bastantes cosas diferentes con esta declaración, en este caso estoy hablando de la decoradores @classmethod y @staticmethod. Para muchos de sus proyectos, probablemente no necesitó o no encontró estas características, pero puede encontrar que son útiles un poco más de lo que esperaba. No es tan obvio cómo crear métodos estáticos de Python, que es donde entran estos dos decoradores.

En este artículo te contaré qué hace cada uno de estos decoradores, sus diferencias y algunos ejemplos de cada uno.

El decorador @classmethod

Este decorador existe para que pueda crear métodos de clase que se pasan al objeto de clase real dentro de la llamada a la función, al igual que self se pasa a cualquier otro método de instancia ordinario en una clase.

En esos métodos de instancia, el self El argumento es el objeto de instancia de clase en sí mismo, que luego se puede usar para actuar sobre los datos de instancia. @classmethod Los métodos también tienen un primer argumento obligatorio, pero este argumento no es una instancia de clase, en realidad es la propia clase no autenticada. Entonces, mientras que un método de clase típico podría verse así:

class Student(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

scott = Student('Scott',  'Robinson')

Un similar @classmethod El método se usaría así en su lugar:

class Student(object):

    @classmethod
    def from_string(cls, name_str):
        first_name, last_name = map(str, name_str.split(' '))
        student = cls(first_name, last_name)
        return student

scott = Student.from_string('Scott Robinson')

Esto sigue el patrón de fábrica estática muy bien, encapsulando la lógica de análisis dentro del método mismo.

El ejemplo anterior es muy simple, pero puede imaginar ejemplos más complicados que lo hacen más atractivo. Imagina si un Student El objeto se puede serializar en muchos formatos diferentes. Puede usar esta misma estrategia para analizarlos todos:

class Student(object):

    @classmethod
    def from_string(cls, name_str):
        first_name, last_name = map(str, name_str.split(' '))
        student = cls(first_name, last_name)
        return student

    @classmethod
    def from_json(cls, json_obj):
        # parse json...
        return student

    @classmethod
    def from_pickle(cls, pickle_file):
        # load pickle file...
        return student

El decorador se vuelve aún más útil cuando te das cuenta de su utilidad en subclases. Dado que el objeto de la clase se le proporciona dentro del método, aún puede usar el mismo @classmethod también para subclases.

El decorador de @staticmethod

los @staticmethod decorador es similar a @classmethod en que se puede llamar desde un objeto de clase no autenticado, aunque en este caso no hay cls parámetro pasado a su método. Entonces, un ejemplo podría verse así:

class Student(object):

    @staticmethod
    def is_full_name(name_str):
        names = name_str.split(' ')
        return len(names) > 1

Student.is_full_name('Scott Robinson')   # True
Student.is_full_name('Scott')            # False

Desde que no self El objeto tampoco se pasa, eso significa que tampoco tenemos acceso a ningún dato de instancia y, por lo tanto, este método tampoco se puede llamar en un objeto instanciado.

Estos tipos de métodos no suelen estar destinados a crear / instanciar objetos, pero pueden contener algún tipo de lógica perteneciente a la clase en sí, como un método auxiliar o de utilidad.

@classmethod vs @staticmethod

Lo más obvio entre estos decoradores es su capacidad para crear métodos estáticos dentro de una clase. Estos tipos de métodos se pueden llamar en objetos de clase no autenticados, al igual que las clases que usan el static palabra clave en Java.

En realidad, solo hay una diferencia entre estos dos decoradores de métodos, pero es una de las principales. Probablemente hayas notado en las secciones anteriores que @classmethod los métodos tienen un cls parámetro enviado a sus métodos, mientras @staticmethod los métodos no lo hacen.

Esta cls parámetro es el objeto de clase del que hablamos, que permite @classmethod métodos para crear instancias de la clase fácilmente, independientemente de la herencia. La falta de esto cls parámetro en @staticmethod los métodos los convierten en verdaderos métodos estáticos en el sentido tradicional. Su objetivo principal es contener lógica perteneciente a la clase, pero esa lógica no debería tener ninguna necesidad de datos de instancia de clase específicos.

Un ejemplo más extenso

Ahora veamos otro ejemplo en el que usamos ambos tipos juntos en la misma clase:

# static.py

class ClassGrades:

    def __init__(self, grades):
        self.grades = grades

    @classmethod
    def from_csv(cls, grade_csv_str):
        grades = map(int, grade_csv_str.split(', '))
        cls.validate(grades)
        return cls(grades)


    @staticmethod
    def validate(grades):
        for g in grades:
            if g < 0 or g > 100:
                raise Exception()

try:
    # Try out some valid grades
    class_grades_valid = ClassGrades.from_csv('90, 80, 85, 94, 70')
    print 'Got grades:', class_grades_valid.grades

    # Should fail with invalid grades
    class_grades_invalid = ClassGrades.from_csv('92, -15, 99, 101, 77, 65, 100')
    print class_grades_invalid.grades
except:
    print 'Invalid!'
$ python static.py
Got grades: [90, 80, 85, 94, 70]
Invalid!

Observe cómo los métodos estáticos pueden incluso funcionar junto con from_csv vocación validate utilizando la cls objeto. Ejecutar el código anterior debería imprimir una serie de calificaciones válidas y luego fallar en el segundo intento, imprimiendo así “¡No válido!”.

Conclusión

En este artículo viste cómo tanto el @classmethod y @staticmethod Los decoradores trabajan en Python, algunos ejemplos de cada uno en acción y en qué se diferencian entre sí. Con suerte, ahora puede aplicarlos a sus propios proyectos y utilizarlos para continuar mejorando la calidad y organización de su propio código.

¿Alguna vez ha usado estos decoradores antes, y si es así, cómo? ¡Háznoslo saber en los comentarios!

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con tus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad