Python中函數(shù)可以設(shè)定默認(rèn)值。
Python是dynamically typed的,可以接收任何數(shù)據(jù)類型,函數(shù)的參數(shù)也是,不用考慮輸入的數(shù)據(jù)類型,而是將其交給具體的代碼去判斷執(zhí)行,但是缺點(diǎn)是,必須在函數(shù)的開頭加上數(shù)據(jù)的類型檢查。
函數(shù)的嵌套
Python的函數(shù)支持嵌套
def f1():
print('hello')
def f2():
print('world')
f2()
f1()
# 輸出
hello
world
函數(shù)嵌套的作用:
- 能夠保證內(nèi)部函數(shù)的隱私,內(nèi)部函數(shù)只能被外部函數(shù)訪問,不會(huì)暴露全局作用域。比如一些隱私數(shù)據(jù),數(shù)據(jù)庫(kù)的用戶名和密碼等。
def connect_DB():
def get_DB_configuration():
...
return host, username, password
conn = connector.connect(get_DB_configuration())
return conn
- 合理的使用函數(shù)嵌套,能夠提高程序的運(yùn)行效率,可以看下遞歸的python代碼,求一個(gè)數(shù)的階乘:
def factorial(input):
# validation check
if not isinstance(input, int):
raise Exception('input must be an integer.')
if input < 0:
raise Exception('input must be greater or equal to 0' )
...
def inner_factorial(input):
if input <= 1:
return 1
return input * inner_factorial(input-1)
return inner_factorial(input)
print(factorial(5))
使用函數(shù)嵌套,輸入是否合法的檢查就只需要一次,如果不使用函數(shù)嵌套,就需要在inner_factorial中繼續(xù)做參數(shù)檢查
變量
- 注意:函數(shù)內(nèi)部不能隨意改變?nèi)肿兞康闹?/strong>
MIN_VALUE = 1
MAX_VALUE = 10
def validation_check(value):
...
MIN_VALUE += 1
...
validation_check(5)
MIN_VALUE和MAX_VALUE都是全局變量,這樣會(huì)報(bào)錯(cuò)
UnboundLocalError: local variable 'MIN_VALUE' referenced before assignment
因?yàn)?,Python的解釋器會(huì) 默認(rèn)函數(shù)內(nèi)部的變量 是局部變量,但是發(fā)現(xiàn)局部變量MIN_VALUE并沒有聲明,所以無法執(zhí)行相關(guān)操作。如果一定要在函數(shù)內(nèi)部改變?nèi)肿兞康闹担仨毤由?global 聲明:
MIN_VALUE = 1
MAX_VALUE = 10
def validation_check(value):
global MIN_VALUE
...
MIN_VALUE += 1
...
validation_check(5)
如果遇到函數(shù)內(nèi)部局部變量和全局變量同名的情況,在函數(shù)內(nèi)部,局部變量會(huì)覆蓋全局的變量。
- 嵌套函數(shù),內(nèi)部函數(shù)可以訪問外部函數(shù)定義的變量,但是無法修改,若要修改,必須加上 nonlocal 這個(gè)關(guān)鍵字
def outer():
x = "local"
def inner():
nonlocal x # nonlocal 關(guān)鍵字表示這里的 x 就是外部函數(shù) outer 定義的變量 x
x = 'nonlocal'
print("inner:", x)
inner()
print("outer:", x)
outer()
# 輸出
inner: nonlocal
outer: nonlocal
閉包(closure)
閉包和嵌套函數(shù)類似,只是閉包外部函數(shù)的返回值是內(nèi)部函數(shù)
def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of # 返回值是 exponent_of 函數(shù)
square = nth_power(2) # 計(jì)算一個(gè)數(shù)的平方
cube = nth_power(3) # 計(jì)算一個(gè)數(shù)的立方
print(square)
print(cube)
print(square(2))
print(cube(2))
<function nth_power.<locals>.exponent_of at 0x000002599895B5E0>
<function nth_power.<locals>.exponent_of at 0x000002599895B550>
4
8
使用閉包的一個(gè)原因是,閉包能讓程序變得更加簡(jiǎn)潔易讀,上面的邏輯其實(shí)可以直接寫成
def nth_power_rewrite(base, exponent):
return base ** exponent
但是,調(diào)用時(shí)區(qū)別就出來了
# 不適用閉包
res1 = nth_power_rewrite(base1, 2)
res2 = nth_power_rewrite(base2, 2)
res3 = nth_power_rewrite(base3, 2)
...
# 使用閉包
square = nth_power(2)
res1 = square(base1)
res2 = square(base2)
res3 = square(base3)