圖解Python 【第三篇】:Python-函數
本節內容一覽圖
一、函數介紹
1、什麽是函數
2、定義一個函數
你可以定義一個由自己想要功能的函數,以下是簡單的規則:
- 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()。
- 任何傳入參數和自變量必須放在圓括號中間,圓括號之間可以用於定義參數。
- 函數的第一行語句可以選擇性地使用文檔字符串—用於存放函數說明。
- 函數內容以冒號起始,並且縮進。
- return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。
註意:
- 函數在執行過程中只要遇到return語句,就會停止執行並返回結果,so 也可以理解為 return 語句代表著函數的結束
- 如果未在函數中指定return,那這個函數的返回值為None
3、函數語法:
二、函數參數與局部變量
一覽表:
形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量
實參可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。因此應預先用賦值,輸入等辦法使參數獲得確定值
1、默認參數
看下面代碼
1 2 3 4 5 6 7 8 9 10 |
def stu_register(name,age,country,course): print ( "----註冊學生信息------" )
print ( "姓名:" ,name)
print ( "age:" ,age)
print ( "國籍:" ,country)
print ( "課程:" ,course)
stu_register( "王山炮" , 22 , "CN" , "python_devops" )
stu_register( "張叫春" , 21 , "CN" , "linux" )
stu_register( "劉老根" , 25 , "CN" , "linux" )
|
發現 country 這個參數 基本都 是"CN", 就像我們在網站上註冊用戶,像國籍這種信息,你不填寫,默認就會是 中國, 這就是通過默認參數實現的,把country變成默認參數非常簡單
1 |
def stu_register(name,age,course,country = "CN" ):
|
這樣,這個參數在調用時不指定,那默認就是CN,指定了的話,就用你指定的值。
另外,你可能註意到了,在把country變成默認參數後,我同時把它的位置移到了最後面,為什麽呢?
2、關鍵參數
正常情況下,給函數傳參數要按順序,不想按順序就可以用關鍵參數,只需指定參數名即可,但記住一個要求就是,關鍵參數必須放在位置參數之後。
1 |
stu_register(age = 22 ,name = ‘alex‘ ,course = "python" ,)
|
3、非固定參數
若你的函數在定義時不確定用戶想傳入多少個參數,就可以使用非固定參數
1 2 3 4 5 6 7 8 9 10 |
def stu_register(name,age, * args): # *args 會把多傳入的參數變成一個元組形式
print (name,age,args)
stu_register( "Alex" , 22 )
#輸出
#Alex 22 () #後面這個()就是args,只是因為沒傳值,所以為空
stu_register( "Jack" , 32 , "CN" , "Python" )
#輸出
# Jack 32 (‘CN‘, ‘Python‘)
|
還可以有一個**kwargs
1 2 3 4 5 6 7 8 9 10 |
def stu_register(name,age, * args, * * kwargs): # *kwargs 會把多傳入的參數變成一個dict形式
print (name,age,args,kwargs)
stu_register( "Alex" , 22 )
#輸出
#Alex 22 () {}#後面這個{}就是kwargs,只是因為沒傳值,所以為空
stu_register( "Jack" , 32 , "CN" , "Python" ,sex = "Male" ,province = "ShanDong" )
#輸出
# Jack 32 (‘CN‘, ‘Python‘) {‘province‘: ‘ShanDong‘, ‘sex‘: ‘Male‘}
|
4、局部變量
1 2 3 4 5 6 7 8 9 10 11 |
name = "Alex Li"
def change_name(name):
print ( "before change:" ,name)
name = "金角大王,一個有Tesla的男人"
print ( "after change" , name)
change_name(name)
print ( "在外面看看name改了麽?" ,name)
|
輸出
1 2 3 |
before change: Alex Li
after change 金角大王,一個有Tesla的男人
在外面看看name改了麽? Alex Li
|
5、全局與局部變量
在子程序中定義的變量稱為局部變量,在程序的一開始定義的變量稱為全局變量。 全局變量作用域是整個程序,局部變量作用域是定義該變量的子程序。 當全局變量與局部變量同名時: 在定義局部變量的子程序內,局部變量起作用;在其它地方全局變量起作用
三、函數基礎類型
1、匿名函數
lambda表達式
# ###################### 普通函數 ###################### # 定義函數(普通方式) def func(arg): return arg + 1 # 執行函數 result = func(123) # ###################### lambda ###################### # 定義函數(lambda表達式) my_lambda = lambda arg : arg + 1 # 執行函數 result = my_lambda(123)View Code
匿名函數就是不需要顯式的指定函數
#這段代碼 def calc(n): return n**n print(calc(10)) #換成匿名函數 calc = lambda n:n**n print(calc(10))View Code
匿名函數有個限制,就是只能有一個表達式,不用寫return
,返回值就是該表達式的結果
#!/usr/bin/python3 # 可寫函數說明 sum = lambda arg1, arg2: arg1 + arg2; # 調用sum函數 print ("相加後的值為 : ", sum( 10, 20 )) print ("相加後的值為 : ", sum( 20, 20 ))View Code
小結
Python對匿名函數的支持有限,只有一些簡單的情況下可以使用匿名函數。
- lambda 只是一個表達式,函數體比 def 簡單很多。
- lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
- lambda 函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間裏的參數。
- 雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不占用棧內存從而增加運行效率。
2、遞歸函數
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數
尾遞歸調用時,如果做了優化,棧不會增長,因此,無論多少次調用也不會導致棧溢出。
遺憾的是,大多數編程語言沒有針對尾遞歸做優化,Python解釋器也沒有做優化,所以,即使把上面的fact(n)
函數改成尾遞歸方式,也會導致棧溢出。
小結
使用遞歸函數的優點是邏輯簡單清晰,缺點是過深的調用會導致棧溢出。
針對尾遞歸優化的語言可以通過尾遞歸防止棧溢出。尾遞歸事實上和循環是等價的,沒有循環語句的編程語言只能通過尾遞歸實現循環。
Python標準的解釋器沒有針對尾遞歸做優化,任何遞歸函數都存在棧溢出的問題。
3、裝飾器
小結
在面向對象(OOP)的設計模式中,decorator被稱為裝飾模式。OOP的裝飾模式需要通過繼承和組合來實現,而Python除了能支持OOP的decorator外,直接從語法層次支持decorator。Python的decorator可以用函數實現,也可以用類實現。
decorator可以增強函數的功能,定義起來雖然有點復雜,但使用起來非常靈活和方便
4、內置函數
註:查看詳細猛擊這裏
四、高級特性:
1、生成器generator
Python中,這種一邊循環一邊計算的機制,稱為生成器:generator
定義:一個函數調用時返回一個叠代器,那這個函數就叫做生成器(generator),如果函數中包含yield語法,那這個函數就會變成生成器
第一種方法很簡單,只要把一個列表生成式的[]
改成()
,就創建了一個generator:
通過next()
函數獲得generator的下一個返回值
使用for
循環,因為generator也是可叠代對象
第二種方法。如果一個函數定義中包含yield
關鍵字,那麽這個函數就不再是一個普通函數,而是一個generator:
2、叠代
如果給定一個list或tuple,我們可以通過for
循環來遍歷這個list或tuple,這種遍歷我們稱為叠代(Iteration)
在Python中,叠代是通過for ... in
來完成的,而很多語言比如C或者Java,叠代list是通過下標完成的
任何可叠代對象都可以作用於for
循環,包括我們自定義的數據類型,只要符合叠代條件,就可以使用for
循環
3、叠代器Iterator
叠代器是訪問集合元素的一種方式。
叠代器是一個可以記住遍歷的位置的對象。
叠代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。叠代器只能往前不會後退。
叠代器有兩個基本的方法:iter() 和 next()。
字符串,列表或元組對象都可用於創建叠代器
可以直接作用於for
循環的數據類型有以下幾種:
一類是集合數據類型,如list
、tuple
、dict
、set
、str
等;
一類是generator
,包括生成器和帶yield
的generator function。
這些可以直接作用於for
循環的對象統稱為可叠代對象:Iterable
。
可以使用isinstance()
判斷一個對象是否是Iterable
對象:
生成器都是Iterator
對象,但list
、dict
、str
雖然是Iterable
,卻不是Iterator
。
把list
、dict
、str
等Iterable
變成Iterator
可以使用iter()
函數
特點:
- 訪問者不需要關心叠代器內部的結構,僅需通過next()方法不斷去取下一個內容
- 不能隨機訪問集合中的某個值 ,只能從頭到尾依次訪問
- 訪問到一半時不能往回退
- 便於循環比較大的數據集合,節省內存
小結
凡是可作用於for
循環的對象都是Iterable
類型;
凡是可作用於next()
函數的對象都是Iterator
類型,它們表示一個惰性計算的序列;
集合數據類型如list
、dict
、str
等是Iterable
但不是Iterator
,不過可以通過iter()
函數獲得一個Iterator
對象。
Python的for
循環本質上就是通過不斷調用next()
函數實現的
聲明:
本人在學習老男孩python自動化網絡課程後,結合所學整理做次筆記,本文內容多出
Alex老師博客:http://www.cnblogs.com/alex3714/articles/5740985.html
武沛齊老師博客:http://www.cnblogs.com/wupeiqi/articles/5453708.html
感謝老男孩教育老師Alex,武沛齊老師,本文多從二位老師文章中結合整理
感謝麻瓜編程侯爵
http://www.runoob.com/python3/python3-basic-syntax.html
https://python.xiaoleilu.com/100/101.html
http://www.ituring.com.cn/book/1863
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318435599930270c0381a3b44db991cd6d858064ac0000
圖解Python 【第三篇】:Python-函數