2015-06-04 27 views
2

我有一个类运行检查,每个函数执行检查。我曾想过装饰者添加额外的条件,但这可能不是明智的。多个python装饰器检索原函数

我理解装饰器的概念,每个装饰器都以输入装饰它的功能,并返回下一个装饰的功能。例如,对于返回字符串的函数,这很好,因为输出可以很容易地由装饰器编辑并返回到下一个装饰器。

我想要做的就是修改函数属性,把例如一个don't exec标志检查,不再运行,require auth仅当验证已经获得,或改变功能属性order,测序检查启动进行检查。

# I return f only if is_authenticated flag is True 
def auth_required(is_authenticated): 
    def check_authentication(f): 
     if is_authenticated: 
      return f 
    return check_authentication 

# I edit order variable 
def assignOrder(order): 
    def do_assignment(f): 
     f.order = order 
     return f 
    return do_assignment 
# I instanciate Checks class and provide authentication; 
# login and password will be tried and is_authenticat flag set accordingly 
c = Checks(target, login, password) 

# I sort on order variable and launch checks 
functions = sorted(
    [ 
     getattr(c, field) for field in dir(c) 
     if hasattr(getattr(c, field), 'order') 
    ],key = (lambda field : field.order) 
) 
for function in functions: 
    function() 

# I assign decorators so that order variable is set 
# I would like auth_required triggers launch if auth is performed 
@auth_required(True) 
@assignOrder(100) 
def check_shares(self): 
    # check defined here 

这对assignOrder很有效,我的检查按正确顺序启动。

@auth_required适用于assignOrder这不是我想要的。

有没有办法检索要装饰的原始功能?或者装饰者的用法在这种情况下是不相关的?那么解决方案是什么?

非常感谢

+0

“但@auth_required应用于assignOrder,这不是我想要的。” 实际上,'auth_required'应用于“什么'assignOrder'返回”,而不是'assignOrder'本身。这里你的_real_问题实际上是什么? –

+0

感谢您的回答;我的问题是我不能设置一个'认证'标志并在同一时间分配一个'订单'。我编辑我的问题,使其更清晰 – philippe

+0

恐怕我不明白你的'auth_required'装饰器应该如何工作? –

回答

0

有没有解决您的问题的通用方式。装饰者没有内置的设施可以合作,甚至不需要保留对原始功能的引用。

所以你需要自己想出一个协议,例如,使assignOrder将原始功能保存为do_assignment

然后在is_authenticated,你必须看看是否有一个“真实”的功能在传递的后面,并用它来代替。

0

尽管你声明了你没有装饰器,但你的代码似乎很混乱。

我希望你已了解,如果你这样做:

def auth_required(is_authenticated): 
    def check_authentication(f): 
     if is_authenticated: 
      return f 
    return check_authentication 

@auth_required(something) 
def my_function(): 
    .... 

意味着“东西”变量在导入时检查,并且只有一次,你的装饰功能将被supressed - 那是名称“mu_function”将被绑定到None,导致任何代码尝试调用该错误。如果你替换返回None来返回一个不做任何事情的函数,为了解决这个错误,直到你重新加载包含该函数的模块(在测试场景中,这通常意味着再次运行一切),这仍然是不可改变的, 。

所以,这不仅仅是错误的 - 它表明你困惑的是由装饰者做的一切。

这将是简单的依靠全球variale打开funcion和关闭这种方式:

from functools import wraps 
def auth_required(f): 
    @wraps(f) 
    def wrapper (*args, **kw): 
     if is_authenticated: 
      return f(*args, **kw) 
     return None 
    return wrapper 

现在,这种装饰可以把你的装饰功能“的”和“关”随意在调用之间的运行时更改is_authenticated模块级变量 - 不需要重新加载模块。

此外,回到“多个python装饰器检索原始功能”的标题问题: 注意我将functools.wraps修饰器添加到上面的包装器代码本身。最近Python中的这个函数在装饰函数上设置一个__wrapped__属性,该属性指向您的原始装饰函数。

所以,如果你所有的装饰都表现良好,并在他们的包装应用functools.wraps,你可以随时使用其__wrapped__属性可以访问到最里面的功能由 。