Python - 在类中使用修饰函数

时间:2014-06-15 09:07:31

标签: python flask decorator

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

它使用烧瓶类视图和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

1 个答案:

答案 0 :(得分:0)

考虑代码的简化(和可运行)版本代码:

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 实例。这些参数的输入顺序错误。
  4. 解决问题的一种方法是在第一项后插入data args

    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参数。