本系列主要學(xué)習(xí)Python的基本使用和語法知識(shí),后續(xù)可能會(huì)圍繞著AI學(xué)習(xí)展開。
Python3 (1) Python語言的簡(jiǎn)介
Python3 (2) Python語法基礎(chǔ)
Python3 (3) Python函數(shù)
Python3 (4) Python高級(jí)特性
Python3 (5) Python 函數(shù)式編程
Python3 (6) Python 模塊
Python3 (7) Python 面向?qū)ο缶幊?/a>
Python3 (8) Python 面向?qū)ο蟾呒?jí)編程
Python3 (9) Python 錯(cuò)誤、調(diào)試和測(cè)試
Python3 (10) Python IO編程
Python3 (11) Python 進(jìn)程和線程
Python3 (12) Python 常用內(nèi)建模塊
Python3 (14) Python 網(wǎng)絡(luò)編程
函數(shù)部分主要有函數(shù)的調(diào)用、函數(shù)的定義、函數(shù)的參數(shù)(參數(shù)部分比較難,相對(duì)于java增加了好多新的概念,參數(shù)可以各種組合)、函數(shù)的遞歸。
函數(shù)的調(diào)用
為什么先強(qiáng)調(diào)函數(shù)的調(diào)用呢,因?yàn)镻ython有好多內(nèi)置函數(shù),可以為我們解決各種問題。舉幾個(gè)例子:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
//abs() 獲取絕對(duì)值,我們可以直接調(diào)用
x = abs(100)
//abs 賦值給a, 相當(dāng)于a指向了abs函數(shù),這也體現(xiàn)python賦值的強(qiáng)大之處
a = abs
y = a(-20)
// int、str ...數(shù)據(jù)轉(zhuǎn)化函數(shù),可以對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換,前提是可以相互轉(zhuǎn)換的數(shù)據(jù)
z = int('123')
s = str(True)
print(x, y,z,s)
//數(shù)學(xué)類函數(shù)
print('max(1, 2, 3) =', max(1, 2, 3))
print('min(1, 2, 3) =', min(1, 2, 3))
print('sum([1, 2, 3]) =', sum([1, 2, 3]))
輸出結(jié)果:
100 20 123 True
max(1, 2, 3) = 3
min(1, 2, 3) = 1
sum([1, 2, 3]) = 6
python內(nèi)置函數(shù)的調(diào)用中,如果參數(shù)不匹配會(huì)出現(xiàn) TypeError 錯(cuò)誤:
Traceback (most recent call last):
File "F:/python/HelloWord/call_func.py", line 4, in <module>
x = a(100,200)
TypeError: abs() takes exactly one argument (2 given)
函數(shù)的定義
在Python中,定義一個(gè)函數(shù)要使用def語句,依次寫出函數(shù)名、括號(hào)、括號(hào)中的參數(shù)和 冒號(hào):,然后,在縮進(jìn)塊中編寫 函數(shù)體,函數(shù)的返回值用return語句返回,注意python中沒有大括號(hào)。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import math
//自定義一個(gè)取絕對(duì)值的函數(shù)
def my_abs(x):
//自定義類型異常捕獲機(jī)制,關(guān)鍵字 isinstance
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
n = my_abs(-20)
print(n)
# TypeError: bad operand type:
# my_abs('123')
輸出結(jié)果:
20
- 在函數(shù)中,一旦執(zhí)行到return時(shí),函數(shù)就執(zhí)行完畢,并將結(jié)果返回,如果沒有return 函數(shù)執(zhí)行完成后默認(rèn) return None , 函數(shù)中 return None 可以簡(jiǎn)寫成 return。
- 自定義的函數(shù),參數(shù)類型不會(huì)像內(nèi)置函數(shù)拋出 TypeError 異常,可以自定義TypeError 異常,來保證函數(shù)的嚴(yán)謹(jǐn)性。
空函數(shù)
def no_fun():
pass
print(no_fun())
輸出結(jié)果:
None
空函數(shù)的定義: 可以通過關(guān)鍵字 pass 來做函數(shù)體 意思很明顯,直接通過
函數(shù)返回值
python 中支持多參數(shù)返回,實(shí)質(zhì)上是返回一個(gè)tuple!
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
// 多參數(shù)接收
x, y = move(100, 100, 60, math.pi / 6)
// 單參數(shù)接收
n = move(100, 100, 60, math.pi / 6)
print(x, y,n)
輸出結(jié)果:
151.96152422706632 70.0 (151.96152422706632, 70.0)
函數(shù)參數(shù)
函數(shù)的參數(shù)定義非常的靈活,支持必選參數(shù)、位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)等、并且這些參數(shù)可以組合使用。
必選參數(shù)
def myPower(x):
return x * x
print("myPower (2)= ",myPower(2))
輸出結(jié)果:
myPower(2) = 4
參數(shù)x為必選參數(shù),否則TypeError: myPower() missing 1 required positional argument: 'x'。
位置參數(shù)
def myPower(x,n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
print("myPower = ",myPower(2,5))
輸出結(jié)果:
myPower = 32
myPower(x, n)函數(shù)有兩個(gè)參數(shù):x和n,這兩個(gè)參數(shù)都是位置參數(shù),調(diào)用函數(shù)時(shí),傳入的兩個(gè)值按照位置順序依次賦給參數(shù)x和n。
默認(rèn)參數(shù)
默認(rèn)參數(shù)相當(dāng)于java的重載,一個(gè)函數(shù)傳入不同個(gè)數(shù)的參數(shù),沒有傳的參數(shù),會(huì)有默認(rèn)參數(shù)來代替
def myPower(x,n = 2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
print("myPower = ",myPower(2))
輸出結(jié)果:
myPower = 4
- 注意定義函數(shù)時(shí),必選參數(shù)在前,默認(rèn)參數(shù)在后
- 變化大的的默認(rèn)參數(shù)在前,變化小的默認(rèn)參數(shù)在后,符合使用規(guī)則
- 默認(rèn)參數(shù)代替了java 中因?yàn)閰?shù)個(gè)數(shù)引起的重載,減少了函數(shù)的定義
- 定義默認(rèn)參數(shù)要牢記一點(diǎn):默認(rèn)參數(shù)必須指向不變對(duì)象!
比如定義一個(gè)函數(shù),傳入一個(gè)默認(rèn)參數(shù)list:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def my_list(L=[]):
L.append('END')
return L
N = my_list([1,2,3,4,5])
print(N)
# 第一次調(diào)用參數(shù)
K = my_list()
print(K)
# 第二次調(diào)用參數(shù)
R = my_list()
print(R)
print('--------------------')
def my_list1(L = None):
if L is None:
L = []
L.append('END')
return L
# 第一次調(diào)用參數(shù)
K1 = my_list1()
print(K1)
# 第二次調(diào)用參數(shù)
R1 = my_list1()
print(R1)
輸出結(jié)果:
[1, 2, 3, 4, 5, 'END']
['END']
['END', 'END']
--------------------
['END']
['END']
以上就可以看到,如果定義函數(shù)時(shí),參數(shù)為list: L = [ ] 在多次使用默認(rèn)參數(shù)時(shí) 就會(huì)出現(xiàn) 重復(fù)添加的情況,原因也很簡(jiǎn)單,我們定義了一個(gè)默認(rèn)參數(shù)的值就會(huì)創(chuàng)建一個(gè)數(shù)據(jù)對(duì)象,函數(shù)執(zhí)行完返回的值會(huì)存儲(chǔ)在數(shù)據(jù)對(duì)象中,所以再次調(diào)用會(huì)呈現(xiàn)累加的情況,我們可以給參數(shù)定義一個(gè)None L = None 特殊的一個(gè)空對(duì)象(這個(gè)對(duì)象是不變的),這樣就不會(huì)造成累加的情況了。
可變參數(shù)
可變參數(shù)指?jìng)魅氲膮?shù)是可變的,不同于默認(rèn)參數(shù),可變參數(shù)可以理解為傳入一個(gè)list或tuple,具體的使用有兩種方式
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 第一種
def my_calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
#傳入一個(gè)list
m = [1,2,3,4,5,6]
print(my_calc(m))
# 第二種
def my_calc1(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
# 直接將參數(shù)用逗號(hào)隔開,傳進(jìn)去
print(my_calc1(1,3,5,7,9))
# 接收一個(gè)list的寫法
n = [2,4,6,8,10]
print(my_calc1(*n))
輸出結(jié)果:
91
165
220
可以看出可變參數(shù)的寫法有兩種,一種是直接傳入一個(gè)list,第二種是用*numbers 直接將參數(shù)傳入,list 傳入時(shí)用 *n傳入。
關(guān)鍵字參數(shù)
關(guān)鍵字參數(shù)允許你傳入0個(gè)或任意個(gè)含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict。與java中傳入一個(gè)map 集合類似,如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
return
# 通過name = value 形式傳入
person('張三', 35, weight=55,height = 175)
##直接傳入一個(gè)dict
others = {'weight': 65,'height': 185}
person ('李四',45,**others)
輸出結(jié)果:
name: 張三 age: 35 other: {'weight': 55, 'height': 175}
name: 李四 age: 45 other: {'weight': 65, 'height': 185}
最后**others傳入的是others 的復(fù)制版本,others 的變化不會(huì)引起函數(shù)的變化。
命名關(guān)鍵字參數(shù)
命名關(guān)鍵字是與位置參數(shù)比較的,位置可以靈活,寫法在位置參數(shù)前加一個(gè)可變參數(shù)*args 或者*,命名關(guān)鍵字參數(shù)也可以有默認(rèn)參數(shù),如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def person(name, age, *, weight,heigth):
print('name=',name, 'age=',age,'weight=', weight,'heigth=', heigth)
person('張三', 24, weight=55, heigth=175)
def person(name, age, *args, weight,heigth):
print('name=',name, 'age=',age,'weight=', weight,'heigth=', heigth,args)
person('張三', 24,weight=55, heigth=175,*(1,2,3,4))
輸出結(jié)果:
name= 張三 age= 24 weight= 55 heigth= 175
name= 張三 age= 24 weight= 55 heigth= 175 (1, 2, 3)
組合參數(shù)
在Python中定義函數(shù),可以用必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù),這5種參數(shù)都可以組合使用。但是他們是有順序的跟運(yùn)算符的級(jí)別一樣。順序如下:
- 必選參數(shù)
- 默認(rèn)參數(shù)
- 可變參數(shù)
- 命名關(guān)鍵字參數(shù)
- 關(guān)鍵字參數(shù)
要注意的是不要同時(shí)使用太多的組合,否則函數(shù)接口的可理解性很差。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
args = (1, 2, 3, 4,5)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)
輸出結(jié)果:
a = 1 b = 2 c = 3 args = (4, 5) kw = {'d': 99, 'x': '#'}
不可思議吧,看到這個(gè)結(jié)果,對(duì)照組合參數(shù)的級(jí)別不難理解。參數(shù)到這就介紹完了,只有多實(shí)踐才能深入理解。
遞歸函數(shù)
遞歸函數(shù)在各種語言中都有,python的遞歸有啥特點(diǎn)呢?廖雪峰大神專門一節(jié)講解,我們就來看看吧。
遞歸函數(shù)的優(yōu)點(diǎn)是定義簡(jiǎn)單,邏輯清晰。理論上,所有的遞歸函數(shù)都可以寫成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰。
遞歸函數(shù)的缺點(diǎn)是遞歸太深的話,因?yàn)閜ython沒有尾遞歸優(yōu)化會(huì)導(dǎo)致棧溢出。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#n! n的階乘
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
print(fact(10))
print(fact(20))
輸出結(jié)果:
3628800
2432902008176640000
參考
https://www.python.org
http://www.runoob.com/python3/python3-tutorial.html
https://www.liaoxuefeng.com