从装饰器访问函数参数

11 投票
5 回答
10653 浏览
提问于 2025-04-16 20:13

我有一个请求处理器和一个装饰器,我想在装饰器里面使用self对象。

class MyHandler(webapp.RequestHandler):

    @myDecorator
        def get(self):
            #code

更新:请注意第一个和第二个self的区别

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函数访问MyHandler的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

我知道如果用户已登录,session对象中会有一个属性'user_key'。

这是我在这个特定案例中最关心的主要目标。

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

谢谢!

5 个回答

1

试试这个方法:一个Python实例方法的装饰器能访问类吗?

虽然这个问题不完全一样,但你可以用类似的方法来创建对self的引用,或者创建一个包含某个类对象的字典,这样你就可以在你的装饰器中使用这些引用。

2

来源

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>
11

我不太清楚你具体想要什么,但如果你只是想使用被装饰函数的参数,那这正是基本装饰器的作用。所以,如果你想从装饰器中访问,比如说,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

撰写回答