Я бы сохранил информацию в самой функции. Существует риск конфликта, если несколько декораторов решат использовать одну и ту же переменную, но если это только ваш собственный код, вы сможете избежать этого.
def d(f):
if getattr(f, '_decorated_with_d', False):
raise SomeException('Already decorated')
@wraps(f)
def wrapper(*args,**kwargs):
print 'Calling func'
return f(*args,**kwargs)
wrapper._decorated_with_d = True
return wrapper
Другой вариант может быть таким:
def d(f):
decorated_with = getattr(f, '_decorated_with', set())
if d in decorated_with:
raise SomeException('Already decorated')
@wraps(f)
def wrapper(*args,**kwargs):
print 'Calling func'
return f(*args,**kwargs)
decorated_with.add(d)
wrapper._decorated_with = decorated_with
return wrapper
Предполагается, что вы контролируете все используемые декораторы. Если есть декоратор, который не копирует атрибут _decorated_with
, вы не будете знать, чем он украшен.