2011-06-24 9 views
8

tengo un controlador de solicitudes y un decorador, me gustaría trabajar con el objeto mismo en el interior del decoradorAcceso argumentos de la función del decorador

class MyHandler(webapp.RequestHandler): 

    @myDecorator 
     def get(self): 
      #code 

Actualización: Por favor, observe la diferencia entre el primer y segundo yo

class myDecorator(object): 

    def __init__(self, f): 
     self.f = f 

    def __call__(self): 
     #work with self 
  1. MyHandler>get (función)>self (argumento)
  2. myDecorator>__call__ (función)>self (argumento)

los argumentos auto mencionados anteriormente son diferentes. Mi intención es acceder al primer yo desde dentro de la función __call__, o encontrar una manera de hacer algo similar.

Hola, ¿puedo acceder al argumento propio de MyHandlers para obtener la función dentro del decorador?

Update2: Quiero aplicar un decorador de trabajar con un inicio de sesión personalizado en el motor de aplicación de Google:

tengo una clase (RequestHandler):

class SomeHandler(webapp.RequestHandler): 
    @only_registered_users 
    def get(self): 
     #do stuff here 

Y Quiero decorar el obtener la función con el fin de comprobar si el usuario está conectado o no:

from util.sessions import Session 
import logging 

class only_registered_users(object): 

    def __init__(self, f): 
     self.f = f 

    def __call__(self): 
     def decorated_get(self): 
     logging.debug("request object:", self.request) 
     session = Session() 

     if hasattr(session, 'user_key'): 
      return self.f(self) 
     else: 
      self.request.redirect("/login") 


    return decorated_get 

sé si un uso r ha iniciado sesión si tiene la propiedad 'user_key' en un objeto de sesión.

Ese es el objetivo principal que me interesa en este caso específico

me dejó saber su sugerencia/opinión si estoy haciendo algo mal!

Gracias!

+0

También, poniendo "Google App Engine" frente a una pregunta que es sólo alrededor de decoradores podrían hacer su pregunta conseguir un menor número de puntos de vista. Los elementos genéricos se ven mucho, las preguntas sobre plataformas específicas se visualizan y responden más lentamente. – marr75

+0

Corregido, gracias @ marr75 –

+1

No hay problema, si su pregunta es vista más, mi respuesta puede ser votada más. Es una victoria para todos. – marr75

Respuesta

9

No estoy del todo claro qué es lo que quieres, pero si solo quieres usar los argumentos de la función decorada, eso es exactamente lo que hace un decorador básico. Así que para acceder por ejemplo, self.request de un decorador que podría hacer:

def log_request(fn): 
    def decorated_get(self): 
     logging.debug("request object:", self.request) 
     return fn(self) 
    return decorated_get 

class MyHandler(webapp. RequestHandler): 
    @log_request 
    def get(self): 
     self.response.out.write('hello world') 

Si está intentando acceder a la clase la función decorada está unido a, entonces es una Tricker poco y vas a tener a engañar un poco usando el módulo inspect.

import inspect 

def class_printer(fn): 
    cls = inspect.getouterframes(inspect.currentframe())[1][3] 
    def decorated_fn(self, msg): 
     fn(self,cls+" says: "+msg) 
    return decorated_fn 

class MyClass(): 
    @class_printer 
    def say(self, msg): 
     print msg 

En el ejemplo anterior buscamos al nombre de la clase de la currentFrame (durante la ejecución del decorador) y luego almacenamos que en la función decorada.Aquí solo estamos anteponiendo el nombre de clase a lo que sea que sea la variable msg antes de pasarla a la función original say, pero puede usar su imaginación para hacer lo que quiera una vez que tenga el nombre de la clase.

>>> MyClass().say('hello') 
MyClass says: hello 
+0

Acabo de actualizar el problema para dejarlo más claro, veo que puedo usar inspeccionar para la clase, pero me gustaría usar el argumento de la función decorada. ¿Es eso posible? thx @Chris –

+0

Disculpe aún no está muy claro lo que está tratando de lograr ... pero actualicé la respuesta con más información de todos modos –

+0

Agregué una nueva actualización (2) con el caso específico, por favor déjeme saber su opinión. ¡Muchas gracias! –

1

Pruebe este enfoque: Can a Python decorator of an instance method access the class?

No es exactamente la misma pregunta, pero usted debería ser capaz de utilizar el mismo método para crear una referencia a sí mismo oa una referencia a un diccionario con los objetos de una determinada clase en los mismos que se puede salir en su decorador.

0

El argumento self-__call__ se rellenará con el ejemplo, el método decorado está siendo llamado en. No hay forma de acceder al objeto decorador desde aquí: __call__ es un método vinculado, y lo que está solicitando requerirá que esté, en efecto, "doblemente vinculado". Python no es compatible con esto, por lo que la instancia de decorador se reemplaza con el primer argumento de la función decorada.

La forma más fácil de evitar esto es utilizar funciones anidadas, como recomienda @Chris.

1
import random 

#decorator to the get function in order to check out if the user is logged in or not 
def only_registered_users(func): 
    def wrapper(handler): 
     print 'Checking if user is logged in' 
     if random.randint(0, 1): 
      print 'User is logged in. Calling the original function.' 
      func(handler) 
     else: 
      print 'User is NOT logged in. Redirecting...' 
      # redirect code here 
    return wrapper 


class MyHandler(object): 

    @only_registered_users 
    def get(self): 
     print 'Get function called' 



m = MyHandler() 
m.get() 
1

source

def p_decorate(func): 
    def func_wrapper(name): 
     return "<p>{0}</p>".format(func(name)) 
    return func_wrapper 

@p_decorate 
def get_text(name): 
    return "lorem ipsum, {0} dolor sit amet".format(name) 

print get_text("John") 

# Outputs <p>lorem ipsum, John dolor sit amet</p> 
Cuestiones relacionadas