-bash
做者 | 弗拉德
來源 | 弗拉德(公衆號:fulade_me)ide
下面是一個打印問候語的簡單函數,名爲greet_user():函數
def greet_user(): """顯示簡單的問候語""" print("Hello!") greet_user()
這個示例演示了最簡單的函數結構。使用關鍵字def
來告訴Python你要定義一個
函數。在這裏,函數名爲greet_user()
,它不須要任何信息就能完成其工做,所以括號是空的(即使如此,括號也必不可少)。最後,定義以冒號結尾。測試
緊跟在def greet_user()
:後面的全部縮進行構成了函數體。代碼行print("Hello!"
)是函數體內的惟一一行代碼,greet_user()
只作一項工做:打印Hello!。 ui
因爲這個函數不須要任何參數,所以調用它時只需輸入greet_user()
便可。和預期的同樣,它打印Hello!
。code
只需稍做修改,就可讓函數greet_user()
不只向用戶顯示Hello!
,還將用戶的名字用做參數。 orm
所以,可在函數定義def greet_user()
的括號內添加username
。經過在這裏添加username
,就可以讓函數接受你給username
指定的任何值。如今,這個函數要求你調用它時給username
指定一個值。調用greet_user()
時,可將一個名字傳遞給它,以下所示:ci
def greet_user(username): """顯示簡單的問候語""" print("Hello, " + username.title() + "!") greet_user('Fulade')
代碼greet_user('Fulade')
調用函數greet_user()
,並向它提供執行print
語句所需的信息。這個函數接受你傳遞給它的名字,並向這我的發出問候:字符串
Hello Fulade !
一樣,greet_user('sarah')
調用函數greet_user()
並向它傳遞sarah
,打印Hello, Sarah!
。
你能夠根據須要調用函數greet_user()
任意次,調用時不管傳入什麼樣的名字,都會生成相應的輸出。get
前面定義函數greet_user()
時,要求給變量username
指定一個值。調用這個函數並提供這種參數,它將打印相應的問候語。
在函數greet_user()
的定義中,變量username
是一個形參——函數完成其工做所需的一項信息。在代碼greet_user('Fulade')
中,值Fulade
是一個實參。
實參是調用函數時傳遞給函數的信息。咱們調用函數時,將要讓函數使用的信息放在括號內。在greet_user('Fulade')
中,將實參Fulade
傳遞給了函數greet_user()
,這個值被存儲在形參username
中。
鑑於函數定義中可能包含多個形參,所以函數調用中也可能包含多個實參。向函數傳遞實參的方式不少,可以使用位置實參,這要求實參的順序與形參的順序相同;也可以使用關鍵字實參,其中每一個實參都由變量名和值組成;還可以使用列表和字典。下面來依次介紹這些方式。
你調用函數時,Python必須將函數調用中的每一個實參都關聯到函數定義中的一個形參。所以,最簡單的關聯方式是基於實參的順序。這種關聯方式被稱爲位置實參。爲明白其中的工做原理,來看一個顯示寵物信息的函數。這個函數指出一個寵物屬於哪一種動物以及它叫什麼名字,以下所示:
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')
這個函數的定義代表,它須要一種動物類型和一個名字。調用describe_pet()
時,須要按順序提供一種動物類型和一個名字。
例如,在前面的函數調用中,實參hamster
存儲在形參animal_type
中,而實參harry
存儲在形參pet_name
中。在函數體內,使用了這兩個形參來顯示寵物的信息。
你能夠根據須要調用函數任意次。要再描述一個寵物,只需再次調用describe_pet()
便可:
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') describe_pet('dog', 'willie')
第二次調用describe_pet()
函數時,咱們向它傳遞了實參dog
和willie
。與第一次調用時同樣,Python將實參dog
關聯到形參animal_type
,並將實參willie
關聯到形參pet_name
。
與前面同樣,這個函數完成其任務,但打印的是一條名爲Willie
的小狗的信息。至此,咱們有一隻名爲Harry
的倉鼠,還有一條名爲Willie
的小狗:
I have a hamster. My hamster's name is Harry. I have a dog. My dog's name is Willie.
調用函數屢次是一種效率極高的工做方式。咱們只需在函數中編寫描述寵物的代碼一次,而後每當須要描述新寵物時,均可調用這個函數,並向它提供新寵物的信息。即使描述寵物的代碼增長到了10行,你依然只需使用一行調用函數的代碼,就可描述一個新寵物。
在函數中,可根據須要使用任意數量的位置實參,Python將按順序將函數調用中的實參關聯到函數定義中相應的形參。
使用位置實參來調用函數時,若是實參的順序不正確,結果可能出乎意料:
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('harry', 'hamster')
在這個函數調用中,咱們先指定名字,再指定動物類型。因爲實參harry
在前,這個值將存儲到形參animal_type
中;同理,hamster
將存儲到形參pet_name
中。結果是咱們獲得了一個名爲Hamster
的harry
:
I have a harry. My harry's name is Hamster.
若是結果像上面同樣搞笑,請確認函數調用中實參的順序與函數定義中形參的順序一致。
關鍵字實參是傳遞給函數的名稱—值對。你直接在實參中將名稱和值關聯起來了,所以向函數傳遞實參時不會混淆。
關鍵字實參讓你無需考慮函數調用中的實參順序,還清楚地指出了函數調用中各個值的用途。下面來從新編寫pets.py
,在其中使用關鍵字實參來調用describe_pet()
:
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')
函數describe_pet()
仍是原來那樣,但調用這個函數時,咱們向Python明確地指出了各個實參對應的形參。看到這個函數調用時,Python知道應該將實參hamster
和harry
分別存儲在形參animal_type
和pet_name
中。輸出正確無誤,它指出咱們有一隻名爲Harry
的倉鼠。
關鍵字實參的順序可有可無,由於Python知道各個值該存儲到哪一個形參中。下面兩個函數調用是等效的:
describe_pet(animal_type='hamster', pet_name='harry') describe_pet(pet_name='harry', animal_type='hamster')
編寫函數時,可給每一個形參指定默認值。在調用函數中給形參提供了實參時,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')
這裏修改了函數describe_pet()
的定義,在其中給形參animal_type
指定了默認值dog
。這樣,調用這個函數時,若是沒有給animal_type
指定值,Python將把這個形參設置爲dog
:
I have a dog. My dog's name is Willie.
請注意,在這個函數的定義中,修改了形參的排列順序。因爲給animal_type
指定了默認值,無需經過實參來指定動物類型,所以在函數調用中只包含一個實參——寵物的名字。然而,Python依然將這個實參視爲位置實參,所以若是函數調用中只包含寵物的名字,這個實參將關聯到函數定義中的第一個形參。這就是須要將pet_name放在形參列表開頭的緣由所在。
如今,使用這個函數的最簡單的方式是,在函數調用中只提供小狗的名字:
describe_pet('willie')
這個函數調用的輸出與前一個示例相同。只提供了一個實參——willie
,這個實參將關聯到函數定義中的第一個形參——pet_name
。因爲沒有給animal_type
提供實參,所以Python使用其默認值dog
。
若是要描述的動物不是小狗,可以使用相似於下面的函數調用:
describe_pet(pet_name='harry', animal_type='hamster')
因爲顯式地給animal_type
提供了實參,所以Python將忽略這個形參的默認值。
因爲可混合使用位置實參、關鍵字實參和默認值,一般有多種等效的函數調用方式。請看下
面的函數describe_pets()
的定義,其中給一個形參提供了默認值:
def describe_pet(pet_name, animal_type='dog'):
基於這種定義,在任何狀況下都必須給pet_name
提供實參;指定該實參時可使用位置方式,也可使用關鍵字方式。若是要描述的動物不是小狗,還必須在函數調用中給animal_type
提供實參;一樣,指定該實參時可使用位置方式,也可使用關鍵字方式。
下面對這個函數的全部調用均可行:
# 一條名爲Willie的小狗 describe_pet('willie') describe_pet(pet_name='willie') # 一隻名爲Harry的倉鼠 describe_pet('harry', 'hamster') describe_pet(pet_name='harry', animal_type='hamster') describe_pet(animal_type='hamster', pet_name='harry')
這些函數調用的輸出與前面的示例相同。
等你開始使用函數後,若是遇到實參不匹配錯誤,不要大驚小怪。你提供的實參多於或少於函數完成其工做所需的信息時,將出現實參不匹配錯誤。
例如,若是調用函數describe_pet()
時沒有指定任何實參,結果將如何呢?
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()
Python發現該函數調用缺乏必要的信息,而traceback
指出了這一點:
Traceback (most recent call last): File "pets.py", line 6, in <module> describe_pet() TypeError: describe_pet() missing 2 required positional arguments: 'animal_ type' and 'pet_name'
函數並不是老是直接顯示輸出,相反,它能夠處理一些數據,並返回一個或一組值。函數返回的值被稱爲返回值。在函數中,可以使用return
語句將值返回到調用函數的代碼行。返回值讓你可以將程序的大部分繁重工做移到函數中去完成,從而簡化主程序。
下面來看一個函數,它接受名和姓並返回姓名:
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)
函數get_formatted_name()
的定義經過形參接受名和姓。它將姓和名合而爲一,在它們之間加上一個空格,並將結果存儲在變量full_name
中。而後,將full_name
的值轉換爲首字母大寫格式,並將結果返回到函數調用行。調用返回值的函數時,須要提供一個變量,用於存儲返回的值。
在這裏,將返回值存儲在了變量musician
中。輸出是姓名:
Jimi Hendrix
有時候,須要讓實參變成可選的,這樣使用函數的人就只需在必要時才提供額外的信息。可以使用默認值來讓實參變成可選的。
例如,假設咱們要擴展函數get_formatted_name()
,使其還處理中間名。爲此,可將其修改爲相似於下面這樣:
def get_formatted_name(first_name, middle_name, last_name): """返回姓名""" full_name = first_name + ' ' + middle_name + ' ' + last_name return full_name.title() musician = get_formatted_name('john', 'lee', 'hooker') print(musician)
只要同時提供名、中間名和姓,這個函數就能正確地運行。它根據這三部分建立一個字符串,在適當的地方加上空格,並將結果轉換爲首字母大寫格式:
John Lee Hooker
然而,並不是全部的人都有中間名,但若是你調用這個函數時只提供了名和姓,它將不能正確地運行。爲讓中間名變成可選的,可給實參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() musician = get_formatted_name('jimi', 'hendrix') print(musician) musician = get_formatted_name('john', 'hooker', 'lee') print(musician)
在這個示例中,姓名是根據三個可能提供的部分建立的。因爲人都有名和姓,所以在函數定義中首先列出了這兩個形參。中間名是可選的,所以在函數定義中最後列出該形參,並將其默認值設置爲空字符串。
在函數體中,咱們檢查是否提供了中間名。Python將非空字符串解讀爲True,所以若是函數調用中提供了中間名,if middle_name
將爲True
。若是提供了中間名,就將名、中間名和姓合併爲姓名,而後將其修改成首字母大寫格式,並返回到函數調用行。
在函數調用行,將返回的值存儲在變量musician
中;而後將這個變量的值打印出來。若是沒有提供中間名,middle_name
將爲空字符串,致使if
測試未經過,進而執行else
代碼塊:只使用名和姓來生成姓名,並將設置好格式的姓名返回給函數調用行。
在函數調用行,將返回的值存儲在變量musician
中;而後將這個變量的值打印出來。調用這個函數時,若是隻想指定名和姓,調用起來將很是簡單。若是還要指定中間名,就必須確保它是最後一個實參,這樣Python才能正確地將位置實參關聯到形參。
這個修改後的版本適用於只有名和姓的人,也適用於還有中間名的人:
Jimi Hendrix John Lee Hooker
可選值讓函數可以處理各類不一樣情形的同時,確保函數調用盡量簡單。
本篇文章沒有做業,下一篇咱們講解函數的高級用法