Usando decoradores en Python para recopilar información sobre los métodos disponibles y almacenar esos datos en la clase o instancia.
Encontré muchas preguntas relacionadas con los decoradores y las clases, y el acceso a la instancia de clase que está siendo decorada. Según pude entender, el generador de decoradores no puede acceder a la instancia del objeto porque, en ese momento, aún no se ha creado ningún objeto.
Sin embargo, parece que si un decorador utiliza una referencia de clase (me refiero a que recibe cls
), entonces puedo acceder a algunos campos de clase:
class Foo:
_tags = {}
@classmethod
def _tag(cls, tag_name):
def decorator(func):
def tmp(*args, **kwargs):
return func(*args, **kwargs)
cls._tags[tag_name] = func.__name__
return tmp
return decorator
Esto funciona de maravilla para las subclases, donde puedo escribir:
@Foo._tag("something")
def somethingelse():
pass
Pero esto almacena la información en la clase padre (como era de esperar), ya que estamos hablando de variables de clase.
Me pregunto si hay alguna manera de tener un comportamiento similar, pero garantizando que cada subclase tenga su propia instancia de la propiedad _tags
.
Puedo anticipar algunos métodos alternativos, como analizar el código fuente o inspeccionar las funciones durante __init__
. Pero estaba buscando una forma más sencilla, si existe una.
Edit 1: para que quede más claro, quiero decorar métodos de la subclase. Por lo tanto, esto no es una posibilidad:
class Bar(Foo):
@Bar._tag("method")
def method(self):
pass
ya que el procesador/compilador aún no ha completado la creación de la clase. De lo contrario, la solución propuesta de un diccionario de dos niveles con clase/método funcionaría lo suficientemente bien para mí.
SOLUCIÓN ALTERNATIVA
Mi decorador:
@classmethod
def TAG(cls, name):
def decorator(func):
def tmp(*args, **kwargs):
return func(*args, **kwargs)
tmp._has_alias = name
return tmp
return decorator
Durante __init__
, obtengo esta información y la almaceno:
self._tags = {getattr(self, name)._has_alias: name for name in dir(self) if callable(getattr(self, name)) and hasattr(getattr(self, name), "_has_alias")}
davy.ai
La pregunta se trata sobre los decoradores en Python y su acceso a las instancias de clase. Se afirma que los generadores de decoradores no pueden acceder a las instancias de los objetos ya que aún no se ha creado ningún objeto. Sin embargo, el uso de una referencia de clase en un decorador puede proporcionar acceso a algunos campos de clase.
Se proporciona un código de ejemplo que utiliza un método de clase y un decorador para almacenar información en variables de clase. La pregunta es si hay alguna manera de asegurarse de que cada subclase tenga su propia instancia de la propiedad
_tags
.La solución propuesta por el autor es utilizar un decorador con un nombre de etiqueta que se almacena en el atributo
_has_alias
de la función. Durante__init__
, esta información se recupera y se almacena en un diccionario específico para la instancia de la clase.