第九課
函數(shù)
- 函數(shù)簡(jiǎn)介
? 函數(shù)也是一個(gè)對(duì)象
? 函數(shù)用來(lái)保存一些可執(zhí)行的代碼,并且可以在需要時(shí),對(duì)這些語(yǔ)句進(jìn)行多次調(diào)用
語(yǔ)法
def 函數(shù)名([形參1,形參2,形參3....]):
代碼塊
注意:
函數(shù)名必須符合標(biāo)識(shí)符的規(guī)范(可以包含字母、數(shù)字、下劃線但是不能以數(shù)字開(kāi)頭)
print是函數(shù)對(duì)象 print()是調(diào)用函數(shù) - 函數(shù)的參數(shù)
2.1 形參和實(shí)參
? 形參(形式參數(shù)) 定義形參就相當(dāng)于在函數(shù)內(nèi)部聲明了變量,但是并不是賦值
? 實(shí)參(實(shí)際參數(shù))指定了形參,那么在調(diào)用函數(shù)時(shí)必須傳遞實(shí)參,實(shí)參將會(huì)賦值給對(duì)應(yīng)的形參,簡(jiǎn)單來(lái)說(shuō)有幾個(gè)形參就要有幾個(gè)實(shí)參
2.2 函數(shù)的傳遞方式
? 定義形參時(shí),可以為形參指定默認(rèn)值。指定了默認(rèn)值以后,如果用戶傳遞了參數(shù)則默認(rèn)值不會(huì)生效。如果用戶沒(méi)有傳遞,則默認(rèn)值就會(huì)生效
? 位置參數(shù):位置參數(shù)就是將對(duì)應(yīng)位置的實(shí)參賦值給對(duì)應(yīng)位置的形參
? 關(guān)鍵字參數(shù) : 關(guān)鍵字參數(shù)可以不按照形參定義的順序去傳遞,而根據(jù)參數(shù)名進(jìn)行傳遞
def fn()
? 混合使用位置參數(shù)和關(guān)鍵字參數(shù)的時(shí)候必須將位置參數(shù)寫到關(guān)鍵字參數(shù)前面去
- 不定長(zhǎng)參數(shù)
? 定義函數(shù)時(shí),可以在形參前面加一個(gè),這樣這個(gè)形參可以獲取到所有的實(shí)參,它會(huì)將所有的實(shí)參保存到一個(gè)元組中
? 帶號(hào)的形參只能有一個(gè),可以和其他參數(shù)配合使用
? *形參只能接受位置參數(shù),不能接受關(guān)鍵字參數(shù)
? **形參可以接收其他的關(guān)鍵字參數(shù),它會(huì)將這些參數(shù)統(tǒng)一保存到字典當(dāng)中。字典的key就是參數(shù)的名字,字典的value就是參數(shù)的值
? **形參只有一個(gè),并且必須寫在所有參數(shù)的后面
# def fn(*args, **kwargs):
# import requests
# requests.get()
- 參數(shù)的解包
? 傳遞實(shí)參時(shí),也可以在序列類型的參數(shù)前添加星號(hào),這樣它會(huì)自動(dòng)的將序列中元素依次作為參數(shù)傳遞
? 要求序列中的元素的個(gè)數(shù)必須和形參的個(gè)數(shù)一致
def fn(a, b, c):
print(a)
print(b)
print(c)
t = (1, 2, 3)
fn(*t)
>>>
1
2
3
********************************************************************************************************
def fn(a, b, c):
print(a)
print(b)
print(c)
d = {'a':1, 'b':2, 'c':3}
fn(**d)
>>>
1
2
3
5.函數(shù)的返回值
def fn(*b):
r = 0
for n in b:
r += n
def fn2():
print("hello")
return 1
return fn2()/###return fn2
s = fn()
print(s)### print(s())
>>>
hello
1
6.文檔字符串
? help()是Python中內(nèi)置函數(shù),通過(guò)help()函數(shù)可以查詢Python中函數(shù)的用法
? 在定義函數(shù)時(shí),可以在函數(shù)內(nèi)部編寫文檔字符串,文檔字符串就是對(duì)函數(shù)的說(shuō)明
7. 函數(shù)的作用域
? 作用域(scope)
? 作用域指的是變量生效的區(qū)域
? 在Python中一共有兩種作用域
? 全局作用域
? 全局作用域在程序執(zhí)行時(shí)創(chuàng)建,在程序執(zhí)行結(jié)束時(shí)銷毀
? 所有函數(shù)以外的區(qū)域都是全局作用域
? 在全局作用域中定義的變量,都是全局變量,全局變量可以在程序的任意位置進(jìn)行訪問(wèn)
? 函數(shù)作用域
? 函數(shù)作用域在函數(shù)調(diào)用時(shí)創(chuàng)建,在調(diào)用結(jié)束時(shí)銷毀
? 函數(shù)每調(diào)用一次就會(huì)產(chǎn)生一個(gè)新的函數(shù)作用域
? 在函數(shù)作用域中定義的變量,都是局部變量,它只能在函數(shù)內(nèi)部被訪問(wèn)
b = 456
def fn():
global a
a = 123
def fn2():
print('函數(shù)內(nèi)部fn2:a=', a)
print('函數(shù)內(nèi)部fn2:b=', b)
print('函數(shù)內(nèi)部fn2:a=', a)
print('函數(shù)內(nèi)部fn2:b=', b)
return fn2()
fn()
>>>
函數(shù)內(nèi)部fn2:a= 123
函數(shù)內(nèi)部fn2:b= 456
函數(shù)內(nèi)部fn2:a= 123
函數(shù)內(nèi)部fn2:b= 456
函數(shù)外部fn2:a= 123
函數(shù)外部fn2:b= 456
8. 命名空間
? 命名空間實(shí)際上就是一個(gè)字典,是一個(gè)專門用來(lái)存儲(chǔ)變量的字典
? locals()用來(lái)獲取當(dāng)前作用域的命名空間
? 如果在全局作用域中調(diào)用locals()則獲取全局命名空間,如果在函數(shù)作用域中調(diào)用locals()則獲取函數(shù)命名空間
def fn():
a = 123
b = 456
c = 789
scope = locals()
print(scope)
fn()
>>>
{'c': 789, 'b': 456, 'a': 123}
? 返回值是一個(gè)字典
9. 遞歸函數(shù)
? 遞歸是解決問(wèn)題的一種方式,它的整體思想,是將一個(gè)大問(wèn)題分解為一個(gè)個(gè)的小問(wèn)題,直到問(wèn)題無(wú)法分解時(shí),在去解決問(wèn)題
? 遞歸式函數(shù)有2個(gè)條件
? 1. 基線條件 問(wèn)題可以被分解為最小問(wèn)題,當(dāng)滿足基線條件時(shí),遞歸就不執(zhí)行了
? 2. 遞歸條件 可以將問(wèn)題繼續(xù)分解的條件
漢諾塔游戲
現(xiàn)在有ABC三根柱子。要求:將A柱所有的圓盤放到C柱。在移動(dòng)的過(guò)程中可以借助B柱。并且規(guī)定大圓盤不能放小圓盤上面,每次只能移動(dòng)一個(gè)盤子。用遞歸的方式來(lái)解決漢諾塔問(wèn)題
1,如果有一個(gè)盤: A>C
2,如果盤數(shù)≥2,我們總可以把他們看成是2個(gè)盤,最下面的一個(gè)和最上面的一個(gè)(多個(gè))
3,把最上面的一個(gè)(多個(gè)) A>B
4,把下面的盤子A>C
5,把B上面的一個(gè)或者多個(gè)B>C
def hannuota(n, a, b, c):
if n == 1:
print('第一個(gè)盤從',a,">",c)
else:
hannuota(n-1, a, c, b)
print('第', n, '個(gè)盤子從', a, '>', c)
hannuota(n-1, b, a, c)
hannuota(3, "a", "b", "c")
>>>
第一個(gè)盤從 a > c
第 2 個(gè)盤子從 a > b
第一個(gè)盤從 c > b
第 3 個(gè)盤子從 a > c
第一個(gè)盤從 b > a
第 2 個(gè)盤子從 b > c
第一個(gè)盤從 a > c