函數是帶名字的代碼塊,用於完成具體的工作。
使用關鍵字 def 來定義一個函數。向 Python 指出了函數名,還可能在括號內指出函數為完成其任務需要什麼樣的信息。緊跟在冒號後面的所有縮進行構成了函數體。
def greet(name): #函數名greet、參數name
print("Hello, " + name.title() + "!")
greet('aiolei') #調用函數
在函數 greet() 的定義中,變量 name 是一個形參,形參是函數完成其工作所需的一項信息。在代碼 greet (‘aiolei’) 中,值 ‘aiolei’ 是一個實參。實參是調用函數時傳遞給函數的信息。我們調用函數時,將要讓函數使用的信息放在括號內。
調用函數時,Python 必須將函數調用中的每個實參都關聯到函數定義中的一個形參。最簡單的關聯方式是基於實參的順序,這種關聯方式被稱為位置實參。
def pet(name,type,age): #三個參數
print("Pet's name is " + name.title() + ".")
print("Pet's type is " + type + ".")
print("Pet's age is " + age + ".\n")
pet('harry','hamster','6')
pet( 'willie','dog','8') #調用函數多次
注意:確認函數調用中實參的順序與函數定義中形參的順序一致。
關鍵字實參是傳遞給函數的名稱–值對,直接在實參中將名稱和值關聯起來。
def pet(name,type,age): #三個參數
print("Pet's name is " + name.title() + ".")
print("Pet's type is " + type + ".")
print("Pet's age is " + age + ".\n")
pet(age='6',name='harry',type='hamster') #無需考慮順序
注意:使用關鍵字實參時,務必准確地指定函數定義中的形參名。
編寫函數時,可給每個形參指定默認值。在調用函數中給形參提供了實參時,Python將使用指定的實參值;否則,將使用形參的默認值。
def pet(name,type='dog',age): #設置type默認值
print("Pet's name is " + name.title() + ".")
print("Pet's type is " + type + ".")
print("Pet's age is " + age + ".\n")
pet(name='harry',age='6')
注意:使用默認值時,在形參列表中必須先列出沒有默認值的形參,再列出有默認值的實參。這讓Python依然能夠正確地解讀位置實參。否則報錯(如下):
鑒於可混合使用位置實參、關鍵字實參和默認值,通常有多種等效的函數調用方式。
def pet(name,type):
print("Pet's name is " + name.title() + ".")
print("Pet's type is " + type + ".")
#一只名為Harry的倉鼠(三種方法效果一樣)
pet('harry', 'hamster')
pet(name='harry', type='hamster')
pet(type='hamster', name='harry')
使用哪種調用方式無關緊要,只要函數調用能生成你希望的輸出就行。使用對你來說最容易理解的調用方式即可。
當提供的實參多於或少於函數完成其工作所需的信息時,將出現實參不匹配錯誤。
函數並非總是直接顯示輸出,相反,它可以處理一些數據,並返回一個或一組值。函數返回的值被稱為返回值。在函數中,可使用 return 語句將值返回到調用函數的代碼行。
def name(first_name, last_name):
full_name = first_name + ' ' + last_name
return full_name.title() #返回完整的姓名
example = name('lei','xin') #將返回值存儲在變量example中
print(example)
對於人的姓名長度是不定的,很多人姓名不止兩部分,需要加入中間名。同時並非所有的人都有中間名,要使調用這個函數能正確地運行,需讓中間名變成可選的,可給實參 middle_name 指定一個默認值——空字符串,並在用戶沒有提供中間名時不使用這個實參。
#給middle_name指定一個默認值(空字符串),並將其移到形參列表的末尾
def name(first_name, last_name, middle_name=''):
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_name
else:
full_name = first_name + ' ' + last_name
return full_name.title() #返回完整的姓名
example_1 = name('lei','xin')
example_2 = name('lei','xin','xing')
print(example_1)
print(example_2)
函數可返回任何類型的值,包括列表和字典等較復雜的數據結構。
#可選形參middle_name、age ,將其默認值設置為空字符串
def build_person(first_name, last_name, middle_name='', age=''):
person = {
'first':first_name, 'last':last_name}
if middle_name:
person['middle'] = middle_name
if age:
person['age'] = age
return person #返回字典
example = build_person('lei','xin','xing','19')
print(example)
def name(first_name, last_name, middle_name=''):
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_name
else:
full_name = first_name + ' ' + last_name
return full_name.title() #返回完整的姓名
while True:
print("\nPlaese tell me your name:(enter 'q' to end)")
f_name = input("first_name:")
if f_name == "q":
break
m_name = input("middle_name:")
if m_name == "q":
break
l_name = input("last_name:")
if l_name == "q":
break
example = name(f_name,l_name,m_name)
print("\nHello, " + example + "!")
將列表傳遞給函數後,函數就能直接訪問其內容。一個簡單例子:
將列表傳遞給函數後,函數就可對其進行修改。在函數中對這個列表所做的任何修改都是永久性的,這讓你能夠高效地處理大量的數據。
舉一個打印機的例子,需要打印的設計存儲在一個列表中,打印後移到另一個列表中。
def printing(unprinted, completed): #正在打印
while unprinted:
current = unprinted.pop()
completed.append(current)
def show_completed(completed): #顯示已打印完成的模型
print("\nThe models have been printed:")
for i in completed:
print(i)
unprinted = ['paper_0','paper_1','paper_2'] #需要打印的模型
completed = [] #已打印的模型
printing(unprinted, completed)
show_completed(completed)
有時候,需要禁止函數修改列表。為解決這個問題,可向函數傳遞列表的副本而不是原件;這樣函數所做的任何修改都只影響副本,而絲毫不影響原件。
切片表示法[:] 創建列表的副本。
def printing(unprinted, completed): #正在打印
while unprinted:
current = unprinted.pop()
completed.append(current)
def show_completed(completed): #顯示已打印完成的模型
print("\nThe models have been printed:")
for i in completed:
print(i)
unprinted = ['paper_0','paper_1','paper_2'] #需要打印的模型
completed = [] #已打印的模型
printing(unprinted[:], completed) #unprinted後跟[:],便不清空需要打印的列表
show_completed(completed)
有時候,預先不知道函數需要接受多少個實參,好在 Python 允許函數從調用語句中收集任意數量的實參。函數只有一個形參*p ,但不管調用語句提供了多少實參,這個形參都將它們統統收入囊中。
如果要讓函數接受不同類型的實參,必須在函數定義中將接納任意數量實參的形參放在最後。Python 先匹配位置實參和關鍵字實參,再將余下的實參都收集到最後一個形參中。
def drink(number, *things):
if number == 1:
print("\nYou want " + str(number) + " bottle of each:")
else:
print("\nYou want " + str(number) + " bottles of each:")
for thing in things:
print("-- " + thing)
drink(1,'water','cola','milk')
有時候,需要接受任意數量的實參,但預先不知道傳遞給函數的會是什麼樣的信息。在這種情況下,可將函數編寫成能夠接受任意數量的鍵值對。
#形參中的兩個星號讓Python創建一個名為user_info的空字典,並將收到的所有鍵值對都封裝到這個字典中
def build_profile(first, last, **user_info): #接受名和姓,任意數量的關鍵字實參
profile = {
} #空字典
profile['first_name'] = first
profile['last_name'] = last
for key, value in user_info.items():
profile[key] = value
return profile
user = build_profile('albert', 'einstein', location='princeton', field='physics') #後兩個為關鍵字實參
print(user_profile)
將函數存儲在被稱為模塊的獨立文件中, 再將模塊導入到主程序中。import 語句允許在當前運行的程序文件中使用模塊中的代碼。
要讓函數是可導入的,得先創建模塊。模塊是擴展名為 .py 的文件,包含要導入到程序中的代碼。
#以上面的代碼為例,將build_profile()函數保存在profile.py文件中
import profile #導入模塊profile
user = build_profile('albert', 'einstein', location='princeton', field='physics') #後兩個為關鍵字實參
print(user_profile)
語法:from 模塊名 import 函數名1, 函數名2, 函數名3…
from profile import build_profile
from profile import build_profile as bp #將函數build_profile () 重命名為bp()
import profile as p #給模塊profile指定別名p
使用星號(*)運算符可讓 Python 導入模塊中的所有函數
from profile import *