最近老是在想「成長」這兩個很經常被提起的事情,這對於一個已經25歲的半中年而言,已是一個不太能高頻提起的詞。
可是,最近一些事情吧,總讓我以爲個人生長期彷佛比正常人來的晚了些,一些屬於青春期的標誌,好比叛逆,好比和家長吵架等等最近才發生在個人身上。
而在這些所謂的鬥爭中,其實最核心不過是,我在被迫成長。溫室裏躲久了,彷佛也會懼怕外面的風吹雨打,可是若是這把年紀了還不走,這輩子是否就這樣安穩不起波瀾的一生呢?
會在小小的格子間裏,抱怨着工做的各類奇怪症狀,吐槽着奇奇怪怪的喜歡吃糖很大聲的同事。
可是彷佛這並非我想要的,因此每當我寫這些叨逼叨的時候,其實就是給本身打雞血的時候,願咱們都心願達成!
算法
最近嘗試開始刷leetcode題目,用Python刷。
然鵝被吊打的不要不要的,要開始回頭看起數據結構和算法啦~
可是基礎仍是很重要滴,因此2018年的最後一個小目標呢,就是在2019年來臨以前刷完正在看的Python教程。數組
Python的函數定義很是簡單,但靈活度卻很是大。除了正常定義的必選參數外,還可使用默認參數、可變參數和關鍵字參數,使得函數定義出來的接口,不但能處理複雜的參數,還能夠簡化調用者的代碼。
這個是咱們很熟悉的朋友,在以往的語法中都很瞭解了,在調用函數的時候,按順序賦值。數據結構
設置默認參數時,有幾點要注意:
一是必選參數在前,默認參數在後,不然Python的解釋器會報錯;
二是如何設置默認參數。
當函數有多個參數時,把變化大的參數放前面,變化小的參數放後面。變化小的參數就能夠做爲默認參數。
定義默認參數要牢記一點:默認參數必須指向不變對象!
數據結構和算法
參數個數不肯定的時候,咱們考慮使用list或者tuple傳參。
1.當咱們有不定個數的參數時候,在位置參數前加上*
,在函數內部接收到的就是一個tuple。這樣就能夠傳入任意個數的參數。函數
2.當咱們已經有一個list的時候,能夠這麼幹↓Python容許你在list或tuple前面加一個*號,把list或tuple的元素變成可變參數傳進去學習
可變參數能夠傳入0個或任意個參數。
優化
關鍵字參數容許你傳入0個或任意個含參數名的參數,這些關鍵字參數在函數內部自動組裝爲一個dict。spa
def person(name,age,**kw): print('name:',name,'age:',age,'others:',kw)
**kw
用來接受任意個數的關鍵詞參數,它也能夠啥都沒有3d
和可變參數相似,也能夠先組裝出一個dict,而後,把該dict轉換爲關鍵字參數傳進去。
注意此處,kw得到的dict實際上是extra
的拷貝,函數內對kw的改變不會影響到extra。code
咱們在關鍵字參數中,只有在函數內才能檢查kw
到底傳入哪些參數。
若是須要限制關鍵字參數的名字,就須要命名關鍵字參數,並用*
隔開。
def person(name, age, *, city, job): print(name, age, city, job)
若是函數定義中已經有了一個可變參數,後面跟着的命名關鍵字參數就再也不須要一個特殊分隔符*了:
def person(name, age, *args, city, job): print(name, age, args, city, job)
命名關鍵字參數必須傳入參數名,這和位置參數不一樣。
命名關鍵字參數能夠有缺省值,從而簡化調用。在具備默認值的時候,可不傳入相關參數
使用命名關鍵字參數時,要特別注意,若是沒有可變參數,就必須加一個 做爲特殊分隔符。若是缺乏,Python解釋器將沒法識別位置參數和命名關鍵字參數。
在Python中定義函數,能夠用必選參數、默認參數、可變參數、關鍵字參數和命名關鍵字參數,這5種參數均可以組合使用。
可是請注意,參數定義的順序必須是:**必選參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數。
其實之前學遞歸的時候,第一個想到的是那個故事:
從前有座山,山裏有座廟,廟裏有個老和尚和小和尚,有一天老和尚跟小和尚說:我給你講個故事吧。從前有座山,山裏有座廟,廟裏有個老和尚和小和尚....
可是遞歸不是死循環,總有一天仍是會出來的,雖然用的是本身的套路。(很土的說法吧hhh)
來個正經的定義吧:在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數。
好比計算階乘n!
用遞歸能夠醬紫寫↓
遞歸函數的優勢是定義簡單,邏輯清晰。理論上,全部的遞歸函數均可以寫成循環的方式,但循環的邏輯不如遞歸清晰。
使用遞歸函數須要注意防止棧溢出。解決遞歸調用棧溢出的方法是經過尾遞歸優化,事實上尾遞歸和循環的效果是同樣的,因此,把循環當作是一種特殊的尾遞歸函數也是能夠的。
尾遞歸
是指,在函數返回的時候,調用自身自己,而且,return語句不能包含表達式。這樣,編譯器或者解釋器就能夠把尾遞歸作優化,使遞歸自己不管調用多少次,都只佔用一個棧幀,不會出現棧溢出的狀況。
上面的代碼的return中帶了乘法表達式,因此不符合尾遞歸。
看了下廖老師的修改優化後的代碼
def fact(n): return fact_iter(n, 1) def fact_iter(num, product): if num == 1: return product return fact_iter(num - 1, num * product)
在此次的計算中,每次都會把num - 1
和producct
的結果計算出來後再進行調用fact_iter
函數,因此棧不會增加。
廖老師給了兩個方法的棧對比圖,雖然懵逼中,可是仍是學習到了。
但願本身寫的時候能夠順順利利。
未優化前↓
優化後↓