day11-python函式基本操作
1.函式
1.1定義
函式是指將一組語句的集合通過一個名字或者說模組封裝起來,要想使用這個函式,只需要呼叫其函式名稱即可。
1.2 特點
- 減少程式碼的重複性
- 讓程式變得可擴充套件
- 程式容易維護
1.3 語法
def function(): # 函式關鍵字和函式名稱 pass # 函式體
function() # 函式呼叫
2. 函式引數
2.1 實參和形參
- 形參變數只有在被呼叫時才分配記憶體單元,在呼叫結束時,即刻釋放所分配的記憶體單元。因此,形參只在函式內部有效。函式呼叫結束返回主呼叫函式後則不能再使用該形參變數
- 實參可以是常量、變數、表示式、函式等,無論實參是何種型別的量,在進行函式呼叫時,它們都必須有確定的值,以便把這些值傳送給形參。因此應預先用賦值,輸入等辦法使引數獲得確定值
2.2 位置實參
呼叫函式時,Python必須將函式呼叫中的每個實參都關聯到函式定義中的對應形參,因此最簡單快捷的方式是基於實參的順序。這種關聯的方式被稱為位置實參。(使用位置實參來呼叫函式時,位置一定要正確)
def test(animal,name): print('我有個' + animal + ',它的名字是' + name.capitalize()) test('Dog','tom') # 我有個Dog,它的名字是Tom
2.3 關鍵字引數
關鍵字引數是傳遞給函式的 名稱-值 對。在實參中就將名稱和值關聯起來了,從而不用考慮函式呼叫中的順序,但是在使用關鍵字引數時,必須準確的指定函式定義中的形參名稱。
PS:關鍵字引數必須在位置引數之後。
def test(animal,name): print('我有個' + animal + ',它的名字是' + name.capitalize()) test(name='tom',animal='Dog') # 我有個Dog,它的名字是Tom
2.4 預設引數
這個引數在呼叫時不指定,那就預設;指定了的話,就用指定的值。
def test(animal,name = 'tom'): print('我有個' + animal + ',它的名字是' + name.capitalize()) test('Dog') # 我有個Dog,它的名字是Tom def test(animal,name = 'tom'): print('我有個' + animal + ',它的名字是' + name.capitalize()) test('Dog','jcak') # 我有個Dog,它的名字是Jcak
2.5 非固定引數
若你的函式在定義時不確定使用者想傳入多少個引數,就可以使用非固定引數
def test(name, age, *args): # *args 會把多傳入的引數變成一個元組形式 print(name, age, args) test("zxl", 18) # zxl 18 () #後面這個()就是args,只是因為沒傳值,所以為空 test("wl", 32, "CN", "Python",'ee') # wl 32 ('CN', 'Python', 'ee')
還可以有一個**kwargs
def stu(name, age, *args, **kwargs): # *kwargs 會把多傳入的引數變成一個dict形式 print(name, age, args, kwargs) stu("Alex", 22) # Alex 22 () {}#後面這個{}就是kwargs,只是因為沒傳值,所以為空 stu("Jack", 32, "CN", "Python", sex="Male", province="ShanDong") # Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}
3.全域性與區域性變數
- 在子程式中定義的變數稱為區域性變數,在程式的一開始定義的變數稱為全域性變數。
- 全域性變數作用域是整個程式,區域性變數作用域是定義該變數的子程式。
- 當全域性變數與區域性變數同名時:在定義區域性變數的子程式內,區域性變數起作用;在其它地方全域性變數起作用。
3.1 示例
a = 11 def test(): a = 10 print('函式體內:',a) print('函式體外(呼叫函式之前):',a) # 函式體外(呼叫函式之前): 11 test() #函式體內: 10 print('函式體外(呼叫函式之後):',a) #函式體外(呼叫函式之後): 11
3.2 global函式
global的作用是在函式體內建立修改全域性變數
a = 11 def test(): global a a = 10 print('函式體內:',a) print('函式體外(呼叫函式之前):',a) # 函式體外(呼叫函式之前): 11 test() #函式體內: 10 print('函式體外(呼叫函式之後):',a) #函式體外(呼叫函式之後): 10
4. 返回值
要想獲取函式的執行結果,就可以用return語句把結果返回,但是要注意:
- 函式在執行過程中只要遇到return語句,就會停止執行並返回結果,so 也可以理解為 return 語句代表著函式的結束
- 如果未在函式中指定return,那這個函式的返回值為None
5.遞迴
如果一個函式在內部呼叫自身本身,這個函式就是遞迴函式。
遞迴特性:
1. 必須有一個明確的結束條件
2. 每次進入更深一層遞迴時,問題規模相比上次遞迴都應有所減少
3. 遞迴效率不高,遞迴層次過多會導致棧溢位(在計算機中,函式呼叫是通過棧(stack)這種資料結構實現的,每當進入一個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴呼叫的次數過多,會導致棧溢位)
def test(n): print(n) if int(n / 2) == 0: return n test(int(n / 2)) test(20) # 20 10 5 2 1
6.匿名函式
匿名函式就是不需要顯式的指定函式名稱,本身無甚大用,但是配合其他函式使用時確實神器。。。
num = lambda w:2**w print(num(10))
6.1 和map函式一起使用
map函式的作用是會對一個序列物件中的每一個元素進行相關操作,並且返回一個包含所有結果的map序列。
res = map(lambda x:x*2,[1,5,7,4,8]) print(type(res)) # <class 'map'> for i in res: print(i)
# 2 10 14 8 16
6.2 filter函式
filter函式的作用是根據條件從序列中過濾出一些元素。
# 過濾出大於2的元素 res = filter(lambda x:x > 2,[1,5,7,4,8]) print(type(res)) # <class 'filter'> for i in res: print(i) # 5 7 4 8
6.3 reduce函式
reduce函式返回計算結果。為int型別。
from functools import reduce res = reduce(lambda x,y:x + y,list(range(1,10))) print(type(res),res) # <class 'int'> for i in res: print(i) # <class 'int'> 45
7.高階函式
變數可以指向函式,函式的引數能接收變數,那麼一個函式就可以接收另一個函式作為引數,這種函式就稱之為高階函式。
def add(x, y, f): return f(x) + f(y) def foo(x): return x res1 = add(3, -6, foo) res2 = add(3, -6, abs) print(res1,res2) # -3 9