Python裝飾器,就是複合函數

來源:互聯網
上載者:User

《python核心編程》這本書一看就知道是搞技術的人寫的,和我以前看qt的某些書籍一樣。東一榔頭西一棒子。不過還好,python的大部分我都知道了,看這本書不過是在查漏補缺,而且本身也有C/C++的基礎。如果是剛入門的同學,如果看這本書能看懂,那真是天才了。

不過如果你同我一樣,抱著查漏補缺的態度,那麼這本書會有很多閃光點。其中一個就是這個python裝飾器。

複合函數

學過數學的人,應該都知道複合函數或者運算元吧:z=h。g。f (h,g是運算元,f是g運算元的定義域), 圈是複合符號.這樣就形成了一個複合函數鏈。前面運算元的範圍是後面運算元的定義域。

如果我們把python中的普通函數看作f,那麼裝飾器就是後面的g,h 運算元 ,返回的z是與f具有接受相同參數能力的新函數f_new,那麼我門在使用的時候直接輸入f(),實際上就是使用的f_new()。

無參數裝飾器

  • 現在簡單來看下f_new=g。f的形式,也就是不帶參數的裝飾器。顯然g的定義域是python的普通函數f,傳回值是f_new。f_new與f具有接受相同參數的能力。

下面看看代碼說明:

def foo():    print 'in foo()'def wrap(func):    print 'in wrap'    return func

這個foo()函數是普通的python函數,它可以作為運算元g的輸入;下面的wrap定義域是func函數,返回的也是一個與輸入func同類型的函數,顯然它就是運算元g

@wrapdef foo():    print 'in foo()'foo()

現在有 foo=f_new=wrap 。 foo ; 現在再調用foo(),實際上就是調用的f_new()也就是 (wrap。foo) ()

帶參數裝飾器

  • 現在來看代參數的裝飾器,其數學運算式為:f_new=g(x)。f  ;同樣,f是我們的普通的python函數。不同的是先用運算元g,產生一個新的運算元g(x),g(x)的定義域才是f,返回的函數為與f同類型的f_new。

下面是代碼說明:

def wrap_out(arg):    print 'in wrap_out,and arg is %s'%arg    def wrap_inner(func):        print 'in wrap_inner'        return func    return wrap_inner@wrap_out('test1')def foo()    print 'in foo'foo()

現在就有foo=f_new=wrap_out(arg)。foo

寫成方程組:

wrap_inner=wrap_out(arg) 

foo=wrap_inner(foo)

有了上面的理解後,就應該非常清楚,封裝函數內部應該是什麼結構,應該返回什麼。只要把函數的複合鏈寫出來,就很容易搞清楚裝飾器的結構。

比如上面的帶參數的裝飾器,我看過很多同學寫的解釋,反正就是很複雜。但是如果把foo=wrap_out(arg)。foo 寫出來分析下。wrap_out帶參數arg,而且它返回的值必須能接受foo函數,也就是wrap_inner=wrap_out(arg),wrap_inner必須能接受foo作為輸入。再著,wrap_inner(foo)返回的值必須是一個和原foo接受統一的參數的函數,。那整個結構就很清楚了。

很多裝飾器的複合

現在來看一個比較複雜的,雙重的裝飾器。

def wrap_out2(arg):    print('in wrap_out 2 ,and arg is %s'%arg)    def wrap_inner2(func):        print('in wrap_inner 2')        func('in wrap 2 call func')        def fun_new2():            print('in func_new  22')        return fun_new2    return wrap_inner2def wrap_out(arg):    print('in wrap_out,and arg is %s'%arg)    def wrap_inner(func):        print('in wrap_inner')        func()        def func_new(h):            print(h)        return func_new    return wrap_inner#foo_new=wrap_out2('world') o wrap_out('hello') o foo@wrap_out2('world')@wrap_out('hello')def foo():    print('in foo')foo()

輸出結果為:

in wrap_out 2 ,and arg is world
in wrap_out,and arg is hello
in wrap_inner
in foo
in wrap_inner 2
in wrap 2 call func
in func_new  22

數學式子為:

foo=wrap_out2('world')。wrap_out('hello')。foo

通過輸出結果可以判斷其化解順序為:
foo=wrap_inner2。wrap_out('hello')。foo

foo=wrap_inner2。wrap_inner。foo

也就是說運算元化簡是從左至右,而普通計算是從右至左。要是這樣都不能理解裝飾器,那就只有去撞牆了。^_^

還可以看到wrap_out 和wrap_out2的輸入與輸出是不同的,在數學上輸入與輸出相同稱為變換,如果不同那麼只能稱為映射了。映射不能隨意的匹配,在這裡只能寫成wrap_out2。wrap_out的形式,而不能顛倒它們的複合順序。當然一般的裝飾器,都是經過一定處理後,返回原函數,也就是變換。

綜上:func=h([arg])。g([arg])。func =T 。func  ;T就是一個運算元,它的定義域和範圍都是接受相同參數的 func 。老func 輸入 T 返回同類型的 新func 。也就是說裝飾器就是運算元T,整個運算元T是func空間的變換;over

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.