Explicación de @classmethod y @staticmethod de Python

    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!

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *