【问题标题】:Accessing function arguments from decorator从装饰器访问函数参数
【发布时间】:2011-09-22 03:20:58
【问题描述】:

我有一个请求处理程序和一个装饰器,我想在装饰器中使用 self 对象

class MyHandler(webapp.RequestHandler):

    @myDecorator
        def get(self):
            #code

更新:请注意第一自我和第二自我的区别

class myDecorator(object):

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

    def __call__(self):
        #work with self
  1. MyHandler > get (函数) > self (参数)
  2. myDecorator > __call__ (函数) > self (参数)

上面提到的 self 参数是不同的。我的意图是从 __call__ 函数内部访问第一个 self,或者找到一种方法来做类似的事情。

您好,我可以从装饰器中的 get 函数访问 MyHandlers 的 self 参数吗?

更新 2:我想实现一个装饰器来处理谷歌应用引擎中的自定义登录:

我有一个类( requestHandler ):

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

我想装饰get函数以检查用户是否登录:

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

如果会话对象中具有“user_key”属性,我知道用户是否已登录。

这是我对这个具体案例感兴趣的主要目标

如果我做错了什么,请告诉我您的建议/意见!

谢谢!

【问题讨论】:

  • 此外,将“Google App Engine”放在仅与装饰器有关的问题前面可能会使您的问题获得更少的浏览量。通用项目的浏览量很大,有关特定平台的问题的浏览和回答速度较慢。
  • 没问题,如果您的问题被更多人浏览,我的回答可以得到更多投票。这是双赢。

标签: python google-app-engine decorator


【解决方案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>

【讨论】:

    【解决方案2】:
    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()
    

    【讨论】:

      【解决方案3】:

      __call__self 参数将填充正在调用装饰方法的实例。无法从这里访问装饰器对象 - __call__ 是一个绑定方法,而您所要求的实际上是“双重绑定”。 Python 不支持这一点,因此装饰器实例被装饰函数的第一个参数替换。

      解决此问题的最简单方法是使用嵌套函数,正如 @Chris 建议的那样。

      【讨论】:

        【解决方案4】:

        我不完全清楚你想要什么,但如果你只想使用装饰函数的参数,那么这正是基本装饰器所做的。所以要从装饰器访问说,self.request,你可以这样做:

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

        如果您尝试访问装饰函数所附加到的类,那么这有点诡计,您必须使用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
        

        在上面的示例中,我们从当前帧(在装饰器执行期间)获取类的名称,然后将其存储在装饰函数中。在这里,我们只是将类名添加到 msg 变量之前,然后将其传递给原始的 say 函数,但是一旦有了类名,您就可以发挥您的想象力做任何您想做的事情。

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

        【讨论】:

        • 我刚刚更新了问题以使其更清楚,我看到我可以对类使用检查,但我想使用修饰函数的参数。那可能吗?谢谢@克里斯
        • 抱歉,您仍然不太清楚您要达到的目标......但我还是用更多信息更新了答案
        • 我添加了一个新的更新(2)与具体案例,请告诉我你的意见。非常感谢!
        【解决方案5】:

        试试这个方法:Can a Python decorator of an instance method access the class?

        不是完全相同的问题,但您应该能够使用相同的方法来创建对 self 的引用或对包含某个类的对象的字典的引用,您可以在装饰器中获取这些对象。

        【讨论】:

          猜你喜欢
          • 2011-06-25
          • 2020-06-20
          • 2021-09-14
          • 1970-01-01
          • 2021-11-21
          • 2019-06-14
          • 1970-01-01
          • 2014-03-27
          • 2016-10-10
          相关资源
          最近更新 更多