2道極好的Python算法題|帶你透徹理解裝飾器的妙用

編程語言 Python 大數據 兔子 天善智能 2017-04-06

每日干貨好文分享丨請點擊+關注

歡迎關注天善智能微信公眾號,我們是專注於商業智能BI,大數據,數據分析領域的垂直社區。

對商業智能BI、大數據分析挖掘、機器學習,python,R等數據領域感興趣的同學加微信:tstoutiao,邀請你進入頭條數據愛好者交流群,數據愛好者們都在這兒。

前一篇講了裝飾器額基本知識,裝飾器我個人認為是Python中最最最難的知識點,上一篇算是一個入門的介紹,有18個小夥伴給我留言,後臺也有很多同學跟我討論,大家總是覺得不過癮,好像離深入理解還差那麼一丟丟趕腳,裝飾器到底有啥妙用呢,其實裝飾器內容非常豐富,今天我分享兩道非常好的算法題,大家耐心看完兩道算法題之後,注意精華在最後,我相信大家對裝飾器的理解又會更上一層樓.

1.斐波那契數列

1).這個序列非常有名,我非常喜歡這個序列(有同學問我為啥,偷偷告訴大家,這個序列幫了我不少忙,等下半年我寫數據分析文章的時候,會跟大家分享心得)

這個序列也叫兔子序列,網上有很多關於這個序列的解法,我們就直接上代碼

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

我們用推導列表把兔子序列前10項打印出來,有同學說這個跟裝飾器有毛關係,不要急,如果我們若打印40項,看看需要花多少時間

import time

start=time.time()

[fib(n) for n in range(40)]

end=time.time()

print 'cost:{}'.format(end-start)

>>

cost:150.200000048

如果我們打印50項,則需要花更多的時間,光40項需要花150多秒,50項就更長了.難是因為這個運算量太大了嗎,NONONO,是因為我們算法沒有經過優化.

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

看上面這張圖,你會發現我們在計算兔子序列的時候,有大量重複的計算,比如算F(10)=F(9)+F(8),F(9)=F(8)+F(7),F(8)需要重複計算兩次~~

怎麼破,很容易想到我們需要用一個緩存,把這個計算過的數字存在一個表裡面,用的時候若這個數字在這個表,就不用再花cpu去運算,直接取就好了。

2).先把上面的代碼改一下,我們申明一個count變量,每次遞歸都存起來,然後最後再返回

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

3).接著演變,我們現在構造一個緩衝區cache

我們查表,比如用字典來保存,比如cache[8]=34,我們只需要查一下8是不是在字典裡面就可以了,在的話直接取,不在的話再去用算法計算,是不是很爽

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

看運行40項,幾乎不費吹灰之力,非常快

2.爬樓梯

比如我有7階臺階,我們可以用兩種爬發,一次一步或者兩步,只能進不能退,算算有多少種爬法

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

我們先簡單分析一下:

若只有一階臺階,那麼不管是一次選擇一步還是兩步,都只有一種爬法

若只有兩階臺階,選擇一步or兩步,會有兩種爬法

若只有三階臺階,選擇一步然後一步然後一步,或者一步,兩步,或者兩步,一步,這樣有3種爬法

若只有四階臺階,選擇一步,然後剩下3階臺階的爬法,這3階爬法可以直接取前面3階臺階的計算結果

我們先寫源碼,源碼很簡單用遞歸搞定,首先設計遞歸的出口,當只有1階或者小於1階臺階時候,直接return 1

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

大家有沒有發現這個爬樓梯一樣存在重複計算的問題,比如5階的時候,一步一步然後剩下3步,或者兩步然後剩下3步

一樣需要用到兔子序列的cache方法,那麼在climb函數中再重複寫一篇,是不是很累贅,這不是Pythonic的風格,有沒有比較好的封裝方法呢,同時又能不改動原始的代碼呢~~有的,牛逼閃閃的Python當然有,就是我們的裝飾器啦,好我們看裝飾器如何封裝搞定

3.裝飾器封裝

對於兔子序列和爬樓梯,我們用裝飾器去封裝一下,怎麼封裝呢,我們一步一步來,參考上一篇入門很容易構建出來

1).創建一個裝飾器

def decorate(func):

cache={}

def wrap(n):

if n not in cache:

cache[n]=func(n)

return cache[n]

return wrap

2).裝飾一下斐波那契數列

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

是不是很簡潔,裝飾器真是個好東西啊~~

3).裝飾器參數升級

大家有沒有發現我們上面構造的裝飾器,入參是一個參數n.如果碰到需要傳入的多個參數的函數怎麼辦,比如我們的爬樓梯原函數就是2個參數,所以我們需要把裝飾器寫更通俗一點,對用變參

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

留幾個問題:

1.print climb(5,(1,2))為啥不是[1,2]

2.為啥不能加else

def decorator(func):

cache={}

def wrap(*args):

if args not in cache:

cache[args]=func(*args)

else:

return cache[args]

return wrap

3.加緩衝的時候

def fib(n,cache=None):

為啥不能寫成def fib(n,cache={}):

好了裝飾器的妙用就講到這裡,大家想一想如果我們還有類似的代碼需要緩存機制,是不是隻需要用裝飾器封裝一下就行了,是不是代碼簡潔很多而且容易維護和擴展功能,講到這裡大家是不是對裝飾器的妙用有了進一步的理解,若有什麼不懂的,也可以留言跟我探討交流

對商業智能BI、大數據分析挖掘、機器學習,python,R等數據領域感興趣同學加微信:tstoutiao,邀請您加入頭條數據愛好者交流群,數據愛好者們都在這兒。

2道極好的Python算法題|帶你透徹理解裝飾器的妙用

本文來源自天善社區菜鳥學python的博客(公眾號)。

原文鏈接:https://ask.hellobi.com/blog/caoniao_xueyuan 。

相關推薦

推薦中...