Класс декоратора для проверки необходимых переменных класса

Во-первых, я не знаю, правильный ли это подход. Я хочу написать класс декоратора, который будет использоваться с методами другого класса. Перед запуском метода я хотел бы проверить, инициализированы ли все необходимые переменные класса. Идеальным случаем было бы что-то похожее на это:

class Test(object):
    def __init__(self, f):
        self.f = f
        # some magic

    def __call__(self):
        self.f.magically_get_variable(required)
        # do some checks and execute method or throw an exception

class Data(object):
    def __init__(self, a, b):
        self.a = a

    @test
    def sum(self):
        required('self.a', 'self.b')
        return self.a + self.b

Если это не так, как это должно быть сделано, пожалуйста, посоветуйте мне, как это сделать правильно.


person chriss    schedule 10.03.2010    source источник


Ответы (2)


Я бы сказал, что декораторы здесь немного не подходят для проверки существования переменной.

Подумайте, что вы планируете делать, если требуемые переменные не предоставлены: создать исключение (это в вашем комментарии).

Я бы сказал (на основе приведенного выше кода):

def sum(self):
    return self.a + self.b

И пусть это не сработает, если self.a или self.b не предоставлены (это вызовет исключение NameError, вы можете поймать его, если хотите, и затем вы можете создать свое собственное, если хотите).

person ChristopheD    schedule 10.03.2010
comment
+1: NameError расскажет больше, чем любой декоратор. Он встроен. Он всегда работает. - person S.Lott; 10.03.2010

Если вы настаиваете на проверке до того, как запустится тело декорированного метода, следующий разумный способ сделать это...:

import functools

class test(object):
    def __init__(self, requiredvars):
        self.reqs = requiredvars.split()

    def __call__(self, f):
        @functools.wraps(f)
        def wrapper(wself, *a, **k):
          missing = set()
          for v in self.reqs:
            if not hasattr(wself, v):
              missing.add(v)
          if missing:
            msg = 'missing fields: %s' % ','.join(sorted(missing))
            raise valueerror, msg
          return f(wself, *a, **k)
        return wrapper

class data(object):
    def __init__(self, a, b):
        self.a = a

    @test('a b')
    def sum(self):
        return self.a + self.b

d = data(23, 42)
d.sum()

Это излучает, как вы, очевидно, желаете,

Traceback (most recent call last):
  File "rev.py", line 29, in <module>
    d.sum()
  File "rev.py", line 16, in wrapper
    raise ValueError, msg
ValueError: Missing fields: b
person Alex Martelli    schedule 10.03.2010