函式/方法(高階)
函式引數
函式的定義與呼叫
- 定義格式:
def 函式名(形參):
函式體
......
複製程式碼
- 呼叫格式:
函式名(實參) 實際引數
複製程式碼
預設引數
預設引數:函式/方法在定義是為形參賦值,對應的形參稱為預設引數。 預設引數在呼叫時如果沒有對應的實參,則使用預設值作為該引數的值。
- 預設引數定義格式:
def 函式名(形參1 = 值1,...):
函式體
.....
複製程式碼
- 呼叫格式一:
函式名(實參) 使用實參作為形參的值
複製程式碼
- 呼叫格式二:
函式名() 使用預設值作為形參的值
複製程式碼
程式碼演示
def test (a,b=2):
pritn(a)
print(b)
test(1)
1
2
複製程式碼
引數格式混用一
def test (c =100,b =200, e =300):
print(c)
print(d)
print(e)
test(3)
3
200
300
def test (b =100, a):
print(a)
print(b)
test(1)
複製程式碼
-
引數格式混用
-
函式/方法的形參定義順序(從左向右):a,b,c,x=a,y=2,z=3
-
函式/方法的形參呼叫傳參順序(從左向右):
-
預設引數可以不傳值1,2,3
-
預設引數可以按照順序傳值
-
1,2,3,4(x賦值)
-
1,2,3,4,5(x,y賦值)
-
====1====,2,3,4,5,6(x,y,z賦值)
預設引數應用場景
- 減少函式/方法中大量反覆的固定值得傳參
- 為使用者預留可操作的入口
str.index(str , start, end)
list.pop(index)
複製程式碼
程式碼演示
str1 = "hello python"
#shr1.index("???".0.len(str1))
#這個是預設值
print(str1.index("0",6,12))
list1 = [1,2,3]
#list1.pop(len(list1)-1)
#這個是預設值
print(list1.pop())
複製程式碼
關鍵字引數
關鍵字引數:函式/方法在呼叫時指定參賦值的形參變數名,對應的實參稱為關鍵字引數。
- 關鍵字引數定義格式:
def 函式名(形參,...):
函式體
...
複製程式碼
- 呼叫格式
函式名(形參名 = 實參)
複製程式碼
程式碼演示
def test (a =100,b =200):
print(a)
print(b)
test(b = 1)
#執行結果
100
1
複製程式碼
引數格式混用二
def test (a,b):
print(a)
print(b)
test(b=2,a=1)
複製程式碼
注意: 實參傳值時,關鍵字引數必須出現在位置數後面 函式/方法呼叫時每個引數只能賦值一次,為避免同意變數同時使用位置引數和關鍵字引數賦值,建議不同類別的引數使用固定的策略進行引數賦值。 關鍵字引數主要是解決預設跳躍賦值的問題
關鍵字引數應用場景
- 簡化多預設引數的函式/方法的呼叫複雜度
- 降低多預設引數的函式/方法的呼叫風險
print(value,sep,end,file,flush)
複製程式碼
print("hello",end=" ")
print("itcast",end=" ")
print("python")
#執行結果
hello itcast python
複製程式碼
注意: 關鍵字引數在使用後,直接跳過了某一些預設的引數,後續在使用中,如果設定的方法中有大量的預設引數,而使用的時候期望於改其中一個預設引數的值得時候,哪怕是第一個也建議寫關鍵字引數,避免預設呼叫產生衝突的尷尬。
可變引數
可變引數: 函式/方法在定義時使用一個形參可以接收呼叫時傳入的任意數量的實參,對應的形參稱為可變引數。
-可變引數定義格式:
def 函式名(*形參,...):
函式體
....
複製程式碼
- 呼叫格式:
函式名(實參1,...)
複製程式碼
程式碼演示
def sun(*args):
sums =0
for num in args:
sums += num
print(sums)
sum(1,2,3,4,5)
#執行結果
15
複製程式碼
引數格式混用三
*和位置引數的混用
def test(a,b,*args):
print(a)
print(b)
print(args)
for data in args:
print(data)
test("張三",18,"itcast",True)
#執行結果
張三
18
('itcast',True)
複製程式碼
注: 列印出來的元組全部給了*args
位置引數和可變引數,位置引數一定要在可變引數的前邊,位置引數不要的引數,都給可變引數。
def test (*args,c,d):
print(args)
print(c)
print(d)
test(1,2,3,c=4,d=5)
#執行結果
(1,2,3)
4
5
複製程式碼
注: 在進行定義的時候,關鍵字引數賦值的東西要放在可變引數的後邊.
可變引數工作原理
可變引數是對呼叫時傳入的引數進行自動組包,將使用者傳入的資料以元組的形式儲存並傳遞給函式/方法。 獲取傳入的資料同元組的基本操作。 使用中注意事項: 在同一函式/方法引數定義中,==只能定義一個可變引數==。
- 引數格式混用
- 函式/方法的形參定義順序(從左向右):
- 函式/方法的形參呼叫傳參順序(從左向右):a,*args,x=1
- 函式/方法的呼叫規則:1,2,3,4,5,x=2
- 位置引數根據位置和數量進行賦值
- 可變引數接收位置引數後預設引數前的所有制
- 預設引數如需傳值使用關鍵字引數的形式寫在可變引數傳參的後面
可變引數的應用場景
可變引數應用場景可以完美被元組進行代替
print("a","b","c","d",sep="+")
a+b+c+d
#sep是進行定義引數分割符
複製程式碼
字典引數
字典引數: 函式/方法在定義時使用一個形參可以接收呼叫時傳入的未定義的關鍵引數,對應的形參稱為字典引數。
- 字典引數定義格式:
def 函式名(**形參,...):
函式體
...
複製程式碼
- 呼叫格式:
函式名(未定義變數名 =實參1,......)
複製程式碼
def test(**kwargs):
print(kwargs)
for key in kwargs.keys():
print(key)
print(kwargs[key])
test(a = 1, b = 2)
#執行結果
{'a':1,'b':2}
a
1
b
2
複製程式碼
結論: 沒有定義關鍵字的引數,被函式接收以後可以通過**定義出來的字典引數接收到。
引數格式混用四
def tast(a,*args,m=1,**kwargs):
print(kwargs)
#a(位置引數),*args(可變引數)
,m=1(預設引數),放在**kwargs
(字典引數後邊都會出現報錯的現象。)
複製程式碼
結論: 原始引數最後面加字典引數
def test(m,**kwargs):
print(m)
print(kwargs)
test(x=1,m=1,y=2)
#執行結果
1
{x:1,y:2}
#注: 這種情況m=1可以隨意放置
,**kwargs的取值是test中為明確
定義的剩餘值,m=1,有明確定義傳值給m的。
複製程式碼
- 字典引數使用的注意事項:
在同一個函式/方法定義中,只能存在一個字典引數。
- 引數格式混用
- 函式/方法的形參定義順序(從左向右):
- a,*args,x=1,**kwargs
- 函式/方法的形參呼叫傳參順序(從左向右):
- 1, 2,3,4,5, x=2, m=1,n=2
字典引數應用場景
'''流水線作業一'''
#要求:兩端去空格,小寫轉大寫,按照空格切割字串,輸出字串,同行輸出,間隔使用:
#“hello itcast python" ->HELLO: ITCAST:OYTHIN:
def coderl(str):
#對資料進行處理
str_list = str.split()
renturn str_list
def coder2(str):
#對資料進行處理
#交由下一流水下繼續作業
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str)
#提供資料,指定最終處理策略
ste_list =coder2(" hello itcast python ")
for data in str_list:
print(data, end= ": ")
#執行結果:
HELLO: ITCAST: PYTHON:
複製程式碼
'''流水線作業二'''
def coderl(str):
#對資料進行處理
str_list = str.split()
for data in str_list:
print(data, end= ", ")
def coder2(str):
#對資料進行處理
#交由下一流水下繼續作業
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str)
#提供資料,指定最終處理策略
coder2(" hello itcast python ")
#執行結果:
HELLO, ITCAST, PYTHON,
複製程式碼
'''流水線作業三'''
def coderl(str,end):
#對資料進行處理
str_list = str.split()
for data in str_list:
print(data, end=end)
def coder2(str,end):
#對資料進行處理
#交由下一流水下繼續作業
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str,ebd)
#提供資料,指定最終處理策略
coder2(" hello itcast python "," -")
#使用傳參形式,控制分割格式
#執行結果:
HELLO- ITCAST- PYTHON-
複製程式碼
'''流水線作業四'''
def coderl(str,**kwargs):
#對資料進行處理
str_list = str.split()
for data in str_list:
print(data,**kwargs)
def coder2(str,**kwargs):
#對資料進行處理
#交由下一流水下繼續作業
new_str =str.strip()
new_str = new_str.upper()
return coderl(new_str,**kwargs)
#提供資料,指定最終處理策略
coder2(" hello itcast python ",end="%")
#使用字典引數
#執行結果:
HELLO%ITCAST%PYTHON%
複製程式碼
- 字典引數應用場景
- 函式/方法多層級呼叫間的關鍵字引數傳遞
- 通過設計可避免字典引數的使用
def call_depth_4(d =10,**kwargs):#d留
print("call_depth_4,d =%d" % d)
def call_depth_3(c =10,**kwargs):#c留,d使用字典引數向後傳遞
print("call_depth_3,d =%d" % d)
call_depth_4(**kwargs)
def call_depth_2(b =10,**kwargs):#b留,cd使用字典引數向後傳遞
print("call_depth_3,d =%d" % d)
call_depth_3(**kwargs)
def call_depth_1(a =10,**kwargs):#a留,bcd使用字典引數向後傳遞
print("call_depth_1,d =%d" % d)
call_depth_2(**kwargs)
call_pedth_1(a=1,b=1,c=1,d=1)
#執行結果
call_depth_1,a = 1
call_depth_2,b = 1
call_depth_3,c = 1
call_depth_4,d = 1
複製程式碼
字典引數形參操作
def test(**kwargs):
print(kwargs)
#**kwargs 將收到的關鍵字引數按照引數傳遞的格式交給函式
# {"a":1,"b":2,"c":3}->a = 1,b = 2,c = 3
#*kwargs對傳遞過來的所有字典引數中鍵key進行顯示操作
print(*kwargs)
#這個是*實際起到的作用是拆包
test(a = 1,b = 2,c = 3)
#執行結果
{'a':1.'b':2,'c':3}
a b c
複製程式碼
- 字典引數資料讀取
- 獲取字典引數中被包裝的字典物件
- 形參名 (字典)
- 獲取字典引數中被包裝的所有未知關鍵字引數名
- *形參名 (實參格式)
- *容器變數名 (拆包成函式呼叫的引數)
- 解包字典引數中的資料為關鍵字引數
- **形參名 (實參格式)
拆包: 所有的資料儲存容器均支援拆包,拆包後的資料可以用於儲存到對應的變數中,也可以用於作為函式/方法呼叫的實參。
遞迴函式
遞迴函式 是在當前函式體內出現了對自身函式的呼叫。
- 遞迴函式製作要點
- 要出現自身呼叫自身的現象
- 要具有明確的結束標誌
# 求1到指定數字的和(100)
def sum(num):
#設定結束標誌
if num == 1:
retur
return sum(num-1)+num
print(sum(100))
#執行結果
5050
複製程式碼
注: 函式呼叫的==最大層級是1000次==,遞迴操作很容易突破該層級,使用時要注意。主程式自身佔一層,所以在999時就報錯了。
匿名函式
def add(a , b):
retun a+b
add = lambda a , b : a + b
#等同上述格式
複製程式碼
- 匿名函式定義格式:
- 函式名 = lambda 形參 : 返回值
- 匿名函式呼叫格式:
- 結果 = 函式名(實參)
add = lambda a , b : a + b
c = add(3,4)
print(c)
#執行結果
7
複製程式碼
result = (lambda a , b : a + b )( 3 , 4 )
複製程式碼
- 匿名函式定義並呼叫格式:
- 結果 = (lambda 形參 : 返回值)(實參)
c = (lambda a , b : a + b )( 3 , 4 )
print (c)
#執行結果
7
複製程式碼
匿名函式注意事項
#1.無引數
f1 =(lambda : 100)()
print(f1)
#執行結果
100
#2多返回值
f2,f3 =(lambda : 3 , 4)()
print(f2)
print(f3)
#不可執行
#3無返回值
x =(lambda : print("hello itcast"))()
print(x)
#執行結果
hello itcast
None
#不成立
#4.資料儲存模型
f4 = (lambda :[a**2 for a in range(5) if a % 2 == 0])()
print(f4)
#執行結果
[0,4,16]
複製程式碼
注意事項:
- 匿名函式可以無引數
- 匿名函式不存在無返回值的結果(None)
- 匿名函式僅能返回單一值,不支援自動組包
- 可以通過返回資料儲存模型代替多值
- 資料儲存模型支援推導式
引用
- 引用 就是變數指想資料儲存空間的現象。
- 相同資料使用同一個空間儲存,節約記憶體佔用
- 使用==id==(==資料==)操作獲取資料儲存的記憶體空間引用地址
引用---數字
a=1
b=1
print(id(1))
print(id(a))
print(id(b))
print(id(2))
a=2
print(id(a))
#執行結果
1777757200
1777757200
1777757200
1777757232
1777757232
flag1 =True
flag2 = False
print(id(flag1))
print(id(flag2))
flag1=False
print("--------------")
print(id(flag1))
print(id(flag2))
#執行結果
1777266912
1777266944
-------------
1777266944
1777266944
str1 = "a"
str2 = "a"
print(id(str1))
print(id(str2))
str1 = "b"
print(id(str1))
print(id(str2))
#執行結果
2093786795904
2093786795904
2215596460272
2215596461952
複製程式碼
函式引數型別
- 函式的形參如果接收到的實參是不可變型別,函式的內部操作,不會對外部的實參產生影響。
- 函式的形參吐過接收到的實參是可變型別,函式內部的操作,會對外部的實參產生影響。
def test(a):#a->list1->@兩個資料對應的地址 最終a->@兩個資料對應的地址
a.append("itcast")#a對地址中的資料進行了操作 a->變化?沒有->@兩個資料對應的地址
list1 = ["hello"."python"]#list1->@兩個資料對應的地址
print(list1)
print("---------------")
test(list1)
print(list1)#輸出list1,輸出list1的指向->@兩個資料對應的地址
#執行結果
['hello','python']
------------
['hello','python','itcast']
複製程式碼
形參使用預設引數
- 函式的形參如果設定了預設引數,且預設引數為可變型別,在呼叫時,如果不傳遞引數值,使用預設引數,則預設引數使用同一個引用地址的資料,不會進行二次初始化。
- 對預設引數的值儘量不要使用可變型別的資料