Pregunta

El problema es la necesidad de tener en cuenta los argumentos antes de elegir el respondedor. Aquí está mi intento hasta ahora.

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)

El efecto deseado sería:

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()

No sabré de antemano todas las funciones contenidas en los respondedores A, B y C.

¿Fue útil?

Solución

Prueba esto:

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 () selecciona aleatoriamente una opción de las opciones, y que getattr usa para obtener el atributo.

EDITAR: en realidad parece que quieres algo más como esto.

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

Esto podría escribirse usando lambda, pero lo dejaré así para que quede más claro.

Otros consejos

Cuando haces esto

r.doSomething(1)

lo que sucede es, en orden:

  • r.__getattr__ se llama y devuelve un objeto
  • este objeto se llama con un argumento " 1 "

En el momento en que se llama a __getattr__, no tiene forma de saber con qué argumentos se va a llamar el objeto que devuelve, va , o incluso si se va a llamar. ..

Por lo tanto, para obtener el comportamiento que desea, <=> tiene que devolver un objeto invocable que tome la decisión en sí mismo en función de los argumentos con los que se llama. Por ejemplo

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é pasa con:

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

Si especifica args (sin el asterisco), es solo una Lista de valores (cadenas). Del mismo modo, kwargs es un Dict de coincidencia de claves (cadenas) con valores (cadenas).

Esto es uno de los primeros resultados que encontré después de buscar en Google args kwargs .

Editar: en realidad no sé exactamente lo que estás buscando, así que esto es solo una suposición.

¿Estás tratando de hacer esto?

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)

Tus clases de respuesta (A, B, C) son solo objetos. Puede manipular una clase utilizando asignaciones, listas, sentencias if, cualquier codificación de Python que desee en el método pickAResponder.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top