关于python:从decorator访问函数参数

Accessing function arguments from decorator

我有一个请求处理程序和一个修饰器,我想在修饰器内部处理自对象。

1
2
3
4
5
class MyHandler(webapp.RequestHandler):

    @myDecorator
        def get(self):
            #code

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

1
2
3
4
5
6
7
class myDecorator(object):

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

    def __call__(self):
        #work with self
  • MyHandler>get(函数)>self(参数)
  • myDecorator>__call__(函数)>self(参数)
  • 上面提到的自我论证是不同的。我的目的是从__call__函数内部访问第一个自我,或者找到做类似事情的方法。

    嗨,我可以从装饰器内部的get函数访问myhandlers自变量吗?

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

    我有一个类(请求处理程序):

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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",则该用户是否已登录。

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

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

    谢谢!


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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模块进行一些欺骗。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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

    在上面的示例中,我们从当前框架(在执行decorator期间)中获取类的名称,然后将其存储在decorated函数中。在这里,我们只是在将类名称传递给原始的say函数之前,将该变量的名称预先加上它,但是一旦您有了类名,就可以使用您的想象力来做任何您喜欢的事情。

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


    来源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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>


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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()

    尝试这种方法:实例方法的python修饰符可以访问该类吗?

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


    __call__self参数将用正在调用修饰方法的实例填充。从这里无法访问decorator对象-__call__是一个绑定方法,您所要求的是它实际上是"双重绑定"。python不支持这个,所以decorator实例被decorated函数的第一个参数替换。

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