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
Contenido
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.
Te puede interesar:Explicación de los entornos virtuales de PythonEl 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:
Te puede interesar:Procesamiento paralelo en Python# 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!
Te puede interesar:Sirviendo archivos estáticos con Flask