函數(shù)
位置實參
你調(diào)用函數(shù)時,Python必須將函數(shù)調(diào)用中的每個實參都關聯(lián)到函數(shù)定義中的一個形參。因此最簡單的關聯(lián)方式是基于實參的順序。這種關聯(lián)方式被稱為位置實參。
def describe(animal_type,pet_name):
'''顯示寵物的信息‘’‘
print('I have a'+anmial_type + '.' + 'Its name is'+ pet_name)
describe('dog','harry')
位置實參的順序很重要
使用位置實參來調(diào)用函數(shù)時,如果實參的順序不正確,結果可能出乎意料:
比如再上面的例子中,我們先指定名字,再指定動物類型describe('harry','dog')由于實參'harry'在前,這個值將存儲到形參animal_type中;同理,'hamster'將存儲到形參pet_name中。結果時我們得到了一個名字為dog的harry:
describe('harry','dog')
>>I have a harry. Its name is dog
關鍵字實參
關鍵字實參是傳遞給函數(shù)名稱-值對。
直接在實參中將名稱和值關聯(lián)起來,因此向函數(shù)傳遞實參時不會混淆(不會的得到名為dog的harry這樣的結果)。關鍵字實參讓你無需考慮函數(shù)調(diào)用中的實參順序,還清楚地指出了函數(shù)調(diào)用中各個值得用途。
下面兩個函數(shù)調(diào)用是等效得:
describe(animal_type = 'dog',pet_name = 'harry')
describe(pet_name = 'harry',animal_type = 'dog')
關鍵字實參得順序無關緊要,因為Python知道各個值該存儲到哪個形參中。
注:使用關鍵字實參時,務必準確地指定函數(shù)定義中地形參名
默認值
編寫函數(shù)時,可給每個形參指定默認值。在調(diào)用函數(shù)中給形參提供了實參時,Python將使用指定地實參值;否則,將使用形參的默認值。因此,給形參指定默認值后,可在函數(shù)調(diào)用中省略相應的實參。使用默認值可簡化函數(shù)調(diào)用,還可清楚地指出函數(shù)地典型用法。
例如,如果你發(fā)現(xiàn)調(diào)用describe()時,描述的大都是小狗,就可將形參animal_type的默認值設置為‘dog'。這樣,調(diào)用describe()來描述小狗時,就可不提供這種信息:
def describe(pet_name,animal_type = 'dog'):
'''顯示寵物的信息‘’‘
print('I have a'+anmial_type + '.' + 'Its name is'+ pet_name)
這樣調(diào)用這個函數(shù)時,如果沒有給animal_type指定值,Python將把這個形參設置為’dog‘:
describe(pet_name = 'willie')
>>I have a dog. Its name is willie
請注意,在這個函數(shù)的定義中,修改了形參的排列順序。由于給animal_type指定了默認值,無需通過實參來指定動物類型,因此在函數(shù)調(diào)用中只包含一個實參——寵物的名字。然而,python依然將這個實參視為位置實參,因此如果函數(shù)調(diào)用中只包含寵物的名字,這個實參將關聯(lián)到函數(shù)定義中的第一個形參。這就是需要將pet_name放在形參列表開頭的原因所在。
現(xiàn)在,使用這個函數(shù)的最簡單的方式是,在函數(shù)調(diào)用中只提供小狗的名字:
describe('willie')
這個函數(shù)調(diào)用的輸出與前一個示例相同。只提供了一個實參——'willie',這個實參將關聯(lián)到函數(shù)定義中的第一個形參——pet_name。由于沒有給animal_type提供實參,因此Python使用其默認值'dog'。
注意:使用默認值時,在形參列表中必須先列出沒有默認值的形參,再列出有默認值的形參。這讓Python依然能夠正確地解讀位置實參。
讓實參變成可選的
有時候,需要讓實參變成可選的,這樣使用函數(shù)的人就只需在必要時才提供額外的信息。可使用默認值來讓實參變成可選的。
例如,假如
def get_formatted_name(first_name,middle_name,last_name):
"""返回整潔的姓名"""
full_name = first_name + ' ' + middle_name + last_name
return full_name.title()
只要同時提供名,中間名和姓,這個函數(shù)就能正確地運行。它根據(jù)這三部分創(chuàng)建一個字符串,在適當?shù)氐胤郊由峡崭?,并將結果轉(zhuǎn)換為首字母大寫格式
然而,并非所有地人都有中間名,但如果你調(diào)用這個函數(shù)時只提供了名和姓,它將不能正確地運行。為讓中間名變成可選地,可給實參middle_name指定一個默認值——空字符串,并在用戶沒有提供中間名時不使用這個實參。為讓get_formatted_name()在沒有提供中間名時依然可行,可給實參middle_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()
在這個示例中,姓名是根據(jù)三個可能提供地部分創(chuàng)建的。由于人都有名和姓,因此在函數(shù)定義中首先列出了這兩個形參。中間名是可選的,因此在函數(shù)定義中最后列出該形參,并將默認值設置為空字符串。
傳遞任意數(shù)量的實參
有時候,你預先不知道函數(shù)需要接受多少個實參,好在Python允許函數(shù)從調(diào)用語句中收集任意數(shù)量的實參。
例如,來看看一個制作比薩的函數(shù),它需要接受很多配料,但你無法預先確定顧客要多少種配料。下面的函數(shù)只有一個形參*toppings,但不管調(diào)用語句提供了多少實參,這個形參都將它們統(tǒng)統(tǒng)收入囊中:
def make_pizza(*toppings):
"""打印顧客點的所有配料"""
print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms','green peppers','extra cheese')
形參名*toppings中的星號讓Python創(chuàng)建一個名為topings的空元組,并收到的所有值都封裝到這個元組中。
不管收到的是一個值還是三個值,這個函數(shù)都能妥善地處理:
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')
>>making a pizza with the following toppings:
- pepperoni
making a pizza with the following topings:
- mushrooms
- green pepers
- extra cheese
結合使用位置實參和任意數(shù)量實參
如果要讓函數(shù)接受不同類型的實參,必須在函數(shù)定義中將接納任意數(shù)量實參的形參放在最后。PYthon先匹配位置實參和關鍵字實參,再將余下的實參都收集到最后一個形參中。
例如,如果前面的函數(shù)還需要一個表示比薩尺寸的實參,必須將該形參放在形參*toppings的前面:
def make_pizza(size,*toppings):
"""概述要制作的披薩"""
print("\nMaking a " + str(size)+"-ich pizze with the following toppings:")
for toppings in toppings:
print("- " + topping)
making_pizza(16,'pepperoni')
making_pizza(12,'mushrooms','green peppers','extra cheese')
使用任意數(shù)量的關鍵字實參
有時候,需要接受任意數(shù)量的實參,但預先不知道傳遞給函數(shù)的會是什么樣的信息。在這種情況下,可將函數(shù)編寫成能夠接受任意數(shù)量的鍵-值——調(diào)用語句提供了多少就接受多少。
示例:創(chuàng)建用戶簡介
只知道將要收到關于用戶的信息,但不確定會是什么樣的信息。在下面的示例中,函數(shù)build_profile()接受名和姓,同時還接受任意數(shù)量的關鍵字實參
#user_profile.py
def build_profile(first,last,**user_info)
"""創(chuàng)建一個字典,其中包含我們知道的有關用戶的一切"""
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)
函數(shù)build_profile()的定義要求提供名和姓,同時允許用戶根據(jù)需要提供任意數(shù)量的名稱-值對。形參**user_info中的兩個星號讓Python創(chuàng)建一個名為user_info的空字典,并將收到的所有名稱-值對都封裝到這個字典中。在這個函數(shù)中,可以像訪問其他字典那樣訪問user_info中的名稱-值對
將函數(shù)存儲在模塊中
通過將函數(shù)存儲在獨立的文件中,可隱藏程序代碼的細節(jié),將重點放在程序的高層邏輯上。這還能讓你在眾多不同的程序中重用函數(shù)。將函數(shù)存儲在獨立文件后,可與其他程序員共享這些文件而不是整個函數(shù)。知道如何導入函數(shù)還能讓你使用其他程序員編寫的函數(shù)庫
導入整個模塊
要讓函數(shù)是可導入的,得先創(chuàng)建模塊。模塊是擴展名為.py得文件,包含要導入得程序中的代碼。下面來創(chuàng)建一個包含函數(shù)make_pizza()的模塊。
pizza.py
def make_pizza(size,*toppings):
"""概述要制作的披薩"""
print("\nMaking a " + str(size)+"-ich pizze with the following toppings:")
for toppings in toppings:
print("- " + topping)
接下來,我們只需要在新文件中通過import pizza即可調(diào)用這個文件里面的函數(shù):
import pizza
pizza.make_pizza(16,'pepperoni')
Python 讀這個文件時,代碼行import pizza讓Python打開文件pizza.py,并將其中的所有函數(shù)都復制到這個程序中。
導入特定的函數(shù)
from modle_name import function_name
通過用逗號分隔函數(shù)名,可根據(jù)需要從模塊中導入任意數(shù)量的函數(shù):
from modle_name import function_nam_e_1,function_name_2
使用as給函數(shù)指定別名
from pizza import make_pizza as mp
使用as給模塊指定別名
impost pizza as p
導入模塊中的所有函數(shù)
使用星號(*)運算符可讓Python導入模塊中的所有函數(shù):
from pizza import *
making_pizza(16,'pepperoni')
making_pizza(12,'mushrooms','green peppers','extra cheese')
import語句中的星號讓python將模塊pizza中的每個函數(shù)都復制到這個程序文件中。由于導入了每個函數(shù),可通過名稱來調(diào)用每個函數(shù),而無需使用句點表示法。然而并非自己編寫的大型模塊時,最好不要采用這種導入方法:如果模塊中有函數(shù)的名稱與你的項目中使用的名稱相同,可能導致意想不到的結果:Python可能遇到多個名稱相同的函數(shù)或變量,進而覆蓋函數(shù),而不是分別導入所有函數(shù)
最佳的做法是,要么導入你需要使用的函數(shù),要么導入整個模塊并使用句點表示法。讓代碼更清晰,更容易閱讀和理解。
函數(shù)編寫指南
應給函數(shù)指定描述性名稱,且只在其中使用小寫字母和下劃線。
每個函數(shù)都應包含簡要地闡述其功能地注釋,該注釋應該緊跟在函數(shù)定義后面。
其他程序員只要知道函數(shù)的名稱,需要的實參以及返回值的類型就能在自己的程序中使用它。