【问题标题】:Python - Use decorated function in classPython - 在类中使用装饰函数
【发布时间】:2014-06-15 09:07:31
【问题描述】:

我的装饰函数的参数正在交换。 在authorized(self, resp) 中,resp 正在变成ClientView 对象,self 正在变成resp 变量。 我怎样才能装饰这个函数以便它可以用作方法?

它使用flask类视图和flask_oauthlib。

功能代码:

class ClientView(UserView):

    @bp.route('/vklogin/authorized')
    @vk.authorized_handler
    def authorized(self, resp):
        if resp is None:
            return 'Access denied: reason=%s error=%s' % (
                request.args['error_reason'],
                request.args['error_description']
            )
        session['oauth_token'] = (resp['access_token'], '')
        me = self.vk.get('method/users.get?uids={}'.format(resp['user_id']))
        return '{}'.format(me.data)

装饰器功能代码:

class OAuthRemoteApp(object):
    def authorized_handler(self, f):
            @wraps(f)
            def decorated(*args, **kwargs):
                if 'oauth_verifier' in request.args:
                    try:
                        data = self.handle_oauth1_response()
                    except OAuthException as e:
                        data = e
                elif 'code' in request.args:
                    try:
                        data = self.handle_oauth2_response()
                    except OAuthException as e:
                        data = e
                else:
                    data = self.handle_unknown_response()

                # free request token
                session.pop('%s_oauthtok' % self.name, None)
                session.pop('%s_oauthredir' % self.name, None)
                return f(*((data,) + args), **kwargs)
            return decorated

【问题讨论】:

    标签: python flask decorator


    【解决方案1】:

    考虑一下您的代码的这个简化(和可运行)版本代码:

    class OAuthRemoteApp(object):
        def authorized_handler(self, f):
            def decorated(*args, **kwargs):
                print(self, f, args, kwargs)   #1
                # (<__main__.OAuthRemoteApp object at 0xb74d324c>, <function authorized at 0xb774ba04>, (<__main__.ClientView object at 0xb74d32cc>,), {})
                data = 'resp'
                print((data,) + args)  #2
                # ('resp', <__main__.ClientView object at 0xb74d32cc>)
                return f(*((data,) + args), **kwargs)             
            return decorated
    
    vk = OAuthRemoteApp()
    
    class ClientView(object):
        @vk.authorized_handler
        def authorized(self, resp):
            print(self, resp)  #3
            # ('resp', <__main__.ClientView object at 0xb7452eec>)
    cv = ClientView()
    cv.authorized()
    
    1. 注意args 中的第一项是ClientView 实例:

      args = (<__main__.ClientView object at 0xb74d32cc>,)
      
    2. 表达式 (data,) + args 在前面添加 'resp' ClientView 实例。这就是问题的根源。
    3. 注意这里selfresprespClientView 实例。提供的参数顺序错误。

    解决问题的一种方法是在第一项之后插入dataargs:

    class OAuthRemoteApp(object):
        def authorized_handler(self, f):
            def decorated(*args, **kwargs):
                data = 'resp'
                args = args[:1] + (data,) + args[1:]
                return f(*args, **kwargs) 
            return decorated
    
    vk = OAuthRemoteApp()
    
    class ClientView(object):
        @vk.authorized_handler
        def authorized(self, resp):
            print(self, resp)
    
    cv = ClientView()
    cv.authorized()
    

    产量

    (<__main__.ClientView object at 0xb7434f0c>, 'resp')
    

    这表明ClientViewresp 参数以正确的顺序提供。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      • 2019-07-23
      • 2021-07-16
      • 2017-01-15
      相关资源
      最近更新 更多