Я пытаюсь настроить некоторые декораторы так, чтобы я мог сделать что-то вроде:
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' ]
В настоящее время это не работает, так как при вызове лямбда-проверки аргумент self не передается.
Теперь что-то вроде этого работает нормально:
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
Цель состоит в том, чтобы иметь возможность пометить методы в классе как «команду» и получить список команд, которые допустимы для выполнения. На самом деле запуск метода не изменился. Я хотел бы использовать декораторы здесь, так как это кажется наименее хитрым способом сделать это. По сути, я пытаюсь настроить немного DSL, используя Python.
Но у меня трудности, особенно с аргументом self
. Вот моя текущая реализация command
, 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