Python學習筆記7_函 數
1.1 定義函數
def greet_user(): """顯示簡單的問候語""" print("Hello!") #一個空格 print("World!") greet_user()
1.1.1 向函數傳遞信息
# username = "Hello Python world!" def greet_user(username): """顯示簡單的問候語""" print("Hello, " + username.title() + "!") greet_user("yunfung")
1.2 傳遞實參
1.2.1 位置實參
def describe_pet(animal_type, pet_name):"""顯示寵物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "‘s name is " + pet_name.title() + ".") describe_pet(‘hamster‘, ‘harry‘)
1.2.2 關鍵字實參
直接在實參中將名稱和值關聯起來了,因此向函數傳遞實參時不會混淆.
def describe_pet(animal_type, pet_name): """顯示寵物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "‘s name is " + pet_name.title() + ".") describe_pet(animal_type=‘hamster‘, pet_name=‘harry‘)
1.2.3 默認值
編寫函數時,可給每個形參指定默認值。在調用函數中給形參提供了實參時,Python將使用指定的實參值;否則,將使用形參的默認值。
例如,如果調用describe_pet()時,描述的大都是小狗,就可將形參animal_type的默認值設置為‘dog‘。這樣,調用describe_pet()來描述小狗時,就可不提供這種信息:
def describe_pet(pet_name, animal_type=‘dog‘): """顯示寵物的信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "‘s name is " + pet_name.title() + ".") describe_pet(pet_name=‘willie‘)
1.3 返回值
在函數中,可使用return語句將值返回到調用函數的代碼行。
1.3.1 返回簡單值
def get_formatted_name(first_name, last_name): """返回整潔的姓名""" full_name = first_name + ‘ ‘ + last_name return full_name.title() musician = get_formatted_name(‘jimi‘, ‘hendrix‘) #離開循環不需要空格 print(musician)
1.3.2 讓實參變成可選的
有時候,需要讓實參變成可選的,這樣使用函數的人就只需在必要時才提供額外的信息。例如,假設我們要擴展函數get_formatted_name(),使其還處理中間名。
def get_formatted_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() musician = get_formatted_name(‘jimi‘, ‘hendrix‘) print(musician)
1.3.3 返回字典
函數可返回任何類型的值,包括列表和字典等較復雜的數據結構。
def build_person(first_name, last_name): """返回一個字典,其中包含有關一個人的信息""" person = {‘first‘: first_name, ‘last‘: last_name} return person musician = build_person(‘jimi‘, ‘hendrix‘) print(musician)
在函數定義中,新增了一個可選形參age,並將其默認值設置為空字符串。如果函數調用中包含這個形參的值,這個值將存儲到字典中。
def build_person(first_name, last_name, age=‘‘): """返回一個字典,其中包含有關一個人的信息""" person = {‘first‘: first_name, ‘last‘: last_name} if age: person[‘age‘] = age return person musician = build_person(‘jimi‘, ‘hendrix‘, age=27) print(musician)
1.3.4 結合使用函數和while 循環
def get_formatted_name(first_name, last_name): """返回整潔的姓名""" full_name = first_name + ‘ ‘ + last_name return full_name.title() # 這是一個無限循環! while True: print("\nPlease tell me your name:") f_name = input("First name: ") l_name = input("Last name: ") formatted_name = get_formatted_name(f_name, l_name) print("\nHello, " + formatted_name + "!")
1.4 傳遞列表
將greet_users()定義成接受一個名字列表,並將其存儲在形參names中。這個函數遍歷收到的列表,並對其中的每位用戶都打印一條問候語。
def greet_users(names): """向列表中的每位用戶都發出簡單的問候""" for name in names: msg = "Hello, " + name.title() + "!" print(msg) usernames = [‘hannah‘, ‘ty‘, ‘margot‘] greet_users(usernames)
1.4.1 在函數中修改列表
需要打印的設計存儲在一個列表中,打印後移到另一個列表中。下面是在不使用函數的情況下模擬這個過程的代碼:
# 首先創建一個列表,其中包含一些要打印的設計 unprinted_designs = [‘iphone case‘, ‘robot pendant‘, ‘dodecahedron‘] completed_models = [] # 模擬打印每個設計,直到沒有未打印的設計為止 # 打印每個設計後,都將其移到列表completed_models中 while unprinted_designs: current_design = unprinted_designs.pop() #模擬根據設計制作3D打印模型的過程 print("Printing model: " + current_design) completed_models.append(current_design) # 顯示打印好的所有模型 print("\nThe following models have been printed:") for completed_model in completed_models: print(completed_model)
程序首先創建一個需要打印的設計列表,還創建一個名為completed_models的空列表,每個設計打印都將移到這個列表中。只要列表unprinted_designs中還有設計,while循環就模擬打印設計的過程:從該列表末尾刪除一個設計,將其存儲到變量current_design中,並顯示一條消息,指出正在打印當前的設計,再將該設計加入到列表completed_models中。循環結束後,顯示已打印的所有設計:
為重新組織這些代碼,我們可編寫兩個函數,每個都做一件具體的工作。大部分代碼都與原來相同,只是效率更高。第一個函數將負責處理打印設計的工作,而第二個將概述打印了哪些設計:
def print_models(unprinted_designs, completed_models): """ 模擬打印每個設計,直到沒有未打印的設計為止 打印每個設計後,都將其移到列表completed_models中 """ while unprinted_designs: current_design = unprinted_designs.pop() # 模擬根據設計制作3D打印模型的過程 print("Printing model: " + current_design) completed_models.append(current_design) def show_completed_models(completed_models): """顯示打印好的所有模型""" print("\nThe following models have been printed:") for completed_model in completed_models: print(completed_model) unprinted_designs = [‘iphone case‘, ‘robot pendant‘, ‘dodecahedron‘] completed_models = [] print_models(unprinted_designs, completed_models) show_completed_models(completed_models)
1.4.2 禁止函數修改列表
向函數傳遞列表的副本而不是原件;這樣函數所做的任何修改都只影響副本,而絲毫不影響原件。
function_name(list_name[:])
切片表示法[:]創建列表的副本
print_models(unprinted_designs[:], completed_models)
雖然向函數傳遞列表的副本可保留原始列表的內容,但除非有充分的理由需要傳遞副本,否則還是應該將原始列表傳遞給函數,因為讓函數使用現成列表可避免花時間和內存創建副本,從而提高效率,在處理大型列表時尤其如此。
1.5 傳遞任意數量的實參
Python允許函數從調用語句中收集任意數量的實參。
例如,來看一個制作比薩的函數,它需要接受很多配料,但你無法預先確定顧客要多少種配料。下面的函數只有一個形參*toppings,但不管調用語句提供了多少實參,這個形參都將它們統統收入囊中:
def make_pizza(*toppings): """打印顧客點的所有配料""" print(toppings) make_pizza(‘pepperoni‘) make_pizza(‘mushrooms‘, ‘green peppers‘, ‘extra cheese‘)
形參名*toppings中的星號讓Python創建一個名為toppings的空元組,並將收到的所有值都封裝到這個元組中。
def make_pizza(*toppings): """概述要制作的比薩""" print("\nMaking a pizza with the following toppings:") for topping in toppings: print("- " + topping) make_pizza(‘pepperoni‘) make_pizza(‘mushrooms‘, ‘green peppers‘, ‘extra cheese‘)
1.5.1 結合使用位置實參和任意數量實參
如果要讓函數接受不同類型的實參,必須在函數定義中將接納任意數量實參的形參放在最後。Python先匹配位置實參和關鍵字實參,再將余下的實參都收集到最後一個形參中。例如,如果前面的函數還需要一個表示比薩尺寸的實參,必須將該形參放在形參*toppings的前面:
def make_pizza(size, *toppings): """概述要制作的比薩""" print("\nMaking a " + str(size) + "-inch pizza with the following toppings:") for topping in toppings: print("- " + topping) make_pizza(16, ‘pepperoni‘) make_pizza(12, ‘mushrooms‘, ‘green peppers‘, ‘extra cheese‘)
1.5.2 使用任意數量的關鍵字實參
有時候,需要接受任意數量的實參,但預先不知道傳遞給函數的會是什麽樣的信息。在這種情況下,可將函數編寫成能夠接受任意數量的鍵—值對——調用語句提供了多少就接受多少。一個這樣的示例是創建用戶簡介:你知道你將收到有關用戶的信息,但不確定會是什麽樣的信息。在下面的示例中,函數build_profile()接受名和姓,同時還接受任意數量的關鍵字實參:
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_profile = build_profile(‘albert‘, ‘einstein‘,location=‘princeton‘,field=‘physics‘) print(user_profile)
函數build_profile()的定義要求提供名和姓,同時允許用戶根據需要提供任意數量的名稱—值對。形參**user_info中的兩個星號讓Python創建一個名為user_info的空字典,並將收到的所有名稱—值對都封裝到這個字典中。然後遍歷字典user_info中的鍵—值對,並將每個鍵—值對都加入到字典profile中。
1.6 將函數存儲在模塊中
函數的優點之一是,使用它們可將代碼塊與主程序分離。通過給函數指定描述性名稱,可讓主程序容易理解得多。還可以更進一步,將函數存儲在被稱為模塊的獨立文件中,再將模塊導入到主程序中。import語句允許在當前運行的程序文件中使用模塊中的代碼。
1.6.1 導入整個模塊
模塊是擴展名為.py的文件,包含要導入到程序中的代碼。下面來創建一個包含函數make_pizza()的模塊。
def make_pizza(size, *toppings): """概述要制作的比薩""" print("\nMaking a " + str(size) + "-inch pizza with the following toppings:") for topping in toppings: print("- " + topping)
接下來,在pizza.py所在的目錄中創建另一個名為making_pizzas.py的文件,這個文件導入剛創建的模塊,再調用make_pizza()兩次:
如果使用這種import語句導入了名為module_name.py的整個模塊,就可使用下面的語法來使用其中任何一個函數:
module_name.function_name()
1.6.2 導入特定的函數
可以導入模塊中的特定函數,這種導入方法的語法如下:
from module_name import function_name
通過用逗號分隔函數名,可根據需要從模塊中導入任意數量的函數:
from module_name import function_0, function_1, function_2
對於前面的making_pizzas.py示例,如果只想導入要使用的函數,代碼將類似於下面這樣:
from pizza import make_pizza
make_pizza(16, ‘pepperoni‘)
make_pizza(12, ‘mushrooms‘, ‘green
peppers‘, ‘extra cheese‘)
1.6.3 使用as 給函數指定別名
如果要導入的函數的名稱可能與程序中現有的名稱沖突,或者函數的名稱太長,可指定簡短而獨一無二的別名——函數的另一個名稱,類似於外號。要給函數指定這種特殊外號,需要在導入它時這樣做。
下面給函數make_pizza()指定了別名mp()。這是在import語句中使用make_pizza as mp實現的,關鍵字as將函數重命名為你提供的別名:
from pizza import make_pizza
as mp
mp(16,
‘pepperoni‘)
mp(12,
‘mushrooms‘, ‘green
peppers‘, ‘extra cheese‘)
1.6.4 使用as 給模塊指定別名
同樣可以給模塊指定別名。
import pizza as p
p.make_pizza(16, ‘pepperoni‘)
p.make_pizza(12, ‘mushrooms‘, ‘green
peppers‘, ‘extra cheese‘)
1.6.5 導入模塊中的所有函數
使用星號(*)運算符可讓Python導入模塊中的所有函數:
from pizza import *
make_pizza(16, ‘pepperoni‘)
make_pizza(12, ‘mushrooms‘,
‘green peppers‘, ‘extra
cheese‘)
import語句中的星號讓Python將模塊pizza中的每個函數都復制到這個程序文件中。由於導入了每個函數,可通過名稱來調用每個函數,而無需使用句點表示法。然而,使用並非自己編寫的大型模塊時,最好不要采用這種導入方法:如果模塊中有函數的名稱與你的項目中使用的名稱相同,可能導致意想不到的結果:Python可能遇到多個名稱相同的函數或變量,進而覆蓋函數,而不是分別導入所有的函數。
1.7 函數編寫指南
編寫函數時,需要牢記幾個細節。
- 應給函數指定描述性名稱,且只在其中使用小寫字母和下劃線。描述性名稱可幫助你和別人明白代碼想要做什麽。給模塊命名時也應遵循上述約定。
- 每個函數都應包含簡要地闡述其功能的註釋,該註釋應緊跟在函數定義後面,並采用文檔字符串格式。文檔良好的函數讓其他程序員只需閱讀文檔字符串中的描述就能夠使用它
- 給形參指定默認值時,等號兩邊不要有空格:
def function_name(parameter_0, parameter_1=‘default value‘)
- 對於函數調用中的關鍵字實參,也應遵循這種約定:
function_name(value_0, parameter_1=‘value‘)
- PEP 8(https://www.python.org/dev/peps/pep-0008/)建議代碼行的長度不要超過79字符,這樣只要編輯器窗口適中,就能看到整行代碼。如果形參很多,導致函數定義的長度超過了79字符,可在函數定義中輸入左括號後按回車鍵,並在下一行按兩次Tab鍵,從而將形參列表和只縮進一層的函數體區分開來。
def function_name(
parameter_0, parameter_1, parameter_2,
parameter_3, parameter_4, parameter_5):
function body...
Python學習筆記7_函 數