2016-06-12 60 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