2009-01-26 6 views
1

Le problème est de prendre en compte les arguments avant de choisir le répondeur. Voici ma tentative jusqu'à présent.Nécessité de router les appels d'instance dans une classe python

from responders import A, B, C 

class RandomResponder(object) 
    def init(self, *args, *kwargs): 
     self.args = args 
     self.kwargs = kwargs 

    def __getattr__(self, name): 
     # pick a responder based on the args the function was called with 
     # I don't know how to do this part 
     # for sake of argument lets the args a function was called with lead me to pick responder A 
     r = A 
     responder = r(*self.args, **self.kwargs) 
     return responder.__getattr__(name) 

L'effet recherché serait:

r = RandomResponder() 
r.doSomething(1) 
#returns A.doSomething() 
r.doSomething(2) 
#returns B.doSomething() 
r.doSomething(3) 
#return C.doSomething() 
r.doSomethingElse(1) 
#returns A.doSomethingElse() 
r.doSomethingElse(2) 
#returns B.doSomethingElse() 
r.doSomethingElse(3) 
#returns C.doSomethingElse() 

Je ne saura pas à l'avance toutes les fonctions contenues avec les intervenants A, B et C.

+0

Ce que vous essayez de faire n'est pas du tout clair, pouvez-vous donner plus d'informations? (Je voudrais également clarifier le titre) –

+0

S'il vous plaît mettre à jour votre question avec des faits supplémentaires; commenter une réponse n'est pas aussi utile que de régler votre question. –

Répondre

2

Essayez ceci:

class RandomResponder(object): 
    choices = [A, B, C] 

    @classmethod 
    def which(cls): 
     return random.choice(cls.choices) 

    def __getattr__(self, attr): 
     return getattr(self.which(), attr) 

qui() sélectionne au hasard une option parmi les choix, et qui getattr utilise pour obtenir l'attribut.

EDIT: il semble que vous voulez quelque chose de plus comme ça.

class RandomResponder(object): 
    choices = [A, B, C] 

    def __getattr__(self, attr): 
     # we define a function that actually gets called 
     # which takes up the first positional argument, 
     # the rest are left to args and kwargs 
     def doCall(which, *args, **kwargs): 
      # get the attribute of the appropriate one, call with passed args 
      return getattr(self.choices[which], attr)(*args, **kwargs) 
     return doCall 

Cela pourrait être écrit en utilisant lambda, mais je vais le laisser comme ça, donc c'est plus clair.

+0

Très intelligent par vous et dF, je n'ai jamais pensé à retourner une fonction qui contient la logique. –

0

Si vous spécifiez args (sans l'astérisque), c'est juste une liste de valeurs (chaînes). De même, kwargs est un Dict des clés correspondantes (chaînes) aux valeurs (chaînes).

This est l'un des premiers résultats que j'ai trouvé après Googling args kwargs. Edit: Je ne sais pas vraiment ce que vous cherchez, donc c'est juste une supposition.

0

Etes-vous en train d'essayer de faire cela?

from responders import A, B, C 

class RandomResponder(object) 

    def pickAResponder(self, someName): 
     """Use a simple mapping.""" 
     return { 'nameA': A, 'nameB': B, 'nameC': C }[someName] 

    def __init__(self, *args, *kwargs): 
     self.args = args 
     self.kwargs = kwargs 

    def __getattr__(self, name): 
     """pick a responder based on the args[0]""" 
     r = self.pickAResponder(self.args[0]) 
     responder = r(*self.args, **self.kwargs) 
     return responder.__getattr__(name) 

Vos classes répondeur (A, B, C) sont juste des objets. Vous pouvez manipuler une classe en utilisant des mappages, des listes, des instructions if, le codage Python que vous voulez dans la méthode pickAResponder.

+0

Fermez, mais je ne veux pas utiliser les arguments de __init__, je veux utiliser les arguments avec lesquels l'attribut est appelé. –

+0

S'il vous plaît mettez à jour votre question avec les faits supplémentaires. –

1

Qu'en est-:

RandomResponder = [A, B, C] 
RandomResponder[0].doSomething() # returns A.doSomething() 
RandomResponder[1].doSomething() # returns B.doSomething() 
RandomResponder[2].doSomething() # returns C.doSomething() 
# etc 
3

Lorsque vous faites cela

r.doSomething(1) 

ce qui se passe est, dans l'ordre:

  • r.__getattr__ est appelé, et retourne un objet
  • cette objet est appelé avec un argument "1"

Au moment où __getattr__ est appelé, vous avez aucun moyen de savoir quels arguments l'objet retour est va à être appelée avec, ou même si elle va être appelé à tout ...

Donc, pour obtenir le comportement que vous voulez, __getattr__ doit retourner un objet appelable qui prend la décision lui-même basé sur les arguments c'est appelé avec. Par exemple

from responders import A, B, C 

class RandomResponder(object): 
    def __getattr__(self, name): 
     def func(*args, **kwds): 
      resp = { 1:A, 2:B, 3:C }[args[0]] # Decide which responder to use (example) 
      return getattr(resp, name)()   # Call the function on the responder 
     return func 
+0

Devrait être: resp = {1: A, 2: B, 3: C} [args [0] - 1] Parce qu'il n'est pas indexé par zéro. –

Questions connexes