2017-08-12 77 views
-1

我有這樣的代碼:哪裏蟒蛇裝飾從裝飾的功能獲得的參數

def foo(bar): 
    def test(some_string): 
     return 'Decorator test: '+bar(some_string) 
    return test 


def main(): 
    print(bar('test1')) 


@foo 
def bar(some_string): 
    return some_string[:3] 

據我所知,調用bar('test1)基本上是呼喚foo(bar('test1')),但是當我嘗試在foo其它功能之前打印some_string ,我得到some_string is not defined

def foo(bar): 
    print(some_string) 
    def test(some_string): 
     return 'Decorator test: '+bar(some_string) 
    return test 
  1. 如何test知道some_stringfoo不?
  2. 爲什麼我必須返回test讓裝飾工作?直接返回Decorator test: '+bar(some_string)不起作用,因爲some_string未定義。
+2

都能跟得上。它是'foo(bar)('test1')'。 –

回答

5

據我所知,調用bar('test1)基本上呼籲foo(bar('test1'))

不,它不是,你的理解是不正確。它基本上是調用

foo(bar)('test') 

@foo裝飾語法告訴Python來調用foo()傳遞由bar命名的函數對象(和結果分配回名bar)。

foo()裝飾返回一個新的函數對象:

def test(some_string): 
    # ... 
return test 

所以foo(bar)結果是名爲test該函數對象(在foo()裝飾本地名稱)。 foo(bar)('test')因此稱爲test('test')

如果你想打印傳遞給test(..)的說法,這樣做該功能:

def foo(bar): 
    def test(some_string): 
     print(some_string) 
     return 'Decorator test: '+bar(some_string) 
    return test 
1

據我所知,調用bar('test1)基本上呼籲foo(bar('test1'))

不,是不正確的。

調用bar('test1')相當於

bar = foo(bar) 
bar('test1') 

爲什麼我要回到test的裝飾工作?直接返回裝飾者測試:'+ bar(some_string)不起作用,因爲some_string沒有定義。

當你

@decorator 
def func(): 
    pass 

Python的將其轉換爲

def func(): 
    pass 

func = decorator(func) 

正如你所看到的,Python所預期decorator返回一個功能。這就是爲什麼您必須從foo退回test,才能使bar正常工作。否則,None被分配到bar

>>> def foo(bar): 
    def test(some_string): 
     return 'Decorator test: '+bar(some_string) 


>>> @foo 
def bar(some_string): 
    return some_string[:3] 

>>> bar() 
Traceback (most recent call last): 
    File "<pyshell#6>", line 1, in <module> 
    bar() 
TypeError: 'NoneType' object is not callable 

如何測試瞭解some_string而富不?

只是因爲some_string不會創建,直到test達到。 some_stringtest的參數,所以它只存在於test的範圍內。否則,不存在名稱some_string,所以如果嘗試訪問它,則會得到NameError - 包括foo的內部。

如果你想printsome_string的價值,test內這樣做:

def foo(bar): 
    def test(some_string): 
     print(some_string) 
     return 'Decorator test: '+bar(some_string) 
    return test