帶你學python基礎:函式是個function?
一、為什麼需要函式
有沒有發現,在前面的那麼多的教程當中,我們沒有函式是不是也是可以寫的出來的,似乎沒有函式這個東西,我們變成也是可以實現的,但是,在實際的開發過程中,我們為什麼需要函式呢,它到底能夠給我們變成帶來怎樣的好處呢?
其實, 函式
這個東西我們可以把它想成是一個 包裝盒
,我們沒有包裝盒的時候,其實也是可以把禮物送給相送的人手上的,但是,當我們用包裝盒包裝美化之後,我們首先會更 好拿
,其次,會更加的 好看
,更賞心悅目,當然,我們要達到的目的就是,讓收到禮物的人 開心
,所以,我們買禮物的時候,通常都會很用心的買一個包裝盒美美的包裝一下。
而 函式
,就是這麼個作用,我們需要把我們寫的零零散散的程式碼包裝起來,讓它更好閱讀,同時也能更好的管理我們的程式碼。
說了這麼多,那麼到底如何使用函式呢?下面一一道來。
二、如何定義函式
這裡,我們先把上面用很淺顯的話說的函式更加正式的表達一下。 函式
是 組織好的、可重複使用的、使用者實現單一或者關聯功能的程式碼段 。函式能夠提高應用的模組性和程式碼的重複利用率。
定義函式規則
def 函式名([引數列表]):#引數列表可選項 函式體
舉例
def printName(): print('我是 hello world!') printName()
注意幾點
- 函式程式碼塊以
def
關鍵詞開頭,後接函式識別符號名稱和圓括號()
。 - 任何傳入
引數和自變數
必須放在圓括號中間。 - 函式內容以
冒號
起始,並且縮排。
是不是很簡單,只要你學過一門程式語言,這些應該都是不值得一提。
現在我們定義好了函式,就相當於我們已經有了包裝禮物的包裝盒,那麼我們如何用包裝盒去包裝禮物呢,也就是說我們 如何去使用函式 呢?
使用函式
規則
函式名([引數列表])
舉例
- 定義函式
def printName(): print('我是 hello world!')
- 呼叫函式
printName()
其實就是這麼簡單!
好了,在我們包裝禮物的時候,可能我們會想收禮物的人寫封信或者寫點東西遞交給他,這個時候,我們可能會寫個小紙條啦,而函式,我們也可以傳信哦!
這時候,就要用到 函式引數 這個概念了。
三、函式引數
函式引數就是說我們可以在定義函式的時候,在括號中定義變數,用於傳給函式內部使用,已達到“傳信”’的效果!
舉例
def printName(name): print('我是:', name)
這個括號中的 name ,就是我們定義的函式引數了。
除了需要知道這個以外,我們還需要了解一個 概念 。
實參與形參
那麼什麼是實參,什麼是形參呢,通過下面這張圖,你就知道了!

我們 傳信 給對方的時候是不是也有很多的方式,比如,我們可以簡單的拿張小紙條寫寫,也可以買個信封寫封信。
同樣,函式的引數也有一些不同的型別。
引數型別
位置實參
位置實參:
函式定義中允許擁有多個形參,因此函式在呼叫的時候,也可能包含多個實參。向函式傳遞引數的方式有很多,通過 實參和形參的順序 對應

關鍵字引數
關鍵字實參是傳遞給函式的名稱-值對。直接在實參中將 名稱和值關聯
起來,因此向函式傳遞實參時不會混淆。函式呼叫使用關鍵字引數來確定傳入的值。所以,位置可以不用對應。
# 定義函式 def printName(name, age): print('我是:', name) print('我:', age) # 呼叫函式 printName(age=18, name='歐陽思海') # 名字跟形參對應,但是位置可以不對應
引數預設值
在很多語言都是有預設值這個特性的。
預設值:函式定義的時候,設定的引數是形參。那麼也可以給每個形參指定一個預設值。當呼叫函式時,如果沒有傳入實參,就使用形參的預設值。如果呼叫的時候傳入了實參,那麼程式將使用傳入的實參。
# 定義函式:使用預設值 age=15 def printName(name, age=15): print('我是:', name) print('我:', age) # 呼叫函式 printName(age=18, name='歐陽思海')# 名字跟形參對應,但是位置可以不對應 printName(name='歐陽思海')# age有預設值,不賦值,預設15

不定長引數
不定長引數:你可能需要一個函式能處理比當初宣告時更多的引數。
規則
def 函式名(*parameter,**parameter): 函式體
注意:加了 *
和 **
的就是不定長引數。
# 定義函式 def printPara(*para, **para2): print(para) print(para2) # 呼叫函式 printPara('one', 'two', 'three', four='4', five='5')

由此可知:
- 加
一個*
的不定長引數,會接收沒有命名的實參,且會轉為元祖tuple
。 - 加
兩個*
的不定長引數,會接受有命名的實參,且轉化為字典dictionary
。
以上就是函式引數的內容了。
有時候,我們把信封放在禮物中送給對方之後,可能,她直接把禮物加資訊拒絕了,這時候,就返回給你了。所以,把函式引數傳過去之後,並不是一定就輸出結果的,有時候,還會返回。所以就有 返回值
了
四、函式返回值
換專業點的話說:函式其實並非我們想象的總是簡單的將結果直接輸出,相反,函式的呼叫者需要函式提供一些通過函式處理過後的一個或者一組資料,只有呼叫者擁有了這個資料,才能夠做一些其他的操作。那麼這個時候,就需要函式返回給呼叫者資料,這個就被稱之為 返回值
,想要在函式中把結果返回給呼叫者,需要在函式中使用 return
。 return
就是返回值的 關鍵詞
。
下面,我們用一個例子直接看 return
怎麼使用。
def sum(a, b): return a + b result = sum(1, 2) print(result)
通過這個例子我們可以看出,通過 return 語句
這樣的方式,就可以把 我們想要返回的東西返回。
然後,通過 呼叫函式
可以用一個 變數
接收函式返回的值,以便儲存使用。
看了這個例子之後,我想,我們應該知道 return
有什麼作用了。
return 作用
- 返回結果。
- 退出函式,return 語句後的函式內容將不會再執行。
五、區域性變數和全域性變數
在程式語言中,都有叫做 變數域 的東西。也就是,限制我們變數在哪個地方能用,哪個地方不能用。
變數分為 區域性變數
和 全域性變數
。
區域性變數:在函式內定義的變數,區域性變數只能在所定義的函式內使用,在不同函式內定義的相同的變數是不會相互影響的,如果在 函式 A
中定義了變數 variable
,在 函式 B
中也定義了變數 variable
,這兩個是相互不影響的。
全域性變數:在函式外定義的變數,任何地方都可以使用。
舉例
c = 3# 全域性變數 def sum(a, b): d = 5# 區域性變數 return a + b result = sum(1, 2) print(result) print(c)# 正確,全域性變數處處可以訪問 print(d)# 錯誤,不能訪問區域性變數

下面,我們需要注意一個問題,當我們需要在函式內部修改一個全域性變數時,我們需要用一個關鍵詞 global
來宣告,這樣我們才能夠改變。
舉例
c = 3# 全域性變數 print('全域性變數id:', id(c)) def sum(a, b): global c c = 5# 區域性變數 print('sum中全域性變數id:', id(c)) return a + b def sum2(a, b): print('sum2中全域性變數id:', id(c)) return a + b sum(1, 2) print('全域性變數id..:', id(c)) sum2(2, 2)

在這個例子中我們可以看到,當我們用 global c
宣告之後,後面再使用變數 c 的時候,變數 c 已經改變了。
再用一個例子,當我們不用 global 宣告
直接修改時,後面的 變數 c
的 id的值是不會改變了。
c = 3# 全域性變數 print('全域性變數id:', id(c)) def sum(a, b): # global c c = 5# 區域性變數 print('sum中全域性變數id:', id(c)) return a + b def sum2(a, b): print('sum2中全域性變數id:', id(c)) # c = 10 return a + b sum(1, 2) print('全域性變數id..:', id(c)) sum2(2, 2)

注: id
是用來展示變數唯一性的。
六、匿名函式
匿名函式:定義函式的過程中,沒有給定名稱的函式就叫做 匿名函式
;Python 中使用 lambda 表示式
來建立匿名函式。
規則
lambda 引數列表: 表示式
下面我們先用一個例子來看看 lambda表示式 怎麼使用。
舉例
res = lambda a, b: a + b print(res(1, 2)) # 輸出3
其中,a,b是引數,a + b 是執行表示式,可以是簡單的表示式,也可以是函式等。
def sum(a, b): return a + b res = lambda a, b: sum(a, b) #執行表示式是函式 print(res(1, 2))
在前面的我們已經學過 if-else 形式了,在這裡,再學習一種不一樣的形式。
條件成立的內容if 條件 else 條件不成立的內容
舉例
s = lambda x, y: x if x > 2 else y print(s(2, 4)) # 輸出4
七、遞迴函式
遞迴就是子程式(或函式)直接呼叫自己或通過一系列呼叫語句間接呼叫自己。
形象點說就是一個黑洞一樣,一層一層的往裡走,走到最後,再往回走,直到走到出發點,這就是遞迴的整個過程。在走的過程中,我們就可以計算。
這裡只是簡單的說說遞迴函式的簡單的用法。
例如:
階乘 1 * 2 * 3 ··· * n
''' 階乘 ''' def jiechen(n): if n == 1: return 1 else: return n*jiechen(n-1) print(jiechen(10))
這個例子,就是函式自己再呼叫函式自己。
八、高階函式

map()
函式接收兩個引數,一個是函式,一個是序列, map
將傳入的函式依次作用到序列的每個元素,並把結果作為新的list返回。
舉例說明,比如我們有一個函式f(x)=x2,要把這個函式作用在一個list [1, 2, 3, 4, 5, 6, 7, 8, 9]
上,就可以用 map()
實現如下:

現在,我們用Python程式碼實現:
>>> def f(x): ...return x * x ... >>> map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) [1, 4, 9, 16, 25, 36, 49, 64, 81]
請注意我們定義的函式 f
。當我們寫 f
時,指的是函式物件本身,當我們寫 f(1)
時,指的是呼叫f函式,並傳入引數1,期待返回結果1。
因此, map()
傳入的第一個引數是 f
,即函式物件本身。
像 map()
函式這種能夠接收函式作為引數的函式,稱之為高階函式(Higher-order function)。
你可能會想,不需要 map()
函式,寫一個迴圈,也可以計算出結果:
L = [] for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]: L.append(f(n)) print L
的確可以,但是,從上面的迴圈程式碼,能一眼看明白“把f(x)作用在list的每一個元素並把結果生成一個新的list”嗎?
所以, map()
作為高階函式,事實上它把運算規則抽象了,因此,我們不但可以計算簡單的f(x)=x2,還可以計算任意複雜的函式。
再看reduce的用法。reduce把一個函式作用在一個序列[x1, x2, x3...]上,這個函式必須接收兩個引數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方說對一個序列求和,就可以用reduce實現:
>>> def add(x, y): ...return x + y ... >>> reduce(add, [1, 3, 5, 7, 9]) 25
當然求和運算可以直接用Python內建函式 sum()
,沒必要動用reduce。
但是如果要把序列 [1, 3, 5, 7, 9]
變換成整數13579,reduce就可以派上用場:
>>> def fn(x, y): ...return x * 10 + y ... >>> reduce(fn, [1, 3, 5, 7, 9]) 13579
這個例子本身沒多大用處,但是,如果考慮到字串 str
也是一個序列,對上面的例子稍加改動,配合 map()
,我們就可以寫出把 str
轉換為 int
的函式:
>>> def fn(x, y): ...return x * 10 + y ... >>> def char2num(s): ...return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] ... >>> reduce(fn, map(char2num, '13579')) 13579
整理成一個 str2int
的函式就是:
def str2int(s): def fn(x, y): return x * 10 + y def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] return reduce(fn, map(char2num, s))
還可以用lambda函式進一步簡化成:
def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] def str2int(s): return reduce(lambda x,y: x*10+y, map(char2num, s))
也就是說,假設Python沒有提供 int()
函式,你完全可以自己寫一個把字串轉化為整數的函式,而且只需要幾行程式碼!
這就是函式的基本內容了!