python其他知識目錄
1、函數介紹
函數是組織好的,可重複使用的,用來實作單一,或相關聯功能的代碼段。
函數能提高應用的子產品性,和代碼的重複使用率。你已經知道Python提供了許多内建函數,比如print()
。但你也可以自己建立函數,這被叫做使用者自定義函數。
def 函數名(參數清單):
函數體d
函數名(參數)
函數名(參數)
2、函數使用優缺點:
公司随随便便幾百上千行。可讀性,重用性,函數,面向過程程式設計
優點:
缺點:
面向過程,可以将可重複性的代碼做成一個函數,用參數代替變化的量,實作具有重複性操作的功能。
當事物需要做這個操作的時候,調用函數即可實作功能。#自己了解
#發郵件:設定裡面開啟pop3,smtp伺服器 ,往smtp伺服器發郵件
比如發郵件,很多對象都使用的一個動作,寫成函數,調用函數。避免代碼備援。
什麼情況寫函數,就是為了能重複使用某個功能,就寫成函數,一個功能一個函數。或者是為了友善閱讀,增加代碼可讀性
函數式程式設計是做什麼的?避免重複性代碼。代碼拆分,增強可移植性,可讀性
本質:将N行代碼拿到别處并給他起個名字,以後通過名字就可以找到這段代碼并執行。
場景:代碼重複執行。
代碼量特别多超過一屏,可以選擇通過函數進行代碼的分割。
3、函數定義:
你可以定義一個由自己想要功能的函數,以下是簡單的規則:
函數代碼塊以 def 關鍵詞開頭,後接函數辨別符名稱和圓括号 ()。
任何傳入參數和自變量必須放在圓括号中間,圓括号之間可以用于定義參數。
函數的第一行語句可以選擇性地使用文檔字元串—用于存放函數說明。
函數内容以冒号起始,并且縮進。
return [表達式] 結束函數,選擇性地傳回一個值給調用方。不帶表達式的return相當于傳回 None
。
文法:
Python 定義函數使用 def 關鍵字,一般格式如下:
def 函數名(參數清單):
函數體
預設情況下,參數值和參數名稱是按函數聲明中定義的順序比對起來的。
函數執行:
def xiaoma():
print("魔降風雲變")
xiaoma()
---------結果:
魔降風雲變
4、函數調用
定義一個函數:給了函數一個名稱,指定了函數裡包含的參數,和代碼塊結構。
這個函數的基本結構完成以後,你可以通過另一個函數調用執行,也可以直接從 Python 指令提示符執
行。
函數不調用,内部代碼不執行。調用後用不用變量接收傳回值,函數都會執行。
def xiaoma():
print("魔降風雲變")
xiaoma()
---------結果:
魔降風雲變
def xiaoma():
print("魔降風雲變")
a=xiaoma()
----------結果:
魔降風雲變
def xiaoma():
print("魔降風雲變")
def mcw(): #函數調用函數
print("我是:")
xiaoma()
mcw()
--------------結果:
我是:
魔降風雲變
5、函數傳參
5.1、函數傳參簡介
不同的對象做相同的操作,可以定義函數。如果每個對象還有些差別,那麼有差別的地方使用函數傳參
定義帶參數的函數的時候
函數式程式設計。通過傳參,傳回不同的值,傳回不同的參數。同一個功能不同的地方就使用傳參
形式參數(形參):形參就是形式上的參數,可以了解為數學的X,沒有實際的值,通過别人指派後才有
意義。相當于變量。
實際參數(實參):實參就是實際意義上的參數,是一個實際存在的參數,可以是字元串或是數字等
函數裡面使用字元串格式化
函數可以定死了,也可以傳遞變量。寫函數不一定需要參數。如果有變的,使用參數,沒有變的就定死
了就可以,看實際情況了。
def eat(arg1,arg2):
print("%s喜歡吃%s"%(arg1,arg2))
eat("小馬過河","米飯")
eat("小明","面條")
-----------結果:
小馬過河喜歡吃米飯
小明喜歡吃面條
5.1沒有函數傳參
案例1:
使用函數隻計算某一個清單内元素的和:
def list_sum():
li = [1, 2, 3]
sum=0
for i in li:
sum+=i
print(sum)
list_sum()
-----------結果
6
5.2一個函數傳參:
案例2:
使用函數計算指定清單内元素的和:
def list_sum(li):
sum=0
for i in li:
sum+=i
print(sum)
info=[1,2,3]
list_sum(info)
-------------結果:
6
報錯問題1:
報錯:函數沒有形參,調用函數時帶着參數的報錯:
def list_sum():
sum=0
for i in li:
sum+=i
print(sum)
info=[1,2,3]
list_sum(info) #調用時,可以直接做參數,也可以用變量做實參
-------------------結果:
list_sum(info)
TypeError: list_sum() takes 0 positional arguments but 1 was given
5.3多個函數傳參:
def xiaoma(arg1,arg2):
print(arg1+arg2)
xiaoma(2,3)
-----------結果:
5
報錯問題2:傳參傳少了
def xiaoma(arg1,arg2):
print(arg1+arg2)
xiaoma(2)
-----------結果:
xiaoma(2)
TypeError: xiaoma() missing 1 required positional argument: 'arg2'
報錯問題3:傳參傳多了
def xiaoma(arg1,arg2):
print(arg1+arg2)
xiaoma(2,3,4)
------------結果:
xiaoma(2,3,4)
TypeError: xiaoma() takes 2 positional arguments but 3 were given
嚴格按照順序來傳參數,按位置一一對應。
5.2基本參數知識
- 任意個數
- 任意類型
def func(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8):
print(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
func(1,False,None,"mcw",["xiaoma","1"],(1,2),{"name":"xiaoma"},{3,4})
------結果:
1 False None mcw ['xiaoma', '1'] (1, 2) {'name': 'xiaoma'} {3, 4}
5.3、位置傳參(調用函數并傳入參數)【執行】
位置傳參:根據位置意義對應傳遞參數
def func(a1, a2):
print(a1, a2)
func(1, 3)
------------結果:
1 3
5.4關鍵字傳參【執行】
關鍵字傳參:指定形參接收實參
def func(a1, a2, a3):
print(a1, a2, a3)
func(1,2,a3=9)
func(1,a2=2,a3=9)
func(a1=1,a2=2,a3=9)
------------------結果:
1 2 9
1 2 9
1 2 9
def func(a1, a2, a3):
print(a1, a2, a3)
func(a1=1,2,3) # 錯誤
-------------結果:
SyntaxError: positional argument follows keyword argument
follows關鍵字定位論點論據
5.5預設參數【定義】
使用場景:定義函數預設參數,友善
指定形參等于什麼參數,如果沒有接收到實參,那麼函數就使用預設參數
def func(a1,a2,a3=9,a4=10): #a3預設9,a4預設10,調用時可以傳可以不傳。;給預設傳參傳了參數就用傳進函數的參數,否則用的預設參數。比如open函數有預設的參數。
print(a1,a2,a3,a4)
func(11,22)
func(11,22,10)
func(11,22,10,100)
func(11,22,10,a4=100)
func(11,22,a3=10,a4=100)
func(11,a2=22,a3=10,a4=100)
func(a1=11,a2=22,a3=10,a4=100)
-------------------結果:
11 22 9 10
11 22 10 10
11 22 10 100
11 22 10 100
11 22 10 100
11 22 10 100
11 22 10 100
5.6萬能參數(打散)
*args:傳遞多個實參給形參*args,并讓函數以元組的形式來接收外部傳參
- 實參前面加*号,将實參内的每個元素傳到*args元組中,而非實參本身。
*kwargs:傳遞多個鍵值對或字典給*kwargs,并且在函數内以字典的形式存在
- 實參字典前面加**給*kwargs,會将實參内每個鍵值對添加到*kwargs字典中,而非實參字典本身
- *args
- 可以接受任意個數的位置參數,并将參數轉換成元組。
- *args隻能接收n個參數。傳入多個實參時,都放到args這個元組裡面。如果傳入元組參數,那麼元組作為args的單個元素。如果*(),實參元組前面有*,那麼實參元組内的每個元素都放到形參構成的元組内,即形參
- 構成的元組内是實參内的各個元素。隻能位置傳參,不能關鍵字傳參#假設可以關鍵字傳參,那麼設定之後,它後面就接收不了參數
- 了,是以不可以做關鍵字傳參
- 使用場景:不确定需要傳參個數的時候使用萬能參數。
- 調用函數無 *
def func(*args): print(args) #*args隻能接收n個參數。傳入多個實參時,都放到args這個元組裡面。 func(1,2,3,4) -------------------結果: (1, 2, 3, 4)
def func(*args): print(args) #如果傳入元組參數,那麼元組作為args的單個元素。 func((1,2),(3,4))
- 調用函數有 *
def func(*args): print(args) func(*(1,2,3,4)) #如果*(),實參元組前面有*,那麼實參元組内的每個元素都放到形參構成的元組内,即形參 func(*[1,2,3,4]) -----------------------結果: (1, 2, 3, 4) (1, 2, 3, 4)
def func(*args): #函數内print星号和不print星号的差別 print(args) print(*args) func(1,2,3,4) ---------結果:
(1, 2, 3, 4)
1 2 3 4
- 調用函數無 *
- 隻能用位置傳參
def func(*args): print(args) func(1) func(1,2) # args=(1, 2) func((11,22,33,44,55)) # args=((11,22,33,44,55),) func(*(11,22,33,44,55)) # args=(11,22,33,44,55) -----------------------結果: (1,) (1, 2) ((11, 22, 33, 44, 55),) (11, 22, 33, 44, 55)
- **kwargs
- 可以接受任意個數的關鍵字參數,并将參數轉換成字典。
- 調用函數無 **
def func(**kwargs): print(kwargs) func(k1=1,k2="mcw") ------------------------結果: {'k1': 1, 'k2': 'mcw'}
- 調用函數有**
def func(**kwargs): print(kwargs) func(**{'k1':'v2','k2':'v2'}) # kwargs={'k1':'v2','k2':'v2'} ---------------------------------結果: {'k1': 'v2', 'k2': 'v2'}
- 調用函數無 **
- 隻能用關鍵字傳參
- 綜合應用:無敵 + 無敵 => 真無敵
def func(*args,**kwargs): print(args,kwargs) func(1,2,3,4,5,k1=2,k5=9,k19=999) func(*[1,2,3],k1=2,k5=9,k19=999) func(*[1,2,3],**{'k1':1,'k2':3}) func(111,222,*[1,2,3],k11='alex',**{'k1':1,'k2':3}) ------------------------結果: (1, 2, 3, 4, 5) {'k1': 2, 'k5': 9, 'k19': 999} (1, 2, 3) {'k1': 2, 'k5': 9, 'k19': 999} (1, 2, 3) {'k1': 1, 'k2': 3} (111, 222, 1, 2, 3) {'k11': 'alex', 'k1': 1, 'k2': 3}
- 可以接受任意個數的關鍵字參數,并将參數轉換成字典。
5.7、混合傳參
def func(a1,*args)
func(1,2,3) 傳了1給a1,後面給args
def func(a1,*args,a2) 混搭
func(1,2,3,a2=4)
def func(a1,*args,a2=10) 混搭 a2隻能靠關鍵字來傳與上同。
def func(a1=2,*args,a2) #混搭 錯誤方式
def func(**kwargs) #傳多個鍵值對到函數,實參為鍵=值 #萬能,傳n個關鍵字參數。并将參數轉換
為字典
func(k1=1,k2="s")
def func(**kwargs): #kwargs={k1=1,k2="s"} #傳字典到函數内 **字典
print(kwargs)
func(**{"k1":1,"k2":"s"})
-------------結果:
{'k1': 1, 'k2': 's'}
def func(**kwargs) #kwargs={k1:{"m":"c"},k2:"s"} #将鍵值對和字典一起傳到函數内,
func(k1={"m":"c"},k2="s")
5.8、傳參使用場景總結:
1、我想要簡單點的基本傳參,用位置傳參;
2、我傳參想讓誰接收,用關鍵字傳參。
3、我沒傳參想讓形參有個預設值,用預設傳參;
4、我要傳遞多個參數,用一個*号的接收;
5、我要傳遞多個鍵值對或字典,用兩個**接收。
函數:增加代碼重用性,可讀性。
比如去樓下拿快遞,是個函數,告訴他拿**的快遞,他就拿到**的快遞
6、函數傳回值return
1) print 和 return 的差別,print 僅僅是列印在控制台,而 return 則是将 return 後面的部分作
為傳回值作為函數的輸出,可以用變量接走,繼續使用該傳回值做其它事。
2)函數需要先定義後調用,函數體中 return 語句的結果就是傳回值。如果一個函數沒有 reutrn 語句
,其實它有一個隐含的 return 語句,傳回值是 None,類型也是 'NoneType'。
3)return作用:結束函數調用、傳回值
4)終止函數的方法:滿足某個條件 return False
成功與不成功傳回一個結果。如果不需要列印,使用者隻需要某個結果,那麼讓函數傳回一個值,讓使用者
根據傳回值做對應的操作。return實作函數傳回值。
調用函數,并用變量接收函數的傳回值。
6.1使用變量接收傳回值:
def xiaoma():
a=1
return a
mcw=xiaoma()
print(mcw)
------------結果
1
6.2使用者根據函數傳回值做别的操作。(根據傳回值進行通信)
#當小明吃完飯,給我傳回1。小明吃完後小馬過河找他玩
def xiaoming(arg):
a=0
if arg=="吃完":
a=1
return a
status=xiaoming("吃完")
if status==1:
print("小馬過河去找小明玩")
--------------結果:
小馬過河去找小明玩
6.3傳回多個值的方法:
如果程式需要有多個傳回值,則既可将多個值包裝成清單之後傳回,也可直接傳回多個值。如果 Python
函數直接傳回多個值,Python 會自動将多個傳回值封裝成元組。多個值用逗号隔開。
1)python 函數使用 return 語句傳回 "傳回值",可以将其賦給其它變量作其它的用處
2)所有函數都有傳回值,如果沒有 return 語句,會隐式地調用 return None 作為傳回值
3)一個函數可以存在多條 return 語句,但隻有一條可以被執行,如果沒有一條 reutrn 語句被執行,同樣會隐式調用 return None 作為傳回值
4)如果有必要,可以顯式調用 return None 明确傳回一個None(空值對象)作為傳回值,可以簡寫為 return
5)如果函數執行了 return 語句,函數會立刻傳回,結束調用,return 之後的其它語句都不會被執行了
def list_sum(li):
sum=0
e_str=""
for i in li:
e_str+=str(i)
sum+=i
return sum,e_str
li=[1,2,3]
mcw=list_sum(li) # 擷取list_sum函數傳回的多個值,多個傳回值被封裝成元組
v1,v2=list_sum(li) #此外,也可使用 Python 提供的序列解包功能,直接使用多個變量接收函數傳回的多個值。
print(mcw)
print(v1,v2)
---------------結果:
(6, '123')
6 123
6.4return終止循環
def mcw(): #沒有return的時候,傳回值預設是None,循環正常結束。
for i in range(1,4):
print(i)
m=mcw()
print(m)
-------------結果:
1
2
3
None
def mcw(): #有return的時候,傳回指定的值,并終止函數向後繼續執行了。
for i in range(1,4):
if i==3:
return "終止函數了"
print(i)
m=mcw()
print(m)
-------------結果:
1
2
終止函數了
6.5、直接列印傳回值
def mcw():
return "魔降風雲變"
print(mcw())
6.6 for .. else .. 語句 (意外終止情況)
# 表示如果 for 語句段的内容正常循環結果才會執行 else 段的語句,如果 for 在循環過程中時被 break 或者 return 語句意外終止循環,就不會執行 else 段中的語句。
6.7、return可以傳回任意類型。
#假如需要函數傳回字典,清單等,就可以給函數調用的時候使用。
retrue 一個資料類型。
def func(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8):
return (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
print(func(1,False,None,"mcw",["xiaoma","1"],(1,2),{"name":"xiaoma"},{3,4}))
-------------------結果:
(1, False, None, 'mcw', ['xiaoma', '1'], (1, 2), {'name': 'xiaoma'}, {3, 4})
6.8、if判斷使用傳回值的三種方式:
def func(a1,a2):
if a1>a2:
return a1
else:
return a2
def func(a1,a2):
return a1 if a1>a2 else a2
def func(a1,a2):
b=a1 if a1>a2 else a2
return b
6.9可利用傳回值True和預設的傳回值None做函數傳回的判斷
def func(arg1):
if arg1==1:
return True
print(func(0))
-----------結果:
None
6.10其他的傳回值,非函數傳回值總結
li=[1,2]
print(li.append(3)) #沒有傳回值就是None嗎?
---------------結果:
None
li=[1,2]
m=li.append(3)
print(m)
-----------結果:
None
a="mcw"
a="*".join(a)
print(a)
----------------結果:
m*c*w
總結:清單所有方法基本上都是傳回None,字元串的所有方法基本上是傳回新值
7、函數作用域
7.1全局作用域
- py檔案:全局作用域
- 函數:局部作用域
- 變量先建立才能再使用。
- 函數也可以看做一個變量,指向一堆代碼
- 作用域中的資料歸自己所有,别人通路不到,局部作用域可以繼承全局作用域
- 函數調用全局變量,可以使用在函數調用之前的環境變量,但是不可以使用函數調用之後的
-
print(func) 傳回的位址
print(func()) 傳回調用值
-
a = 1 def s1(): x1 = 666 print(x1) print(a) print(b) b = 2 print(a) s1() a = 88888 def s2(): print(a,b) s1() s2() ---------------------結果: 1 666 1 2 88888 2 666 88888 2
- 總結:
- 一個函數一個作用域,(其他語言很多是一個代碼塊一個作用域)
- 作用域中查找資料的規則,優先在自己作用域尋找,自己沒有就去父集作用域中尋找,父集沒有再不斷往上層的父集去找。直到全局作用域,再沒有就報錯。
- 父集無法使用子集的變量。子集可以不斷往外層的父集尋找變量
- 1、找變量,本層沒有,2、去上一級作用域中,找調用本函數之前最後指派的那個變量,3、如果到達全局環境變量後還沒有就會報錯。如果沒有到達環境變量,請執行第2步。
-
globla 找到全局 找到後可以給全局變量重新指派,
nonloacl 找到上級,找到後可以給上級變量重新指派。
- 作用域每層都是有自己獨立的内部空間的,子能繼承父,但不能重新指派父,需要借助global和nonlocal。#思考(不确定的問題):有global和nonlocal找到父所在空間,重新開辟空間進行指派,否則開辟的是自己所在的空間嗎?
-
Python基礎知識-09-函數 def func(): x = 9 print(x) func() print(x) #函數内部能使用内部變量,但是函數外部不能使用函數内部變量 -------------結果: 9 Traceback (most recent call last): File "D:/aPython_full目錄/小馬過河的代碼練習/mcwday09.py", line 269, in <module> print(x) NameError: name 'x' is not defined
作用域中查找資料規則:優先在自己的作用域找資料,自己沒有就去 "父級" -> "父級" -> 直到全局,全部麼有就報錯。注意:父級作用域中的值到底是什麼?
x = 10
def func():
x = 9
print(x)
func()
---------------結果:
9
globla 找到全局 找到後可以重新指派,
nonloacl 找到上級,找到後後面重新指派
函數能修改函數外部可變資料類型如清單,集合,字典,但是預設是無法重新指派的。
如果一定要在函數中給環境變量重新指派,使用gloabal 變量。子作用域重新指派全局變量
如果是子函數中使用global重新指派,改的也是全局
nonloacl改的是父集,上一層的變量。
盡量不要修改全局。會造成代碼出現問題
全局變量都是使用大寫。局部變量正常的就行了。友善閱讀。潛規則。
7.2、global語句
https://www.jb51.net/article/147644.htm
https://blog.csdn.net/weixin_37583747/article/details/81262859
7.3、nonlocal語句
8、lambda函數(匿名函數)
8.1、lambda函數簡介
python 使用 lambda 來建立匿名函數。
所謂匿名,意即不再使用 def 語句這樣标準的形式定義一個函數。
- lambda 隻是一個表達式,函數體比 def 簡單很多。
- lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
- lambda 函數擁有自己的命名空間,且不能通路自己參數清單之外或全局命名空間裡的參數。
- 雖然lambda函數看起來隻能寫一行,卻不等同于C或C++的内聯函數,後者的目的是調用小函數時不占用棧記憶體進而增加運作效率。
8.2、lambda 函數文法
lambda 函數的文法隻包含一個語句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
8.3、
lambda 為了解決簡單函數的情況。運算相當于簡單函數編寫方式。這樣函數就相當于一個變量
一行表示,是以不定義變量,使用上一層作用域的變量
變量名=lambda 參數(有無*/**):操作或者函數傳回值(傳回值可為表達式,為三元運算;表達式有傳回的就
作為傳回值,否則傳回None)
表達式1:
沒有參數,隻傳回指定值
有一個參數,傳回表達式
有*和**的參數,舉例比如傳回*和**長度和
lambda 表達式結合三元運算,傳回值部分使用三元運算。
多個lambda放入清單。調用lambda.
9、函數中進階使用 高階函數
9.1、函數可以作為變量來使用
1)
def func():
print("mcw")
v1 = func #将函數名賦予一個變量,再給變量加上小括号便能代替原函數名執行這個函數。函數名指
向函數體的記憶體位置
func() #
v1()
-------------結果:
mcw
mcw
由上面那個函數列印可知,函數名賦予給變量後,他們都是指向一個記憶體位址,函數()代表函數傳回值
,預設為None。
print(type(func),type(func()),func,func())
print(type(v1),type(v1()),v1,v1())
------------結果:
123
123
<class 'function'> <class 'NoneType'> <function func at 0x00A28D20> None
123
123
<class 'function'> <class 'NoneType'> <function func at 0x00A28D20> None
2)函數名可以放入清單等資料類型,調用函數時加上小括号
def func():
print(123)
func_list = [func, func, func]
func_list[0]()
-----------結果:
123
def func():
print(123)
func_list = [func, func, func]
for item in func_list: 循環函數清單并列印函數傳回值
v = item()
print(v)
----------------結果:
123
None
123
None
123
None
3)函數名作為字典的值來用,(不建議當做鍵來用,沒啥意義)。
def func():
print(123)
def bar():
print(666)
info = {'k1': func, 'k2': bar}
info['k1']()
info['k2']()
------------------結果:
123
666
4)容易弄錯的案例:
def func():
return 123
func_list1 = [func,func,func]
func_list2 = [func(),func(),func()]
print(func_list1)
print(func_list2)
info = {
'k1':func,
'k2':func(),
}
print(info)
------------------結果:
[<function func at 0x00648D20>, <function func at 0x00648D20>, <function func at
0x00648D20>] #func函數名是指向函數的位址
[123, 123, 123] # func()是函數傳回值。這裡指定傳回值為123
{'k1': <function func at 0x00648D20>, 'k2': 123}
5)綜上可知:
def func():
print("mcw")
v1 = func
函數名實質上就是函數的記憶體位址。
當我們定義a=1的時候,系統會開辟一塊記憶體空間來儲存1,然後用a變量名儲存1所在的記憶體位址引用,變量名就好像C語言中的指針,大家可以把引用了解成位址,a裡面存的是1這個數值所在的位址,a存了1的引用。當我們在代碼中定義了一個函數,系統會配置設定一塊記憶體空間,用于儲存函數體的内部變量和函數名,這個v1隻是一個變量名,儲存了函數記憶體中的位址,我們可以v1=func,v2=func.這樣的操作就相當于把func中引用的位址,指派給v1,v2 ,這樣v1和v2都指向了func函數所在的引用,我們可以v1()和v2()來
調用func函數,調用實際上是一個函數,而v1,v2,func三個變量存了同一個函數的位址。
9.2、函數可以當作參數進行傳遞
1)
def func(arg):
print(arg)
def show():
return 999
func(show)
----------結果:
<function show at 0x00598D20> #将show函數作為參數傳到func函數,結果為print(show),show這個
函數名指向記憶體位址
2)
def func(arg):
v1 = arg()
print(v1)
def show():
print(666)
func(show)
---------------結果:
666
None
#函數執行分析:将函數名show作為func的參數,執行函數後,arg()會讓show函數執行并列印666,然後
将show函數執行的預設傳回結果賦予變量v1,列印出v1的值。
3)
def func(arg):
v1 = arg()
print(v1)
def show():
print(666)
result = func(show)
print(result)
---------------結果:
666
None
None
#函數執行分析:将函數名show傳參給func函數,然後show會在func内執行,列印666,并将預設傳回值
賦予變量v1并列印。func函數執行傳回預設值None并将值賦予變量result,然後列印result
4)函數傳參功能的使用案例。
(指定使用者輸入選項,并将每個選項的功能寫成函數,然後将函數做成字典,根據使用者輸入執行不同的函數,實作不同的功能)
def func():
print('花費查詢')
def bar():
print('語音溝通')
info = {
'f1': func,
'f2': bar,
}
choice = input('請選擇要選擇功能:')
function_name = info.get(choice)
if function_name:
function_name()
else:
print('輸入錯誤')
---------------結果:
請選擇要選擇功能:f1
花費查詢
9.3、函數可以做傳回值來使用
1)沒有
def func():
print(123)
def bar():
return func
v = bar()
v()
-----------結果:
123
#函數執行分析:函數bar執行後傳回另一個函數名func,将函數名指派給變量v,v()執行函數就等于func()執行func函數,即列印出123(原因:指派後,v和func指向同一個函數)
2)傳回另一個函數名并指派給變量
name = 'mcw'
def func():
print(name)
def bar():
return func
v = bar()
v()
--------------結果:
mcw
#函數執行分析:執行bar函數的傳回值(func函數名)賦給變量v。執行v也是執行func函數,列印變量name,func目前作用域沒有變量name,于是去上級作用域中找到并列印出來。
3)傳回子函數名并指派給變量
def bar():
def inner():
print(123)
return inner
v = bar()
v()
----------結果:
123
#函數執行分析:執行bar函數傳回inner,并将子函數名指派給變量v,執行函數v就是執行函數inner,
并列印出123.
4)傳回值為子函數結合作用域
name = 'xiaoma'
def bar():
name = 'mcw'
def inner():
print(name)
return inner
v = bar()
v()
------------------結果:
mcw
#函數執行分析:執行函數bar,将傳回值inner函數名指派給變量v,調用v即執行inner函數(二者執行同一個函數)。inner目前作用域沒有變量name,那麼先從上一級作用域中去找。
name = 'mcw'
def bar(name):
def inner():
print(name)
return inner
v1 = bar('yh') # { name=yh, inner } # 閉包,為函數建立一塊區域(内部變量供自己使用),為他
以後執行提供資料。
v2 = bar('syn') # { name=syn, inner }
v1()
v2()
-----------------結果:
yh
syn
#函數執行分析:[1]執行bar函數并傳入參數yh後,系統會建立一個獨立的記憶體空間給函數bar,然後将傳回值inner子函數名指派變量v1。如果bar函數内的資源沒有人占用那麼就會銷毀,而這裡由于函數的資源還有變量v1在使用是以沒有銷毀。[2]再次執行函數bar,并傳入參數syn,分析與第一步相同。[3]兩次調用同一個函數,但是兩次開辟的記憶體空間都是獨立的,傳入的參數也是不同的,并且在各自的記憶體空間中。當執行v1的時候,就是執行inner子函數,變量還是找v1所在的函數空間,即列印yh。當執行v2的時候,就是執行inner子函數,變量還是找v2所在的函數空間,即列印syn。
5)解釋閉包現象
def bar(name):
def inner():
print(name)
return inner() #沒有閉包,函數已經執行完畢
v1 = bar('yh')
#
空間不釋放,還被引用,空間還存在東西,沒有傳參也是閉包,函數執行終止了,記憶體還沒有釋放,。
怎樣不是閉包,傳回子函數傳回值,子函數已經執行完畢沒人使用它的資源
9.4函數閉包問題
函數名指向函數代碼,每次執行此函數,新開辟一份空間,(将代碼複制過來)。是以多次執行此函數
互不影響,它們有各自的空間。如果傳回的值正在被調用,函數的這個空間不銷毀,調用之後才銷毀
看函數是由誰建立的,誰那裡有函數的入口
name = 'mcw'
def bar(name):
def inner():
print(name)
return inner
v1 = bar('yh') # { name=yh, inner } # 閉包,為函數建立一塊區域(内部變量供自己使用),為他
以後執行提供資料。
v2 = bar('syn') # { name=syn, inner }
v1()
v2()
----------------結果:
yh
syn
#函數執行分析:[1]執行bar函數并傳入參數yh後,系統會建立一個獨立的記憶體空間給函數bar,然後将傳回值inner子函數名指派變量v1。如果bar函數内的資源沒有人占用那麼就會銷毀,而這裡由于函數的資源還有變量v1在使用是以沒有銷毀。[2]再次執行函數bar,并傳入參數syn,分析與第一步相同。[3]兩次調用同一個函數,但是兩次開辟的記憶體空間都是獨立的,傳入的參數也是不同的,并且在各自的記憶體空間中。當執行v1的時候,就是執行inner子函數,變量還是找v1所在的函數空間,即列印yh。當執行v2的時候,就是執行inner子函數,變量還是找v2所在的函數空間,即列印syn。
10、Python内置函數的了解
Python 解釋器内置了很多函數和類型,您可以在任何時候使用它們。以下按字母表順序列出它們。
内置函數 | ||||
---|---|---|---|---|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | |
- 自定義函數
-
-
其他
len open range id type -
輸入輸出
print input -
強制轉換
dict() list() tuple() int() str() bool() set() -
數學相關
- abs,絕對值
print(abs(1),abs(-1),abs(0)) -------結果: 1 1 0
- float,轉換成浮點型(小數)
print(float(3),float(0),float(2.5)) ----------結果: 3.0 0.0 2.5
- max,找到最大值
mcw=[2,1,4,3] print(max(mcw),min(mcw),sum(mcw)) -----------結果: 4 1 10
- min,找最小值
mcw=[2,1,4,3] print(max(mcw),min(mcw),sum(mcw)) -----------結果: 4 1 10
- sum,求和
mcw=[2,1,4,3] print(max(mcw),min(mcw),sum(mcw)) -----------結果: 4 1 10
- divmod,兩數相除的商和餘數
a,b = divmod(1001,5) print(a,b)
# 練習題 請通過分頁對資料進行展示 """ 要求: 每頁顯示10條資料 讓使用者輸入要檢視的頁面:頁碼 """
USER_LIST = [] #此處生成清單元素[{'name': '魔降風雲變-1', 'email': '[email protected]'},{'name': '魔降風雲變-2', 'email': '[email protected]'}。。。。。]
for i in range(1,836): temp = {'name':'魔降風雲變-%s' %i,'email':'123%[email protected]' %i } USER_LIST.append(temp) def paging(num,data_list): """ 實作分頁功能 :param num: 傳入分頁後每頁顯示的内容 :param data_list: 傳入清單,将每個清單元素分頁展示出來 """ total_count = len(data_list) # 資料總條數 per_page_count= num # 每頁顯示10條 max_page_num,a = divmod(total_count,per_page_count) # 總頁碼數 if a>0: max_page_num += 1 while True: try: page = int(input('要檢視第幾頁:')) except Exception as e: print("輸入有誤!") if page < 1 or page> max_page_num: print('頁碼不合法,必須是 1 ~ %s' %max_page_num ) else: start = (page-1) * per_page_count end = page * per_page_count data = data_list[start:end] for item in data: print(item) paging(4,USER_LIST)
------------------------------結果:
要檢視第幾頁:4
{'name': '魔降風雲變-13', 'email': '[email protected]'}
{'name': '魔降風雲變-14', 'email': '[email protected]'}
{'name': '魔降風雲變-15', 'email': '[email protected]'}
{'name': '魔降風雲變-16', 'email': '[email protected]'}
要檢視第幾頁:10000
頁碼不合法,必須是 1 ~ 209
要檢視第幾頁:
輸入有誤!
要檢視第幾頁:10
{'name': '魔降風雲變-37', 'email': '[email protected]'}
{'name': '魔降風雲變-38', 'email': '[email protected]'}
{'name': '魔降風雲變-39', 'email': '[email protected]'}
{'name': '魔降風雲變-40', 'email': '[email protected]'}
#總結:
- divmod,兩數相除的商和餘數
-
進制轉換相關
- bin,将十進制轉化成二進制
print(bin(4),bin(256)) #将十進制轉換為二進制 ----------結果: 0b100 0b100000000
- oct,将十進制轉換成八進制
print(oct(3),oct(8),oct(18)) #十進制轉換為8進制 ------------結果: 0o3 0o10 0o22
- int,将其他進制轉化成十進制
a="0b1001" b="0o5" c="0xA" print(int(a,base=2),int(b,base=8),int(c,base=16)) --------------結果: 9 5 10 a=0b1001 b=0o5 c=0xA print(int(a,base=2),int(b,base=8),int(c,base=16)) -----------------結果: print(int(a,base=2),int(b,base=8),int(c,base=16)) TypeError: int() can't convert non-string with explicit base
a=0b1001 print(type(a)) b=0o5 c=0xA print(int(a),int(b),int(c),type(a)) ----------------結果: <class 'int'> 9 5 10 <class 'int'>
綜上: 類似數字類型轉換為十進制:int(0o**),int(0x**),int(0b**) #不用加base參數 字元串類型轉換為十進制s #要加base參數
- hex,将十進制轉換成十六進制
print(hex(9),hex(10),hex(16),hex(20)) #将十進制轉換為16進制 -----------------------結果: 0x9 0xa 0x10 0x14
- 一道進制轉換的題
# 1位元組等于8位 # IP: 192.168.12.79 -> 001010010 . 001010010 . 001010010 . 001010010 # 1. 請将 ip = "192.168.12.79" 中的每個十進制數轉換成二進制并通過,連接配接起來生成一個新的字元串。
ip="192.68.12.79" li=ip.split(".") li2=[] for i in li: # li2.append(str(bin(int(i)))) li2.append(bin(int(i))) print(",".join(li2)) -----------------結果: 0b11000000,0b1000100,0b1100,0b1001111
# 2.請将ip=192.168.12.79中的四個十進制數轉換成二進制,将四個二進制數拼接成一個二進制數并轉換為 十進制。(注意:12轉換為二進制位數不滿8位) # 0010100100001010010001010010001010010 -> 十進制的值。
ip="192.168.12.79" li=ip.split(".") li2=[] for i in li: m=str(bin(int(i))).lstrip("0b") m="0"*(8-len(m))+m li2.append(m) mcw="".join(li2) print(int(mcw,base=2)) ----------------結果: 3232238671
- bin,将十進制轉化成二進制
-
bow使用:
1)函數有兩個必需參數x,y和一個可選參數z,結果傳回x的y次幂乘(相當于x**y),如果可選參數z有傳入值,則傳回幂乘之後再對z取模(相當于pow(x,y)%z)。
v1=pow(2,3)
v2=2**3
v3=pow(2,3,5)
v4=pow(2,3)%5
print([v1,v2,v3,v4])
----------------結果:
[8, 8, 3, 3]
2、所有的參數必須是數值類型
print(pow("3","2"))
----------結果:
print(pow("3","2"))
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'str'
3、如果x,y有一個是浮點數,則結果将轉換成浮點數。
print(pow(3.0,2))
--------------結果:
9.0
4、如果x,y都是整數,則結果也是整數,除非y是負數;如果y是負數,則結果傳回的是浮點數,浮點數不能取模,所有可選參數z不能傳入值。
>>> pow(10,2)
100
>>> pow(2,4)
16
>>> pow(2,-4)
0.0625
>>> pow(2,-4,3)
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
pow(2,-4,3)
ValueError: pow() 2nd argument cannot be negative when 3rd argument specified
5. 如果可選參數z傳入了值,x,y必須為整數,且y不能為負數。
>>> pow(2,3,5)
3
>>> pow(10,0.1,3)
File "<pyshell#17>", line 1, in <module>
pow(10,0.1,3)
TypeError: pow() 3rd argument not allowed unless all arguments are integers
>>> pow(10,-2,3)
File "<pyshell#18>", line 1, in <module>
pow(10,-2,3)
>>>
-- 編碼解碼相關:
1)chr,将十進制數字轉換成 unicode 編碼中的對應字元串。
print(chr(9798),chr(10087),chr(9787))
------------------結果:
♆ ❧ ☻
print(chr(9679),chr(9711),chr(9734),chr(9733))
-----------結果:
● ◯ ☆ ★
print([chr(i) for i in range(65,91)]) print([chr(i) for i in range(97,123)]) print(chr(65),chr(65+32),chr(90),chr(90+32)) -------------------結果: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] A a Z z
2)ord,根據字元在unicode編碼中找到其對應的十進制。
print(ord("A"),ord("a"),ord("☻"))
---------------結果:
65 97 9787
一些可能會用到的特殊符号(Unicode)
3)map,循環每個元素(第二個參數),然後讓每個元素執行函數(第一個參數),将每個函數執行的結果儲存到新的清單中,并傳回。
v1 = [11,22,33,44]
result = map(lambda x:x+100,v1)
print(list(result)) # 特殊
-------------結果:
[111, 122, 133, 144]
4)
v1 = [11,22,33,'asd',44,'xf']
def func(x):
if type(x) == int:
return True
return False
result = filter(func,v1) # [11,]
print(list(result))
-------------結果:
[11, 22, 33, 44]
v1 = [11,22,33,'asd',44,'xf']
result = filter(lambda x: True if type(x) == int else False ,v1)
print(list(result))
result = filter(lambda x: type(x) == int ,v1)
print(list(result))
---------------結果:
[11, 22, 33, 44]
[11, 22, 33, 44]
5)reduce
import functools
v1 = ['小','馬','過','河']
def func(x,y):
return x+y
result = functools.reduce(func,v1)
print(result)
result = functools.reduce(lambda x,y:x+y,v1)
print(result)
----------------結果:
小馬過河
小馬過河
from functools import reduce
result = reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
print(result)
---------------結果:
15
原理圖:在這個例子裡,其實計算過程是這樣的:((((1+2)+3)+4)+5) ,累加的過程。還可以實作階乘
來自:https://blog.csdn.net/caimouse/article/details/78129956
6)dir()
dir() 函數不帶參數時,傳回目前範圍内的變量、方法和定義的類型清單;帶參數時,傳回參數的屬性、方法清單。如果參數包含方法__dir__(),該方法将被調用。如果參數不包含__dir__(),該方法将最大限度地收集參數資訊。
import sys,os
print(dir(os))
----------------結果:
['DirEntry', 'F_OK', 'MutableMapping', 'O_APPEND', 'O_BINARY', 'O_CREAT', 'O_EXCL', 'O_NOINHERIT', 'O_RANDOM', 'O_RDONLY', 'O_RDWR', 'O_SEQUENTIAL', 'O_SHORT_LIVED', 'O_TEMPORARY', 'O_TEXT', 'O_TRUNC', 'O_WRONLY', 'P_DETACH', 'P_NOWAIT', 'P_NOWAITO', 'P_OVERLAY', 'P_WAIT', 'PathLike', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'W_OK', 'X_OK', '_Environ', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_execvpe', '_exists', '_exit', '_fspath', '_get_exports_list', '_putenv', '_unsetenv', '_wrap_close', 'abc', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'close', 'closerange', 'cpu_count', 'curdir', 'defpath', 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'errno', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fdopen', 'fsdecode', 'fsencode', 'fspath', 'fstat', 'fsync', 'ftruncate', 'get_exec_path', 'get_handle_inheritable', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getenv', 'getlogin', 'getpid', 'getppid', 'isatty', 'kill', 'linesep', 'link', 'listdir', 'lseek', 'lstat', 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', 'pathsep', 'pipe', 'popen', 'putenv', 'read', 'readlink', 'remove', 'removedirs', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sep', 'set_handle_inheritable', 'set_inheritable', 'spawnl', 'spawnle', 'spawnv', 'spawnve', 'st', 'startfile', 'stat', 'stat_float_times', 'stat_result', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sys', 'system', 'terminal_size', 'times', 'times_result', 'truncate', 'umask', 'uname_result', 'unlink', 'urandom', 'utime', 'waitpid', 'walk', 'write']
參考:https://docs.python.org/zh-cn/3/library/functions.html
11、上述總結
沒傳參的函數,有傳參的函數,沒傳回值的函數,有傳回值的函數。既有傳參又有傳回值的函數。需要
什麼樣的根據具體需求。
#自我總結
列印菱形
for i in range(1,4):
a=" "*(5-i) +"*"*i +"*"*(i-1)
print(a)
for i in range(2,4):
b=" "*(i+1)+"*"*(3-i)+"*"*(4-i)
print(b)
參考連結:
http://www.runoob.com/python3/python3-function.html
https://www.cnblogs.com/i-honey/p/7679897.html
http://c.biancheng.net/view/2248.html
參考續集
http://c.biancheng.net/view/2247.html