防止装饰器在python中的同一函数上使用两次 [英] Prevent decorator from being used twice on the same function in python

查看:240
本文介绍了防止装饰器在python中的同一函数上使用两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个装饰器:

from functools import wraps
def d(f):
    @wraps(f)
    def wrapper(*args,**kwargs):
        print 'Calling func'
        return f(*args,**kwargs)
    return wrapper

我想防止它两次修饰相同的函数,例如防止诸如此类的事情:

And I want to prevent it from decorating the same function twice, e.g prevent things such as:

@d
@d
def f():
   print 2

我能想到的唯一可能的解决方案是使用字典存储装饰器已经装饰的功能,并在请求时引发异常装饰字典中存在的功能。
请告诉您是否有更好的主意...

Only possible solution I could think of is using a dict to store the functions the decorator has already decorated and raising an exception if asked to decorate a function that exists in the dict. Do tell if you have a better idea...

推荐答案

我会将信息存储在函数本身中。如果多个装饰器决定使用同一变量,则有发生冲突的风险,但是如果它只是您自己的代码,则应该可以避免使用该变量。

I'd store the information in the function itself. There is a risk of a conflict if multiple decorators decide to use the same variable, but if it's only your own code, you should be able to avoid it.

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 属性,则您将不知道装饰了什么。

This assumes that you control all the decorators used. If there is a decorator that doesn't copy the _decorated_with attribute, you will not know what is it decorated with.

这篇关于防止装饰器在python中的同一函数上使用两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆