Je suis en train d'installer des décorateurs pour que je puisse faire quelque chose comme:Comment gérer l'argument « auto » avec décorateurs Python
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' ]
Cela ne fonctionne pas actuellement, comme lorsque le lambda de validation est appelée, il n'y a pas d'auto-argument passé.
Maintenant, quelque chose comme ça fonctionne très bien:
class Example(CommandSource):
@command
@when(lambda ball: ball.is_round)
def throwBall(self, ball):
pass
Mais cela ne fonctionne pas non plus:
class Example(CommandSource):
def verify_owner(self, ball):
return ball.owner == self
@command
@when(verify_owner)
def throwBall(self, ball):
pass
Le but est d'être en mesure de marquer des méthodes dans une classe comme une « commande » , et le obtenir une liste de commandes qui sont valides pour exécuter. En fait, l'exécution de la méthode est inchangée. Je voudrais utiliser des décorateurs ici, car il semble que la façon la moins klunky de faire cela. En effet j'essaye d'installer un peu de DSL en utilisant Python.
Mais j'ai des difficultés, surtout avec l'argument self
. Voici mon implémentation actuelle de command
, when
et 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
Grande, qui fonctionne aussi grâce à l'aide de la '' else' pour la boucle for' intérieure. –