小白學習之路,基礎三(函數)
一,函數的基本介紹
首先談到函數,相信大家都不陌生,不管是其他語言都會用到,可能就是叫法不一樣。就我知道的跟python中函數類似的,在C中只有function,在Java裏面叫做method,在js中也是叫function。函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段。函數能提高應用的模塊性,和代碼的重復利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。
函數有下面三點好處:
1.能夠減少重復代碼的使用
2.讓你的程序有更好的擴展性
3.可以讓你的程序變得更加容易維護
下面我們就來講一下怎麽定義一個函數
- 函數代碼塊以 def
- 任何傳入參數和自變量必須放在圓括號中間。圓括號之間可以用於定義參數。
- 函數的第一行語句可以選擇性地使用文檔字符串—用於存放函數說明。
- 函數內容以冒號起始,並且縮進。
- return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。
二,函數的參數
函數可以傳參,也可以不傳參,都是可以的哦。
1 #定義一個需要傳參的函數 2 def say(name): 3 print(‘hello‘,name) 4 say(‘zzq‘) #調用say這個函數,並且傳入參數 5 6 #不需要傳參的函數View Code7 def take(): 8 print(‘I Love You‘) 9 take() #調用函數,不傳任何參數 10 11 #有返回值的函數 12 def add(x,y): 13 return x+y 14 a=add(4,5) #傳入的參數必須是相同數據類型 15 print(a) #執行結果為9
值得註意的是在傳入的參數還有三種:普通參數,不定長參數,自典型
1 #普通參數 2 def say1(name): 3 print(name) 4 say1(‘gmx‘) 5 6 #不定長參數 7 def say2(*args):View Code8 print(args) 9 say2(1,5,‘sd‘) 10 11 #自典型 12 def say3(**kwargs): 13 print(kwargs) 14 say3(name=‘zzq‘,say=‘I Love You‘,to_name=‘gmx‘)#傳入的參數必須是字典 15 16 #執行結果為 17 #gmx 18 #(1, 5, ‘sd‘) 19 #{‘name‘: ‘zzq‘, ‘say‘: ‘I Love You‘, ‘to_name‘: ‘gmx‘}
聽到參數大家還經常聽到形參跟實參這兩個詞,下面我跟大家大概講一下兩者的區別。
- 形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量
- 實參可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。因此應預先用賦值,輸入等辦法使參數獲得確定值
三,全局變量跟局部變量
什麽是全局變量跟局部變量呢,根據他們的名字可以知道,全局變量可以在全局使用,局部變量呢只能在一些地方使用的變量。
在函數裏面定義的變量為局部變量,只能試用於函數。
在外面定義的叫全局變量,也可以在函數內部訪問。
切記!如果全局變量有一個變量名字跟函數裏面的相同,函數內部在調用時,用的是函數內部的變量
1 name=‘zzq‘ 2 def say(): 3 name=‘gmx‘ 4 print(name)#調用的是函數內部的name 5 say() 6 print(name)#調用的全局變量的name 7 8 #執行結果 9 #gmx 10 #zzqView Code
在函數中的局部變量也能轉化為全局變量,但是這種方法是不推薦使用的,也是不能使用的。
1 name=‘zzq‘ 2 def say(): 3 global name #把name設置為全局變量 4 name=‘gmx‘ 5 print(name) 6 say() 7 print(name) 8 #執行結果 9 #gmx 10 #gmxView Code
四,匿名函數
python 使用 lambda 來創建匿名函數,一般一個函數用的次數比較少,為了方便就出現了匿名函數。
- lambda只是一個表達式,函數體比def簡單很多。
- lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
- lambda函數擁有自己的命名空間,且不能訪問自有參數列表之外或全局命名空間裏的參數。
- 雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不占用棧內存從而增加運行效率。
匿名函數基本語法:
1 #計算數字的平方 2 calc=lambda n:n*n #定義一個匿名函數 3 print(calc(5)) 4 5 #當然還能這樣用 6 l=map(lambda n:n*n,[1,2,3,4,5]) #map把後面可叠代對象去執行前面的函數 7 for i in l: 8 print(i)
在這裏用到了map,那就簡單的提一下把。因為要涉及到後面的叠代對象,所以就簡單講一下用法。
map函數的原型是map(function, iterable, …),它的返回結果是一個列表。
參數function傳的是一個函數名,可以是python內置的,也可以是自定義的。
參數iterable傳的是一個可以叠代的對象,例如列表,元組,字符串這樣的。
解釋起來有點不好理解,下面一些簡單的代碼例子,供大家參考吧。
1 a=(1,2,3,4,5) 2 b=[1,2,3,4,5] 3 c="zhangkang" 4 5 la=map(str,a) 6 lb=map(str,b) 7 lc=map(str,c) 8 9 print(la) 10 print(lb) 11 print(lc) 12 13 輸出: 14 [‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘] 15 [‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘] 16 [‘z‘, ‘h‘, ‘a‘, ‘n‘, ‘g‘, ‘k‘, ‘a‘, ‘n‘, ‘g‘]View Code
五,嵌套函數
嵌套函數,聽到名字難道是一個函數裏面還可以放函數,臥槽,居然特麽還有這種操作?當然,嵌套函數就是一個函數裏面還嵌套另外一個函數,下面一個簡單的例子,給大家參考理解吧。
1 name=‘zzq‘ 2 def say1(): 3 name=‘gmx‘ 4 def say2(): 5 name=‘other‘ 6 print(‘最裏面函數‘,name) 7 say2() 8 print(‘外面一層函數‘,name) 9 say1() 10 print(‘最外面函數‘,name) 11 12 #執行結果 13 #最裏面函數 other 14 #外面一層函數 gmx 15 #最外面函數 zzqView Code
六,遞歸
我們剛剛了解了嵌套函數,知道在函數的內部可以繼續調用函數,如果在函數的內部調用自己,那麽這個函數就是遞歸。當然遞歸不能隨便亂用,他也有自己的調用特性。
遞歸特性:
1. 必須有一個明確的結束條件
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少
3. 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)
1 #輸入一個數,輸出所有平方小於500的數 2 def calc(n): 3 if n>500: 4 return n 5 print(n) 6 return calc(n*n) #繼續調用自己,形成遞歸 7 calc(2) 8 9 #執行結果 10 2 11 4 12 16 13 256View Code
七,高階函數
變量可以指向函數,函數的參數能接收變量,那麽一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。通俗的講就是函數的參數可以是函數,然後裏面的參數可以給作為參數的函數當成傳入的參數。emmm,好吧,講得是有點亂。。那就分析分析代碼吧
1 輸入ascii的編碼號,輸出對應的值 2 def say(letter,f): 3 return f(letter) 4 ascii_name=say(65,chr)#f為一個函數 5 print(ascii_name) 6 #執行結果 7 #AView Code
臥槽,不知不覺學了這麽多函數了啊,你就會想這個學了有啥子用嘛,放心,這個為後面厲害的裝逼的打基礎呢,這章的嵌套函數跟高階函數為後面的裝飾器打基礎。萬丈高樓平地起,所以還是要把基礎掌握好,怎麽才能更好的掌握呢,當然方法只有一個,那就是多敲,多記,多思考。
小白學習之路,基礎三(函數)