加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 类中的decorator没有得到值

发布时间:2020-12-20 13:43:45 所属栏目:Python 来源:网络整理
导读:我有一个装饰器来验证我使用请求获得的json响应.我还将一些请求逻辑包装到一个类中,该类接受装饰器需要验证的模式.我尝试在类的get函数上使用装饰器,但每次尝试执行此操作时都会出现类型错误: TypeError: get() takes exactly 1 argument (0 given) 我知道
我有一个装饰器来验证我使用请求获得的json响应.我还将一些请求逻辑包装到一个类中,该类接受装饰器需要验证的模式.我尝试在类的get函数上使用装饰器,但每次尝试执行此操作时都会出现类型错误:

TypeError: get() takes exactly 1 argument (0 given)

我知道如果你在类方法上使用装饰器,你需要在装饰器中设置self = None.

这是代码:

schema = {'pid': int,'description': str}

def validator(schema):
    def _validator(f):
        @wraps(f)
        def wrapped(self=None):
            print f
            check = all([isinstance(v,schema[k]) for k,v in f().iteritems() if v])
            return f() if check else None
        return wrapped
    return _validator


class Data(object):
    ''' Base request wrapper to use for all apis
    accepts a validator schema to check the type of response values. '''

    def __init__(self,base_url,schema=None,debug=False):
        self.base_url = base_url
        self.schema = schema

    def __getattr__(self,key):
        new_base = self.append_to_url(self.base_url,key)
        return self.__class__(base_url=new_base)

    def __getitem__(self,key):
        return self.__getattr__(key)

    # def __call__(self,**kwargs):
    #     self.base_url = self.base_url[:-1]
    #     return self.get(self.base_url,**kwargs)

    def append_to_url(self,param):
        return '{}{}/'.format(base_url,param)

    @validator(schema)
    def get(self,**kwargs):
        try:
            r = requests.get(self.base_url[:-1],**kwargs)
            r.raise_for_status()
            return r.json()

        except requests.exceptions.ConnectionError as e:
            raise errors.ApiError(e)

        except requests.exceptions.HTTPError as e:
            raise errors.ApiError(e)

product_details = Data('my_api_url',schema).shoes['10'].get()

我认为这是因为在我的验证器中我初始化f(),这是get函数期待自我.我试图在装饰器中将self传递给f()但是也会产生相同的错误.我甚至试图在__call__方法上初始化get函数,但是得到get函数需要1 arg和2.

必须有一种更有效或更加方便的方法来实现这一目标.我知道有一个名为妖娆的图书馆可以进行大量的验证,但我想尝试一些简单的学习练习.

解决方法

这不是被包裹的函数调用失败,而是获取调用.你调用它的所有地方就像f(),即没有任何参数.

一个工作示例,正确地将自身参数传递给包装函数:

import functools

def validator(schema):
    def _validator(f):
        @functools.wraps(f)
        def wrapper(self):
            # pass self to the wrapped function
            result = f(self)
            return 'wrapped {} {}'.format(schema,result)
        return wrapper
    return _validator

class Data(object):
    @validator('test')
    def get(self):
        return 'data'

print(Data().get())
# wrapped test data

虽然您可以直接使用自我或其他此类特定参数,但使用* args和** kwargs会使装饰器更加灵活,例如使它也可用于非约束函数:

import functools

def validator(schema):
    def _validator(f):
        @functools.wraps(f)
        def wrapped(*args,**kwargs):
            # pass aribitrary args to the wrapped function
            # for greater flexibility
            result = f(*args,**kwargs)
            return 'wrapped {} {}'.format(schema,result)
        return wrapped
    return _validator

class Data(object):
    @validator('test')
    def get(self):
        return 'data'

@validator('test2')
def get():
    return 'data2'

print(Data().get())
# wrapped test data
print(get())
# wrapped test2 data2

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读