我正在尝试设置一些装饰器,以便我可以执行以下操作:
class Ball(object):
def __init__(self, owner):
self.owner = owner
class Example(CommandSource):
@command
@when(lambda self, ball: ball.owner == self)
def throwBall(self, ball):
# code to throw the ball
pass
e = Example()
ball = Ball(e)
commands = e.listCommands(ball) # commands = [ 'throwBall' ]
这当前不起作用,因为当调用验证lambda时,没有传递自身参数.
现在这样的事情很好:
class Example(CommandSource):
@command
@when(lambda ball: ball.is_round)
def throwBall(self, ball):
pass
但这也行不通:
class Example(CommandSource):
def verify_owner(self, ball):
return ball.owner == self
@command
@when(verify_owner)
def throwBall(self, ball):
pass
目的是能够将类中的方法标记为“命令”,并获取有效运行的命令列表.实际上运行该方法没有改变.我想在这里使用装饰器,因为它似乎是最不笨的方式来做到这一点.实际上我正在尝试使用Python设置一个小DSL.
但我遇到了困难,尤其是自我论证.这是我当前执行的命令,when和CommandSource:
def command(cmd):
if getattr(cmd, 'command', False): return cmd
def wrapper(*args, **kwargs):
return cmd(*args, **kwargs)
wrapper.validators = []
wrapper.command = True
return wrapper
def when(predicate):
def createCommand(cmd):
newcmd = command(cmd)
newcmd.validators.append(predicate)
return newcmd
return createCommand
class CommandSource(object):
def listCommands(self, *args, **kwargs):
commands = []
for command in dir(self.__class__):
func = getattr(self, command, None)
if func == None or getattr(func, 'command', False) == False:
continue
valid = True
for validator in func.validators:
if not validator(*args, **kwargs):
valid = False
break
if valid:
commands.append(command)
return commands
解决方法:
更改您的CommandSource如下:
class CommandSource(object):
def listCommands(self, *args, **kwargs):
commands = []
for command in dir(self.__class__):
func = getattr(self, command, None)
if func == None or getattr(func, 'command', False) == False:
continue
for validator in func.validators:
if not validator(self, *args, **kwargs):
break
else:
commands.append(command)
return commands
并使用您的第一个代码.