Estoy tratando de implementar un sistema de "subcomando" como una clase heredable en Python. Mi caso de uso esperado es algo así como:Definir un decorador en una clase, que también se puede usar dentro de la definición de clase
from command import Command
import sys
class MyCommand(Command):
@Command.subcommand
def foo(self):
print "this can be run as a subcommand"
def bar(self):
print "but this is a plain method and isn't exposed to the CLI"
MyCommand()(*sys.argv)
# at the command line, the user runs "mycommand.py foo"
he implementado Command.subcommand
como un método estático y todo funcionaba bien hasta que he intentado añadir un subcomando a la clase padre, que me consiguió TypeError: 'staticmethod' object is not callable
. En retrospectiva, es obvio que no va a funcionar this:
class Command(object):
@staticmethod
def subcommand(method):
method.is_subcommand = True
return method
@subcommand
def common(self):
print "this subcommand is available to all child classes"
La única alternativa que he encontrado hasta ahora es declarar el decorador subcommand
fuera de la clase padre, y luego inyectarla después de la definición de clase se ha completado.
def subcommand(method):
method.is_subcommand = True
return method
class Command(object):
@subcommand
def common(self):
print "this subcommand is available to all child classes"
Command.subcommand = staticmethod(subcommand)
del subcommand
Sin embargo, como alguien que nunca utiliza Python antes de añadir decoradores, esto se siente muy torpe para mí. ¿Hay una forma más elegante de lograr esto?
Bueno, la primera pregunta es por qué implementa un decorador como método en una clase, a menos que esa clase se use para un grupo de decoradores. Y si para eso sirve, ¿por qué decoras el decorador "común"? Parece torpe, probablemente porque el diseño de tu clase es un poco extraño ... :) –
¿Qué esperas exactamente que logre este decorador por ti? Python ya sabe cuáles son los subcomandos, porque sabe qué clases son subclases de otros. –
@Lennart - puramente para la estética de importación. No era fanático de 'Importar comando ... clase MyCommand (comando.Comando)' (se siente redundante) o 'desde comando importar * ... @ subcomando' (parece que está contaminando el espacio de nombres). –