2016-06-12 58 views
0

所以这里是对这个问题的扩展:https://stackoverflow.com/a/37568895/2290820 关于如何可选地在函数上启用或禁用装饰器。如何让装饰器在递归函数调用中被调用?

在这些线,我想出了这样的事情,使装饰再上一个递归调用调用:

def deco(f): 
    def fattr(attr): 
     f.attr = attr 
     def closure(*args): 
      f(*args) 
     f.unwrap = f 
     f.closure = closure 
     return f 
    return fattr 

@deco 
def printa(x): 
    if x > 1: 
     print x 
     return printa(x-1) 
    else: 
     print x 
    return 

printa({1:1})(5) 

# do the same call w/o deocorator 
def finta(x): 
    if x > 1: 
     print x 
     return finta(x-1) 
    else: 
     print x 
    return 

finta(5) # this works 

与递归函数装饰实验。显然,printa递归版本的行为不应该如此。

我能做

g = printa({1:1}) 
g.closure(5) 

打开装饰选项或无法使用该选项。无论如何,无论设计的好坏,我怎样才能让装饰器在递归调用中被调用?

+0

我不知道为什么这是表决题外话。这真是太棒了! – user2290820

回答

1

在你的deco你有一个分配f.attr = attr,在第一次递归调用后“吃掉”你的参数。你应该修改你的递归调用这种方式:

def deco(f): 
    def fattr(attr): 
     f.attr = attr 
     def closure(*args): 
      f(*args) 
     f.unwrap = f 
     f.closure = closure 
     return f 
    return fattr 

@deco 
def printa(x): 
    if x > 1: 
     print x 
     return printa(None)(x-1) # None will be assigned to f.attr 
    else: 
     print x 
    return 

printa({1:1})(5) 

5 
4 
3 
2 
1 
+0

是完美的。我正要测试它。 – user2290820