終于要開始學函數了,以前學到的所有相關知識都可以在函數中得到應用,要執行函數定義的特定任務,那麼隻需調用函數即可。
1.從例子開始學起
1.1定義函數
在Python中,函數如何定義呢?通過def關鍵字定義函數。例如:
# define a function
def desc_info():
"""函數的文檔注釋"""
print('This is a function')
#調用函數
desc_info()
上面這個例子定義了一個desc_info函數,這個函數的主要功能是列印一句話。這裡要注意幾點。
- 函數的命名,要見名知意。一個好的函數命名,勝過詳細的文檔描述。
- 文檔注釋不可少,函數體的文檔注釋,通過三對雙引号定義,文檔隻是起到函數功能說明。
- 函數的代碼行長度不能太長,一般不超過79字元。
- 冒号不能少,這個是格式問題,記住便可。
1.2函數傳遞參數
1)先舉個例子
# 定義一個可以傳參數的函數
def desc_human(name,animal):
"""列印輸出"""
print(f"{name.title()} love {animal}")
#通過傳參調用函數
desc_human('max','cat')
desc_human('jack','fish')
上面定義了一個desc_human函數,其包含兩個參數,被稱作形參,反正了解就行,不必深究概念。
2)實參和形參
就像上面的例子,name,animal就是形參,而調用函數的時候,指派的‘max’,'cat’就是實參。
2.函數傳遞實參
2.1位置參數
通過上面的例子,我們知道了函數是怎麼傳遞參數的,這裡就看下什麼是位置參數。
其實上面兩個參數的函數desc_human,已經能很好的說明位置參數,這裡主要強調兩點:
- 傳參的時候注意下位置順序,否則容易出錯。
- 可以進行多次調用。
2.2關鍵字實參
關鍵字實參就是傳遞參數的時候,按照名稱對的形式傳遞。這樣将名稱和值關聯起來,就不容易造成混淆了。
def desc_human(name,animal):
print(f"{name.title()} love {animal}")
#通過關鍵字實參調用函數
desc_human(name='john',animal='bird')
2.3預設值
編寫函數的時候,可以給形參指定預設值,這樣,在調用的時候,如果該形參不指定實參就通過預設值作為實參。
def desc_human(name,animal = 'dog'):
print(f"{name.title()} love {animal}")
#調用函數,僅指派name
desc_human('wow')
2.4傳遞清單
前面都是學習的都是傳遞簡單的參數,現在學習向函數傳遞清單,參數傳遞的原理都是一樣的,無論傳遞什麼樣的參數,都是為了處理相關資料。
def greet_users(names):
"""傳遞清單參數進行處理"""
for name in names:
msg = f"{name} is a student"
print(msg)
#調用函數,傳入清單即可
greet_users(['max','jack','john'])
在來看一個清單遷移的例子,感受下稍微複雜的程式設計。
def print_models(unprint_designs,completed_designs):
"""清單資料的遷移"""
while unprint_designs:
design = unprint_designs.pop()
print(f"Current print design is {design}")
completed_designs.append(design)
def show_complete_design(completed_designs):
"""列印遷移後的清單資料"""
print(f"\nThe following model have been printed")
for comp in completed_designs:
print(comp)
#定義兩個清單,一個遷出清單,一個遷入清單
unprint_designs = ['python language','java language','php language']
completed_designs = []
#調用函數進行清單遷移
print_models(unprint_designs,completed_designs)
show_complete_design(completed_designs)
上面這個例子稍微複雜一點,主要功能是進行清單資料的遷移,将清單unprint_designs的資料,遷移到清單completed_designs中來,然後進行列印。涉及到兩個函數,一個進行遷移,一個進行列印。
有時候,可能需要禁止函數修改清單,比如,清單unprint_designs裡面的資料不能修改或者删除,然後還要遷移到另一個清單中。這個時候,就要使用到前面所學的清單副本的方式來進行。
#調用的時候傳入清單的副本即可
print_models(unprint_designs[:],completed_designs)
2.5傳遞任意數量的實參
先來看個比較簡單的例子。
def make_cake(*toppings):
"""列印參數"""
print(toppings)
#調用函數的時候,可以傳入任意數量的參數
make_cake('penddle')
make_cake('mushrooms','green pappers','extra cheese')
上面的函數隻有一個形參,*toppings可以接收任意數量的參數。*toppings中的星号會讓Python建立一個名為toppings的空元組,并将接收到的所有值都組裝在這個元組中。
在來看一個稍微複雜點的函數,并說明關鍵字實參的用法。
def build_profile(first,last,**user_info):
"""建構字典"""
user_info['first_name'] = first
user_info['last_name'] = last
return user_info
#調用函數,并使用關鍵字實參
user_profile = build_profile('feng','max',location = 'hangzhou',hobby = 'reading')
print(user_profile)
上面這個函數的作用就是通過輸入的前兩個參數,建構後一個參數。形參**user_info中的兩個星号讓Python建立一個名為user_info的空字典,并将收到的所有名稱值對都放到空字典中。在上面,不僅傳遞了
'feng','max'
,同時還傳遞了兩個鍵值對
location = 'hangzhou',hobby = 'reading'
,這兩個鍵值對也會放到這個字典中。
3.函數傳回值
3.1簡單的傳回值
def get_full_name(first_name,last_name):
"""拼接全名并傳回"""
full_name = f"{first_name} {last_name}"
return full_name.title()
#調用函數,通過變量接收函數傳回值
full_name = get_full_name('xing','zhe')
print(full_name)
上面這個函數get_full_name的主要功能是進行兩個參數的拼接,然後格式化傳回。當調用函數的時候,用一個變量接收即可擷取函數的傳回值。
往往有些函數可能需要一些可選參數,就那上面的例子來說,可能有些人的名字是三個,是以可能需要指定一個預設參數,這個預設參數,可以在調用的時候不用傳實參。
def get_full_name(first_name,last_name,middle_name = ''):
"""帶預設參數的處理"""
if middle_name:
full_name = f"{first_name} {middle_name} {last_name}"
else:
full_name = f"{first_name} {last_name}"
return full_name.title()
full_name = get_full_name('sun','wu','kong')
print(full_name)
3.2傳回字典
其實函數可以傳回任何類型的值,字元串,數字,清單,字典等都可以,也可能包含更為複雜的資料結構,清單字典,或者字典清單。
def build_person(first_name,last_name):
"""建構一個person字典"""
person = {'first' : first_name,'last' : last_name}
return person
#調用函數
person = build_person('ke','le')
print(person)
同時也可以指定可選形參,并将其預設值設定為特殊值None(這個None表示變量沒有值),可将其視為占位符,在條件測試中None就相當于false。
def build_person(first_name,last_name,age = None):
"""帶可選參數的建構方式"""
person = {'first' : first_name,'last' : last_name}
if age:
person['age'] = age
return person
#調用函數
person = build_person('ma','xi',6)
print(person)
4.子產品中的函數
4.1導入整個子產品
我們不僅可以通過函數将代碼塊和主程式分離,同時也可以通過将函數存儲在成為子產品的獨立檔案中。再将子產品導入到主程式中進行使用。
直接看例子吧,比較直覺。
先建立一個名為pizza.py的檔案,其内容如下:
def make_pizza(size, *toppings):
"""制作皮薩的概述"""
print(f"\nMaking a {size}-inch pizza with the following toppings:")
for topping in toppings:
print(f"- {topping}")
然後在同一目錄下建立making_pizza.py的檔案,内容如下:
#導入剛才建立的pizza子產品
import pizza
#調用子產品中的函數
pizza.make_pizza(16,'pepperoni')
pizza.make_pizza(18,'mushroom','green_peppers','extra cheese')
Python讀取這個making_pizza.py檔案的時候,代碼行
import pizza
,會讓Python打開檔案pizza.py,并将其所有的函數都複制到這個程式中。我們是看不到這個過程,但是程式運作的時候背景已經幫我們幹了。可以在解釋器或者IDE中運作making_pizza.py看看結果。
$ python3 making_pizza.py
Making a 16-inch pizza with the following toppings:
- pepperoni
Making a 18-inch pizza with the following toppings:
- mushroom
- green_peppers
- extra cheese
4.2導入特定的函數
有時候,我們往往不需要将整個子產品導入進來,也可以按需導入,導入我們需要的特定函數即可。導入的文法:
from module_name import function_name
from module_name import function_name_1,function_name_2,function_name_3
例如上面的制作批薩的例子,我們就可以隻導入make_pizza函數就可以了。
#導入剛才建立的pizza子產品中的make_pizza
from pizza import make_pizza
#直接調用函數
make_pizza(16,'pepperoni')
make_pizza(18,'mushroom','green_peppers','extra cheese')
4.3給函數或者子產品指定别名
如果導入的子產品名稱,和我們自己定義的子產品名稱沖突,或者導入的子產品名稱太長了,那麼我們在導入的時候,可以通過
as
給導入的子產品指定别名,類似于外号一樣。
1)給函數指定别名
#導入剛才建立的pizza子產品中的make_pizza并指定别名 mp
from pizza import make_pizza as mp
#通過mp調用函數
mp(16,'pepperoni')
mp(18,'mushroom','green_peppers','extra cheese')
2)給子產品指定别名
#導入建立的pizza子產品并指定p别名
import pizza as p
#通過p調用子產品中的函數
p.make_pizza(16,'pepperoni')
p.make_pizza(18,'mushroom','green_peppers','extra cheese')
3)導入子產品中所有函數(特别不推薦)
使用星号(*)運算符可以讓Python導入子產品中的所有函數:
#導入建立的pizza子產品并指定p别名
from pizza import *
#通過p調用子產品中的函數
make_pizza(16,'pepperoni')
make_pizza(18,'mushroom','green_peppers','extra cheese')
因為導入了所有的函數,可能會和我們自己定義的變量或者函數命名沖突,進而引起意想不到的錯誤結果。