抽象之函數(shù)
函數(shù)可以盡量避免重復(fù)的代碼,簡(jiǎn)化代碼。函數(shù)式結(jié)構(gòu)化編程的核心。
函數(shù)執(zhí)行特定的操作并返回一個(gè)值
def hello(name):
return 'Hello, ' + name + '!'
print(hello('world))
運(yùn)行這些代碼后,將有一個(gè)名為 hello 的新函數(shù)。它返回一個(gè)字符串,其中包含向唯一參數(shù)
指定的人發(fā)出的問(wèn)候語(yǔ)
給函數(shù)編寫(xiě)文檔:以確保其他人能夠理解,可添加注釋(以#打頭的內(nèi)容)
def square(x):
'Calculates the square of the number x.'
return x * x
# 可以像下面這樣訪問(wèn)文檔字符串:
print(square.__doc__)
'Calculates the square of the number x.'
#__doc__ 是函數(shù)的一個(gè)屬性。屬性將在第7章詳細(xì)介紹。屬性名中的雙下劃線表示這是一個(gè)特殊的屬性
有些函數(shù)什么都不返回,可以稱為過(guò)程。如果沒(méi)有聲明其返回值,則默認(rèn)返回None
參數(shù)魔法
在函數(shù)內(nèi)部給參數(shù)賦值對(duì)外部沒(méi)有任何影響
>>> def try_to_change(n):
... n = 'Mr. Gumby'
...
>>> name = 'Mrs. Entity'
>>> try_to_change(name)
>>> name
'Mrs. Entity'
字符串(以及數(shù)和元組)是不可變的(immutable),這意味著你不能修改它們(即只能替換
為新值)。
1.為何要修改參數(shù)
在提高程序的抽象程度方面,使用函數(shù)來(lái)修改數(shù)據(jù)結(jié)構(gòu)(如列表或字典)是一種不錯(cuò)的方式。
def store(data, full_name):
names = full_name.split()
if len(names) == 2: names.insert(1, '')
labels = 'first', 'middle', 'last'
for label, name in zip(labels, names):
people = lookup(data, label, name)
if people:
people.append(full_name)
else:
data[label][name] = [full_name]
函數(shù) store 執(zhí)行如下步驟。
(1) 將參數(shù) data 和 full_name 提供給這個(gè)函數(shù)。這些參數(shù)被設(shè)置為從外部獲得的值。
(2) 通過(guò)拆分 full_name 創(chuàng)建一個(gè)名為 names 的列表。
(3) 如果 names 的長(zhǎng)度為2(只有名字和姓),就將中間名設(shè)置為空字符串。
(4) 將 'first' 、 'middle' 和 'last' 存儲(chǔ)在元組 labels 中(也可使用列表,這里使用元組只是為
了省略方括號(hào))。
(5) 使用函數(shù) zip 將標(biāo)簽和對(duì)應(yīng)的名字合并,以便對(duì)每個(gè)標(biāo)簽?名字對(duì)執(zhí)行如下操作:
獲取屬于該標(biāo)簽和名字的列表;
將 full_name 附加到該列表末尾或插入一個(gè)新列表。
2.如果參數(shù)是不可變的
如果一定要修改參數(shù),可玩點(diǎn)花樣,比如將值放在列表中
3.關(guān)鍵字參數(shù)和默認(rèn)值
有時(shí)候,參數(shù)的排列順序可能難以記住,尤其是參數(shù)很多時(shí)。為了簡(jiǎn)化調(diào)用工作,可指定參
數(shù)的名稱。主要優(yōu)點(diǎn)是有助于澄清各個(gè)參數(shù)的作用。
參數(shù)指定默認(rèn)值后,調(diào)用函數(shù)時(shí)可不提供它!可以根據(jù)需要,一個(gè)參數(shù)值也不提供、
提供部分參數(shù)值或提供全部參數(shù)值。
4.收集參數(shù)
允許用戶提供任意數(shù)量的參數(shù)很有用。
def print_params(*params):
print(params)
def print_params_4(x, y, z=3, *pospar, **keypar):
print(x, y, z)
print(pospar)
print(keypar)
其效果與預(yù)期的相同。
>>> print_params_4(1, 2, 3, 5, 6, 7, foo=1, bar=2)
1 2 3
(5, 6, 7)
{'foo': 1, 'bar': 2}
>>> print_params_4(1, 2)
1 2 3
()
{}