當(dāng)當(dāng)網(wǎng)網(wǎng)站系統(tǒng)建設(shè)的意義搜索引擎優(yōu)化方法包括
前言
上篇文章 python學(xué)習(xí)——【第七彈】學(xué)習(xí)了python中的可變序列集合,自此python中的序列的學(xué)習(xí)就完成啦,這篇文章開始學(xué)習(xí)python中的函數(shù)
。
函數(shù)
在學(xué)習(xí)其他編程語言的時(shí)候我們就了解過函數(shù):函數(shù)就是執(zhí)行特定任何以完成特定功能的一段代碼
那么我們?yōu)槭裁匆褂煤瘮?shù)呢?
復(fù)用代碼
隱藏實(shí)現(xiàn)細(xì)節(jié)
提高可維護(hù)性
提高可讀性便于調(diào)試
函數(shù)的創(chuàng)建
python中函數(shù)的創(chuàng)建方式:
def 函數(shù)名 ([輸入?yún)?shù)]):
函數(shù)體
[return xxx]
形參:形參出現(xiàn)在函數(shù)的定義處
實(shí)參:實(shí)際參數(shù)的值,位置出現(xiàn)在函數(shù)的調(diào)用處
函數(shù)的調(diào)用
在學(xué)習(xí)其他的語言時(shí)我們知道,函數(shù)只有在調(diào)用的時(shí)候才能執(zhí)行,python中的函數(shù)也是一樣的。調(diào)用函數(shù)的方式也很簡單:
[返回值] = 函數(shù)名([參數(shù)])
如果函數(shù)沒有參數(shù),則括號(hào)中可以留空
def pri():print('helloworld')
pri()#調(diào)用函數(shù)
那么在調(diào)用函數(shù)時(shí),對(duì)調(diào)用的參數(shù)有什么要求呢?
函數(shù)調(diào)用的參數(shù)傳遞
位置實(shí)參:根據(jù)形參對(duì)應(yīng)的位置進(jìn)行實(shí)參傳遞
def add(a,b):num=a+breturn num
result=add(10,20)
print(result) #30
關(guān)鍵字實(shí)參:根據(jù)形參名稱進(jìn)行實(shí)參傳遞
def add(a,b):num=a+breturn num
result=add(b=10,a=20)
print(result) #30
需要注意的是,創(chuàng)建函數(shù)有多少個(gè)形參,那么調(diào)用時(shí)就需要傳入多少個(gè)值,且順序必須和創(chuàng)建函數(shù)時(shí)一致。即便該函數(shù)沒有參數(shù),函數(shù)名后的小括號(hào)也不能省略。
函數(shù)參數(shù)的定義
函數(shù)定義時(shí),給形參設(shè)置默認(rèn)值,只有與默認(rèn)值不符的時(shí)候才需要傳遞實(shí)參
def fun1(a,b=10):print(a,b)
# 函數(shù)調(diào)用
fun1(100) #100 10
fun1(20,30) #20 30 與默認(rèn)形參值不相符,傳遞實(shí)參值
個(gè)數(shù)可變的位置形參
1:定義函數(shù)時(shí),可能無法事先確定傳遞的位置的實(shí)參的個(gè)數(shù),可以使用
可變的位置參數(shù)
2:使用 * 定義個(gè)數(shù)可變的位置形參
3:結(jié)果為元組類型
4:如果沒有需傳遞的位置實(shí)參,但是使用了可變的位置參數(shù),這時(shí)再調(diào)用該函數(shù),會(huì)返回一個(gè)空元組 即args=()
def fun1(*args):print(args,type(args))
fun1(10)
fun1(10,20)
fun1(10,20,30)
'''
(10,) <class 'tuple'>
(10, 20) <class 'tuple'>
(10, 20, 30) <class 'tuple'>
'''
def fun11(x,y,*args): #已知形參(x,y)要放在位置形參之前;否則會(huì)報(bào) SyntaxError: invalid syntax 無效語法錯(cuò)誤print('x=',x)print('y=',y)print('args=',args)
fun11(11,22,33,44,55)'''
x= 11
y= 22
args= (33, 44, 55)
'''
注意:使用個(gè)數(shù)可變的位置參數(shù)時(shí),可變的位置參數(shù)只能是1個(gè)
個(gè)數(shù)可變的關(guān)鍵字形參
1:定義函數(shù)時(shí),無法事先確定確定傳遞的關(guān)鍵字實(shí)參的個(gè)數(shù)時(shí),使用
可變的關(guān)鍵字形參
2:使用 ** 定義個(gè)數(shù)可變的關(guān)鍵字形參
3:結(jié)果是一個(gè)
字典
4:如果沒有需要傳遞的關(guān)鍵字實(shí)參,但是使用了可變的關(guān)鍵字參數(shù),這時(shí)再調(diào)用該函數(shù),會(huì)返回一個(gè)空字典 即args={}
def fun2(**args):print(args,type(args))
fun2(a=10)
fun2(a=10,b=20,c=30)
'''
{'a': 10} <class 'dict'>
{'a': 10, 'b': 20, 'c': 30} <class 'dict'>
'''def fun22(x,y,**args): #已知形參(x,y)要放在關(guān)鍵字形參之前;并且位置實(shí)參的個(gè)數(shù)要和位置形參的個(gè)數(shù)保持一致,否則會(huì)報(bào):TypeError: fun22() takes ... positional arguments but ... were given 實(shí)參數(shù)與形參數(shù)不符print('x=',x)print('y=',y)print('args=',args)
fun22(11,22,c=10,d=0)
'''
{'a': 10}
{'a': 10, 'b': 20, 'c': 30}
'''
注意:使用個(gè)數(shù)可變的關(guān)鍵字形參時(shí),可變的關(guān)鍵字形參只能是1個(gè)
def fun6(**args,**args):pass
# 程序報(bào)錯(cuò) SyntaxError: invalid syntax 無效語法
定義函數(shù)的過程中,既有個(gè)數(shù)可變的關(guān)鍵字形參,也有個(gè)數(shù)可變的位置形參,要求個(gè)數(shù)可變的位置形參放在個(gè)數(shù)可變的關(guān)鍵字形參之前。
def fun(x, y, *args, **argss):print("x=", x)print("y=", y)print("args=", args)print("argss=", argss)
fun(1, 2, 3, 4, e=5, f=6, g=7)
'''
x= 1
y= 2
args= (3, 4)
argss= {'e': 5, 'f': 6, 'g': 7}
'''
# 可變位置參數(shù)和可變關(guān)鍵字參數(shù)需要傳遞的實(shí)參數(shù)不相匹配時(shí),如果可變位置參數(shù)或可變關(guān)鍵字參數(shù)沒有收到需要傳遞的實(shí)參的值的話,調(diào)用函數(shù)時(shí)分別返回空元組和空字典。
def fun(x, y, *args, **argss):print("x=", x)print("y=", y)print("args=", args)print("argss=", argss)
fun(3, 4)
'''
x= 3
y= 4
args= ()
argss= {}
'''
函數(shù)參數(shù)的傳遞
位置參數(shù)的傳遞
def funs(a,b,c):print('a=',a)print('b=',b)print('c=',c)
funs(10,20,30)
lst=[11,22,33]
funs(*lst)# 使用位置參數(shù)傳遞,在函數(shù)調(diào)用時(shí),將列表中的每個(gè)元素都轉(zhuǎn)換為位置參數(shù)傳入
'''
a= 10
b= 20
c= 30
a= 11
b= 22
c= 33
'''
關(guān)鍵字參數(shù)的傳遞
# 關(guān)鍵字參數(shù)傳遞
funs(a=111,b=222,c=333)
dic={'a':444,'b':555,'c':666}
funs(**dic)# 使用關(guān)鍵字參數(shù)傳遞,在函數(shù)調(diào)用時(shí),將字典中的每個(gè)元素的鍵值對(duì)都轉(zhuǎn)換為關(guān)鍵字參數(shù)傳入
'''
a= 111
b= 222
c= 333
a= 444
b= 555
c= 666
'''
在 * 之后的參數(shù),在函數(shù)調(diào)用時(shí),只能采用關(guān)鍵字參數(shù)進(jìn)行傳遞
def funcs(a,b,*,c,d):print('a=',a)print('b=',b)print('c=',c)print('d=',d)
funcs(10,20,c=30,d=40)
'''
a= 10
b= 20
c= 30
d= 40
'''
函數(shù)傳遞時(shí)形參的位置問題
函數(shù)的參數(shù)總結(jié)
1 :將序列中的每個(gè)元素都轉(zhuǎn)換為位置實(shí)參
使用*2 :將字典中的每個(gè)鍵值對(duì)都轉(zhuǎn)換為
關(guān)鍵字實(shí)參
使用 **3 :
關(guān)鍵字形參 使用*
4 :
個(gè)數(shù)可變的位置形參 使用*
5 :
個(gè)數(shù)可變的關(guān)鍵字形參 使用**
函數(shù)調(diào)用參數(shù)傳遞內(nèi)存分析
def fun(num1,num2):print('num1=',num1,id(num1)) #num1= 90 140471326216032print('num2=',num2,id(num2)) #num2= [11, 22, 33, 44] 140471317443120num1=111num2.append(999)print('num1=',num1,id(num1)) #num1= 111 140471326216704print('num2=',num2,id(num2)) #num2= [11, 22, 33, 44, 999] 140471317443120
print('---------調(diào)用函數(shù)之前---------')
add1=90
add2=[11,22,33,44]
print(add1,id(add1)) #90 140471326216032
print(add2,id(add2)) #[11, 22, 33, 44] 140471317443120
print('-------------調(diào)用函數(shù)----------')
fun(add1,add2)
'''
num1= 90 140471326216032
num2= [11, 22, 33, 44] 140471317443120
num1= 111 140471326216704
num2= [11, 22, 33, 44, 999] 140471317443120
'''
print('-----------調(diào)用函數(shù)后----------')
print(add1,id(add1)) #90 140471326216032
print(add2,id(add2)) #[11, 22, 33, 44, 999] 140471317443120
可以發(fā)現(xiàn):在函數(shù)調(diào)用過程中,若要進(jìn)行參數(shù)傳遞:
如果是
可變對(duì)象(如列表、集合、字典)
,在函數(shù)體內(nèi)對(duì)其進(jìn)行修改會(huì)影響
到函數(shù)體外的這個(gè)可變對(duì)象的值(因?yàn)榭勺儗?duì)象在內(nèi)存中是可變的,可以被修改),其id地址不會(huì)發(fā)生改變
;如果是
不可變對(duì)象(如數(shù)值、字符串、元組)
,在函數(shù)體內(nèi)對(duì)其進(jìn)行修改不會(huì)影響
到函數(shù)體外這個(gè)不可變對(duì)象的值(因?yàn)椴豢勺儗?duì)象在內(nèi)存中是固定的,無法被修改),其id地址不會(huì)發(fā)生改變
。
函數(shù)返回值
1:當(dāng)函數(shù)不需要返回值時(shí),函數(shù)體內(nèi)可以省略return;并且?函數(shù)執(zhí)行完畢后,不需要給調(diào)用處提供數(shù)據(jù)
def pri():print('helloworld')
pri()
2:當(dāng)函數(shù)只有一個(gè)返回值時(shí),返回值類型就是原類型
def fun2():return 'hello'
res=fun2()
print(res,type(res)) #hello <class 'str'>
3:當(dāng)函數(shù)有多個(gè)返回值時(shí),返回值類型是一個(gè)元組
def fun(num):odd=[]even=[]for i in num:if i%2==0:odd.append(i)else:even.append(i)return odd,even
list1=[11,22,32,23,45,6,0]
print(fun(list1),type(fun(list1)))
# ([22, 32, 6, 0], [11, 23, 45]) <class 'tuple'>
變量的作用域
程序代碼能訪問該變量的區(qū)域 稱作變量的作用域
根據(jù)變量的有效范圍可分為:
局部變量
在函數(shù)體內(nèi)定義并使用的變量,只在函數(shù)內(nèi)部有效,局部變量使用global
聲明 , 這個(gè)變量就會(huì)成為全局變量
def func1(a,b):c=a+b #c 就成為局部變量 因?yàn)閏是在函數(shù)體內(nèi)進(jìn)行定義的變量 a,b是函數(shù)的形參 作用范圍也是函數(shù)內(nèi)部 相當(dāng)于局部變量return c
print(func1(1,2))#3
# 使用global 聲明局部變量,a b為全局變量,在函數(shù)體內(nèi)可以直接被調(diào)用;c在函數(shù)體內(nèi)定義,屬于局部變量,因此需要用global聲明才能在函數(shù)體外被調(diào)用
a=1
b=2
def func3():global cc=a-breturn c
print(func3()) #-1
全局變量
函數(shù)體外定義的變量 ,可作用于函數(shù)體內(nèi)
# 全局變量 a=1,b=2為定義在函數(shù)體外的變量,屬于全局變量,在函數(shù)體內(nèi)與函數(shù)體外均可調(diào)用
a=1
b=2
def func2():c=a+breturn c
print(func2()) #3
遞歸函數(shù)
什么是遞歸函數(shù)
: 如果在一個(gè)函數(shù)的函數(shù)體內(nèi)調(diào)用了該函數(shù)本身, 這個(gè)函數(shù)就稱作遞歸函數(shù)
遞歸的組成部分
: 遞歸調(diào)用與遞歸終止條件
遞歸的調(diào)用過程
: 每遞歸調(diào)用一次函數(shù) ,都會(huì)在棧內(nèi)存分配一個(gè)棧幀(每次調(diào)用函數(shù)時(shí),在內(nèi)存中都會(huì)單獨(dú)開辟一個(gè)空間,配合函數(shù)運(yùn)行,這個(gè)空間叫做棧幀空間。)每執(zhí)行完一次函數(shù), 都會(huì)釋放相應(yīng)的空間
遞歸的思想
:
遞歸是一去一回的過程,調(diào)用函數(shù)時(shí),會(huì)開辟棧幀空間,函數(shù)執(zhí)行結(jié)束之后,會(huì)釋放棧幀空間,遞歸實(shí)際上就是不停地開辟和釋放棧幀空間的過程,每次開辟棧幀空間,都是獨(dú)立的一份,其中的資源不共享。
遞歸其實(shí)利用的時(shí)是壓棧的思想,我們看一下下面這個(gè)例子:
壓棧思想:
遞歸的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
遞歸函數(shù)使代碼看起來干凈整潔。 使用遞歸可以將復(fù)雜的任務(wù)分解為更簡單的子問題。 與使用嵌套嵌套相比,使用遞歸更容易生成序列。
缺點(diǎn):
有些情況,遞歸背后的邏輯很難遵循。 遞歸調(diào)用很昂貴(效率低),因?yàn)樗鼈冋加么罅績?nèi)存和時(shí)間。 遞歸函數(shù)調(diào)試較為復(fù)雜。
遞歸函數(shù)的應(yīng)用
利用遞歸函數(shù)計(jì)算階乘
def func1(n):if n == 1:return 1else:return n*func1(n-1)
print(func1(6)) #720
利用遞歸函數(shù)計(jì)算? ?斐波那契數(shù)列??
斐波那契數(shù)列:1、1、2、3、5、8、13、21、34。。。
F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
計(jì)算第n位的斐波那契數(shù)是多少
def func2(n):if n == 1:return 1elif n == 2:return 1else:res=func2(n-1)+func2(n-2)return res
print(func2(6)) #8
打印出整個(gè)斐波那契數(shù)列
for i in range(1,7):print(func2(i),end=' ')
print('\n')#1 1 2 3 5 8
鍵盤錄入一個(gè)整數(shù),然后根據(jù)這個(gè)正整數(shù)打印出斐波那契數(shù)列以及其數(shù)列和
num=int(input('請(qǐng)輸入一個(gè)正整數(shù):'))
def func3(num):if num==1:return 1elif num==2:return 1else:result=func3(num-1)+func3(num-2)return result
nums=[]
sums=0
for n in range(1,num+1):# print(func3(n),end=' ')nums.append(func3(n))sums+=func3(n)
print('產(chǎn)生的斐波那契數(shù)列是:',nums)
print('\n第',num,'位的斐波那契數(shù)為:',func3(num))
print('\n斐波那契數(shù)列之和為:',sums)
每篇一語
努力的人運(yùn)氣都不會(huì)太差!
如有不足,感謝指正!