天天看點

Python之裝飾器

在Python中一切皆對象,函數是一等對象。這意味着可以通過名字引用函數。

1

2

3

4

5

6

7

8

9

10

11

12

13

<code>&gt;&gt;&gt; a=123</code>

<code>&gt;&gt;&gt; a</code>

<code>123</code>

<code>&gt;&gt;&gt; name=</code><code>'zeng'</code>

<code>&gt;&gt;&gt; name</code>

<code>'zeng'</code>

<code>&gt;&gt;&gt; def func():</code>

<code>...     print </code><code>"hello!"</code>

<code>...</code>

<code>&gt;&gt;&gt; func</code>

<code>&lt;</code><code>function</code> <code>func at 0x1066bdc08&gt;</code>

<code>&gt;&gt;&gt; func()</code>

<code>hello!</code>

從上面的例子可以看出,調用函數時隻需要函數名後面加‘()’即可。如果不加,則傳回函數記憶體位址。

函數還可以作為值傳遞

<code>&gt;&gt;&gt; dict = {</code><code>'func'</code><code>:func}</code>

<code>&gt;&gt;&gt; aaa = dict[</code><code>'func'</code><code>]</code>

<code>&gt;&gt;&gt; aaa</code>

<code>&gt;&gt;&gt; aaa()</code>

從上面的例子可以看到,函數可以作為值儲存到字典dict的‘func’這個key中。然後将函數這個值又可以指派給變量aaa,當執行aaa時,傳回的是函數的記憶體位址,如果調用函數則執行aaa()

函數可以作為值傳遞,那麼是否可以作為參數傳遞呢?

<code>&gt;&gt;&gt; def func1():</code>

<code>...     </code><code>return</code> <code>"I am an amazing function"</code>

<code>&gt;&gt;&gt; def printer(arg):</code>

<code>...     print </code><code>"The function passwd to me says:"</code> <code>+ arg()</code>

<code>&gt;&gt;&gt; printer(func1)</code>

<code>The </code><code>function</code> <code>passwd</code> <code>to me says:I am an amazing </code><code>function</code>

<code>&gt;&gt;&gt;</code>

從上面的例子可以看到,函數完全可以作為參數傳遞。而且傳遞給函數的函數還可以被調用

裝飾器的基礎:

本質上裝飾器就是一個以另一個函數作為參數的函數。看下面的例子:

上面的例子中當執行decorated_function()時,調用了decorated_function函數,而

decorated_function = identity_decorator(a_function),是以調用decorated_function()函數,實際上就是調用了 identity_decorator( )函數。而 identity_function( )函數傳回的是wrapper( )函數的記憶體位址。是以調用 identity_decorator( )函數最終會調用wrapper( )函數,而wrapper( )函數則是調用了

identity_decorator(func)函數的參數。這個參數本身就是a_function()函數,是以最終結果是調用了a_function()函數,輸出結果就是a_function()的輸出結果。

那麼問題來了,上面這個例子饒了一大圈,結果就是調用了a_function()函數,那麼完全可以直接調用a_function()函數,何必兜一圈子呢,是以上面這個例子是一個沒有意義的裝飾器。

下面看一個有意義的裝飾器

上面代碼中@login是裝飾器的寫法。意思是将@login下面的函數作為login()函數的參數。也可以這樣寫

buy = login(buy)

當執行@login時,實際上就是執行了buy = login(buy)

意思是将buy函數作為參數調用login函數,并将結果指派給buy這個變量中。而login函數傳回的是inner函數的記憶體位址。是以當執行buy('zeng')時,其實是調用inner函數,此時會執行

 執行func(arg),則實際上是執行login函數的參數這個函數,這個函數就是buy函數,是以此時會調用buy函數,并将‘zeng’這個參數傳遞到buy函數中,是以結果就是既執行了inner函數,又執行了buy函數。

本文轉自 曾哥最愛 51CTO部落格,原文連結:http://blog.51cto.com/zengestudy/1828019,如需轉載請自行聯系原作者