获取带有args的装饰器以使用方法:self不存在

时间:2014-11-24 15:28:52

标签: python oop decorator

当我尝试用decorate中的参数装饰一个方法时,它给我一个self未定义。如果我改为将val更改为类变量并使用MyCls.val它现在给我MyCls未定义!我如何装饰我的mehtod?

def dodecorate(VAL):
    def decorate(func):
        def wrapped(*args,**kwargs):
            res = func(*args,**kwargs)
            if res == VAL:
                res = "one"
            return res
        return wrapped
    return decorate


class MyCls(object):
    def __init__(self):
        self.val = 1

    @dodecorate(VAL = self.val)
    def onefrom1(self, x):
        return x

编辑以上是我发明的代表原作的抽象。这是实际的代码。

def retry_on_invalid_schema(MAX_RETRIES):
    def retrier(func):
        def wrapped(*args, **kwargs):
            tries = 0
            res = None
            while tries < MAX_TRIES:
                try:
                    res = func(*args, **kwargs)
                    assert res.has_key('by')
                    assert res.has_key('id')
                    break
                except AssertionError:
                    res = None
                    time.sleep(2**tries)
                    tries += 1
                    continue
            return res
        return wrapped
    return retrier



class Base(object):

    def __init__(self):

        self.MAX_RETRIES = 3

    @retry_on_invalid_schema(MAX_RETRIES = self.MAX_RETRIES)
    def _get_api_response(self, uri):
        return json.loads(self._get(uri))

    def _get(self, uri):
        return requests.get(uri).text

2 个答案:

答案 0 :(得分:1)

如果要在实例方法上使用现有的装饰器函数,请注意您可以在__init__中重新定义实例方法,直接调用装饰器而不是使用@语法:

class MyCls(object):

    def __init__(self):
        self.val = 1
        self.onefrom1 = dodecorate(self.val)(self.onefrom1)

    def onefrom1(self, x):
        return x

使用中:

>>> a = MyCls()
>>> for x in range(3):
    print a.onefrom1(x)


0
one
2

答案 1 :(得分:0)

您可以通过实例访问它,而不是尝试将val传递给装饰器。 self包含当前实例,并传递给装饰器中的wrapped方法,因此您可以在装饰器中将其作为第一个参数进行访问。

def decorate(func):
    def wrapped(instance, *args, **kwargs):
        res = func(instance, *args, **kwargs)
        if res == instance.val:
            res = "one"
        return res
    return wrapped


class MyCls(object):
    def __init__(self):
        self.val = 1

    @decorate
    def onefrom1(self, x):
        return x

c = MyCls()
print c.onefrom1(1)
print c.onefrom1(2)

输出

one
2