Question

Le problème est la nécessité de prendre en compte les arguments avant de choisir le répondant. Voici ma tentative jusqu'à présent.

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 souhaité 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 saurai pas à l'avance toutes les fonctions contenues dans les répondeurs A, B et C.

Était-ce utile?

La solution

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)

which () sélectionne de manière aléatoire une option parmi les choix et getattr à utiliser pour obtenir l'attribut.

EDIT: on dirait que vous voulez quelque chose de plus semblable à ç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 lambda, mais je vais le laisser comme ça pour que ce soit plus clair.

Autres conseils

Quand vous faites cela

r.doSomething(1)

ce qui se passe est, dans l'ordre:

  • r.__getattr__ est appelé et renvoie un objet
  • cet objet est appelé avec un argument & "1 &";

Au moment où __getattr__ est appelé, vous n'avez aucun moyen de savoir quels arguments l'objet que vous renvoyez est appelé , ou même s'il le sera. ..

Ainsi, pour obtenir le comportement souhaité, <=> doit renvoyer un objet appelable qui prend la décision lui-même en fonction des arguments avec lesquels est appelé. 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

Qu'en est-il de:

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

Si vous spécifiez args (sans l'astérisque), il ne s'agit que d'une liste de valeurs (chaînes). De même, kwargs est un dicton de correspondance de clés (chaînes) avec des valeurs (chaînes).

Ce est l'un des premiers résultats que j'ai trouvés après la recherche sur Google args kwargs .

Edit: En fait, je ne sais pas trop ce que vous cherchez, ce n’est donc qu’une hypothèse.

Essayez-vous 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 de répondeurs (A, B, C) ne sont que des objets. Vous pouvez manipuler une classe en utilisant des mappages, des listes, des instructions if, le code Python de votre choix dans la méthode pickAResponder.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top