#函數python
1 什麼是函數?
2 爲何要用函數? 3 函數的分類:內置函數與自定義函數 4 如何自定義函數 5 語法 6 定義有參數函數,及有參函數的應用場景 7 定義無參數函數,及無參函數的應用場景 8 定義空函數,及空函數的應用場景 9 調用函數 10 如何調用函數 11 函數的返回值 12 函數參數的應用:形參和實參,位置參數,關鍵字參數,默認參數,*args,**kwargs 13 高階函數(函數對象) 14 函數嵌套 15 做用域與名稱空間 16 裝飾器 17 迭代器與生成器及協程函數 18 三元運算,列表解析、生成器表達式 19 函數的遞歸調用 20 內置函數 21 面向過程編程與函數式編程
生活中要作某件事的時候,可能會用到各類工具,且能夠重複使用。git
遇到這種狀況,如何解決問題:編程
工具就具有某一種功能的物件,就是程序中的函數的概念app
事先準備工具的過程稱爲函數的定義函數式編程
遇到特定的場景拿來就用稱爲函數的調用函數
函數的分類工具
內置函數: 爲了方便開發,針對一些簡單的功能,python解釋器已經爲咱們定義好了的函數即內置函數。spa
對於內置函數,咱們能夠拿來就用而無需事先定義,如len(),sum(),max()設計
自定義函數 :很明顯內置函數所能提供的功能是有限的,這就須要咱們本身根據需求,事先定製好咱們本身的函數來實現某種功能,code
之後,在遇到應用場景時,調用自定義的函數便可。
函數的定義語法:
關鍵字 def 來定義
def 函數名 (參數1,參數2,。。。):
「註釋」
函數體
return 返回值 # 若此處爲print() 則函數的值不能賦值給變量
函數名通常是動詞,表示一個功能,要幹什麼
註釋信息必定要有
return :函數內部能夠沒有return,返回None,等同於 return None
若是return 後面跟一個值 , 將返回該值 , 這個值沒有類型限制, 字符串、數字、列表等均可以返回
若是return 後面跟多個值 , 將返回一個元組,裏面包含多個值
也能夠有多個return,可是隻能執行一次,函數就結束調用,而且會吧return後的值做爲函數執行的結果返回。
何時該有返回值? 調用函數,通過一系列的操做,最後要拿到一個明確的結果,則必需要有返回值。 一般有參函數須要有返回值,輸入參數,通過計算,獲得一個最終的結果。 何時不須要有返回值? 調用函數,僅僅只是執行一系列的操做,最後不須要獲得什麼結果,則無需有返回值。 一般無參函數不須要有返回值。
函數的使用,兩個階段
一、先定義 : def func-name(空,或者參數1,參數2,。。。):
func
ruturn 值
二、再調用 : func-name()
函數在定義階段,只檢測語法,不執行代碼。
函數在調用階段,找已經定義的函數的名字,執行函數的內容
函數名和變量名:
本質同樣,都是名字,函數的定義與變量的定義相似,沒有事先定義變量,而直接引用變量,會報錯
沒有事先定義函數,而直接引用函數,至關於在引用一個不存在的變量名。
函數名加括號能夠傳參,變量名不行
定義函數的三種形式:
無參函數:應用場景僅僅只是執行一些操做,好比與用戶交互、打印,通常就是一些可執行的語句,普通操做等等
有參函數:須要根據外部傳進來的參數,才能執行響應的邏輯,好比統計長度、求最大值等等
空函數: 設計代碼結構,編程的一種思路
def bar():
pass
1 #有參函數,注意返回值用return 2 #求最大值 3 def my_max(x,y): 4 if x > y: 5 # print(x) #若爲print 則返回的值不能賦值給變量 6 return x 7 else: 8 # print(y) 9 return y 10 11 res=my_max(1,2) 12 print(res)
函數調用的三種形式(如上例):
調用函數的語句形式 : my_max(1,2)
調用函數做爲表達式 : my_max(1,2)*10
將函數做爲另外一個函數的參數 : my_max(my_max(1,2) , 3)
函數參數:
形參 : 形式上的參數,不佔內存空間,實際上就是變量名
實參 : 實際存在的參數,佔內存空間,實際上就是變量值
在定義函數階段,函數括號內的參數是形參
在調用函數階段,函數括號內的參數是實參
變量名和變量值是綁定關係,再調用階段,實參(變量值)纔會綁定到形參(變量名),調用結束後,解除綁定。
參數的分類:
位置參數 :按照從左到右的順序,依次定義的參數
位置形參:必選參數,必須被傳值,多一個不行,少一個也不行
位置實參:按照位置給形參傳值,與形參按照位置一一對應
關鍵字參數---關鍵字實參:無需按照位置爲形參傳值
按照name = value 的形式定義的實參,指名道姓的給name傳值 fun(age = 18 , name= 'lalal')
注意的問題:
1. 關鍵字實參必須在位置實參右面
2. 對同一個形參不能重複傳值
位置實參必須在關鍵字實參前面,關鍵字參數只能放在位置實參後面。
形參 在什麼狀況下 必須被定義 , 每次都須要一個不一樣的值, 就要定義成位置參數。
形參 默認參數是 , 值是固定的,每次調用均可以不傳值。
默認參數須要注意的問題:
問題一:默認參數要在位置參數以後,不然報錯
def foo(x , y=1)
print(x,y)
問題二:默認參數,只在定義階段賦值一次,並且,僅賦值一次。
問題三: 默認參數的值,應該定義成不可變類型
默認參數:形參在定義時就已經爲其賦值
能夠傳值也能夠不傳值,常常須要變得參數定義成位置形參,變化較小的參數定義成默認參數(形參) 注意的問題: 1. 只在定義時賦值一次 2. 默認參數的定義應該在位置形參右面 3. 默認參數一般應該定義成不可變類型
可變長參數: 指的是 實參的個數多了,不固定(實參有位置實參和關鍵字實參兩種)
形參必需要兩種機制來分別處理
按照位置定義的實參溢出的狀況: *變量名 (一般 *args) *就到表多出來的位置參數
按照關鍵字定義的實參溢出的狀況: **變量名 (一般 **kwargs)
可變長指的是實參值的個數不固定
而實參有按位置和按關鍵字兩種形式定義,針對這兩種形式的可變長,形參對應有兩種解決方案來完整地存放它們,分別是*args,**kwargs
1 #可變長位置實參 2 def foo(x,y,*num): 3 print(x) 4 print(y) 5 print(num) 6 foo(2,4,6,8,9,3,5,) 7 8 #結果 9 2 10 4 11 (6, 8, 9, 3, 5) #多出來的參數,會組成一個元組,賦值給num
1 #可變長關鍵字實參 ** 2 def foo(x,y,**num): 3 print(x) 4 print(y) 5 print(num) 6 foo(x=5,y=7,z=0,d=8,k=9,s=2,) 7 8 #結果 9 5 10 7 11 {'z': 0, 'd': 8, 'k': 9, 's': 2} #多餘的關鍵字實參,會組成一個字典,賦值給num
擴展用法
若遇到實參裏面有*的參數,把參數打回原形,再傳參
1 def foo(x,y): 2 print(x) 3 print(y) 4 #foo(2,4,*(6,8,9,3,5,)) #實參中有*號,表示的是多餘的位置實參,打回原形至關於 foo(2,4,6,8,9,3,5,),則最終會報錯 5 foo(2,*(6,)) #若實參的個數恰好和形參一一對應,則能夠正常賦值,不報錯 6 7 #結果 8 2 9 6
命名關鍵字參數:在*後面定義的形參稱爲命名關鍵字參數,必須是被以關鍵字實參的形式傳值
1 #這倆東西 *args,**kwargs作什麼用??? 2 def register(name,age,sex='male'): 3 print(name) 4 print(age) 5 print(sex) 6 7 ##裝飾器概念(不改源代碼的狀況下,知足要求),一個函數調用另外一個函數 8 def wrapper(*args,**kwargs): #萬用形參,不過切記,位置參數在關鍵字參數前面 9 print(args) 10 print(kwargs) 11 register(*args,**kwargs) #調用另外一個函數 12 # register(*(1, 2, 3),**{'a': 1, 'b': 2}) 13 # register(1, 2, 3,a=1,b=2) 14 15 16 wrapper('lalala' , 28) #實參是什麼就原生態的傳給register什麼
練習:
函數對象: 函數是第一類對象,能夠被當作數據傳遞
被賦值
能夠當作參數傳入
能夠當作函數的返回值
能夠當作容器類型的元素
1 ''' 2 階段性練習 3 一、寫函數,,用戶傳入修改的文件名,與要修改的內容,執行函數,完成批了修改操做 4 二、寫函數,計算傳入字符串中【數字】、【字母】、【空格] 以及 【其餘】的個數 5 6 三、寫函數,判斷用戶傳入的對象(字符串、列表、元組)長度是否大於5。 7 8 四、寫函數,檢查傳入列表的長度,若是大於2,那麼僅保留前兩個長度的內容,並將新內容返回給調用者。 9 10 五、寫函數,檢查獲取傳入列表或元組對象的全部奇數位索引對應的元素,並將其做爲新列表返回給調用者。 11 12 六、寫函數,檢查字典的每個value的長度,若是大於2,那麼僅保留前兩個長度的內容,並將新內容返回給調用者。 13 dic = {"k1": "v1v1", "k2": [11,22,33,44]} 14 PS:字典中的value只能是字符串或列表 15 ''' 16 17 #======================>> 18 19 20 #題目一 21 def modify_file(filename,old,new): 22 import os 23 with open(filename,'r',encoding='utf-8') as read_f,\ 24 open('.bak.swap','w',encoding='utf-8') as write_f: 25 for line in read_f: 26 if old in line: 27 line=line.replace(old,new) 28 write_f.write(line) 29 os.remove(filename) 30 os.rename('.bak.swap',filename) 31 32 modify_file('/Users/jieli/PycharmProjects/爬蟲/a.txt','alex','SB') 33 34 #題目二 35 def check_str(msg): 36 res={ 37 'num':0, 38 'string':0, 39 'space':0, 40 'other':0, 41 } 42 for s in msg: 43 if s.isdigit(): 44 res['num']+=1 45 elif s.isalpha(): 46 res['string']+=1 47 elif s.isspace(): 48 res['space']+=1 49 else: 50 res['other']+=1 51 return res 52 53 res=check_str('hello name:aSB passowrd:alex3714') 54 print(res) 55 56 57 #題目三:略 58 59 #題目四 60 def func1(seq): 61 if len(seq) > 2: 62 seq=seq[0:2] 63 return seq 64 print(func1([1,2,3,4])) 65 66 67 #題目五 68 def func2(seq): 69 return seq[::2] 70 print(func2([1,2,3,4,5,6,7])) 71 72 73 #題目六 74 def func3(dic): 75 d={} 76 for k,v in dic.items(): 77 if len(v) > 2: 78 d[k]=v[0:2] 79 return d 80 print(func3({'k1':'abcdef','k2':[1,2,3,4],'k3':('a','b','c')}))