在类中定义一个装饰器,且可在类定义中使用
我正在尝试在Python中实现一个可以继承的“子命令”系统。我的预期用法大概是这样的:
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"
我把Command.subcommand
实现成了一个静态方法,一切都运行得很好,直到我尝试给父类添加一个子命令,这时出现了TypeError: 'staticmethod' object is not callable
的错误。回想起来,很明显这个方法是行不通的:
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"
到目前为止,我找到的唯一替代方案是把subcommand
装饰器放在父类外面,然后在类定义完成后再注入它。
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
不过,作为一个在装饰器出现之前就没用过Python的人,这让我觉得很麻烦。有没有更优雅的方法来实现这个呢?
1 个回答
5
我想到这个问题有两种解决方案。最简单的办法是在你在父类中用完这个方法之后把它改成静态方法:
class Command(object):
def subcommand(method): # Regular function in class definition scope.
method.is_subcommand = True
return method
@subcommand
def common(self):
print "this subcommand is available to all child classes"
subcommand = staticmethod(subcommand)
# Now a static method. Can no longer be called during class definition phase.
这样做有点脆弱,因为一旦你把它改成静态方法,就不能在父类中再使用它了。更稳妥的做法是添加一个中间类:
class Command(object):
@staticmethod
def subcommand(method):
method.is_subcommand = True
return method
class CommandBase(Command):
@Command.subcommand
def common(self):
print "this subcommand is available to all child classes"
现在你可以让所有的类都继承自 CommandBase
,而不是 Command
。