如何在Python 3中定义函数

介紹

A function is a block of instructions that performs an action and, once defined, can be reused. Functions make code more modular, allowing you to use the same code over and over again.

Python具有一些內置函數,您可能熟悉其中一些,包括:

  • print()將對象打印到終端
  • int()將字符串或數字數據類型轉換為整數數據類型
  • len()返回對象的長度

函數名包括括號,並且可能包括參數。

在本教程中,我們將介紹如何定義自己的函數以在編碼項目中使用。

先決條件

您應該已經安裝了Python 3並在您的計算機或服務器上設置了編程環境。如果您尚未設置編程環境,可以參考安裝和設置指南:本地編程環境或者適用於您操作系統的服務器上的編程環境(Ubuntu、CentOS、Debian等)。

定義函數

讓我們從將經典的“Hello, World!”程式轉換為一個函數開始。

我們將在我們喜歡的文字編輯器中建立一個新的文字檔,並將程式命名為hello.py。然後,我們將定義函數。

A function is defined by using the def keyword, followed by a name of your choosing, followed by a set of parentheses which hold any parameters the function will take (they can be empty), and ending with a colon.

資訊:要按照本教程中的示例代碼進行操作,請在您的本地系統上運行python3命令以打開Python交互式殼層。然後,您可以通過在>>>提示之後添加、複製或編輯示例來進行操作。

在這種情況下,我們將定義一個名為hello()的函數:

hello.py
def hello():

這為創建函數的初始語句。

從這裡,我們將添加一個縮進4個空格的第二行,以提供函數執行的指示。在這種情況下,我們將打印Hello, World!到控制台:

hello.py
def hello():
    print("Hello, World!")

我們的函數現在已完全定義,但如果在這一點上運行程式,將不會發生任何事情,因為我們沒有調用函數。

因此,在我們定義的函數區塊之外,讓我們使用hello()調用函數:

hello.py
def hello():
    print("Hello, World!")

hello()

現在,讓我們運行程式:

  1. python hello.py

您應該收到以下輸出:

Output
Hello, World!

函數可能比我們上面定義的 hello() 函數更複雜。例如,我們可以在函數塊中使用 for 迴圈條件語句,以及更多其他功能。

例如,下面定義的函數利用條件語句檢查 name 變量的輸入是否包含元音,然後使用 for 迴圈遍歷 name 字串。

names.py
# 定義函數 names()
def names():
    # 設置帶有輸入的 name 變量
    name = str(input('Enter your name: '))
    # 檢查 name 是否有元音
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')

    # 遍歷 name
    for letter in name:
        print(letter)

# 調用函數
names()

我們上面定義的 names() 函數設置了一個條件語句和一個 for 迴圈,展示了在函數定義中如何組織代碼。然而,根據我們對程序意圖的理解以及我們希望如何設置代碼,我們可能希望將條件語句和 for 迴圈定義為兩個獨立的函數。

在程序中定義函數使我們的代碼具有模塊化和可重用性,這樣我們可以在不重寫它們的情況下調用相同的函數。

使用參數

到目前為止,我們已經看過使用空括號的函數,不帶任何參數,但我們可以在函數定義中的括號內定義參數。

A parameter is a named entity in a function definition, specifying an argument that the function can accept.

讓我們創建一個小程序,接受參數 xyz。我們將創建一個函數,以不同的配置將參數相加。這些和將由函數打印出來。然後我們將調用該函數並將數字傳遞給函數。

add_numbers.py
def add_numbers(x, y, z):
    a = x + y
    b = x + z
    c = y + z
    print(a, b, c)

add_numbers(1, 2, 3)

我們將數字 1 傳遞給參數 x,將數字 2 傳遞給參數 y,將數字 3 傳遞給參數 z。這些值與它們給出的順序中的每個參數相對應。

該程序基本上根據我們傳遞給參數的值進行以下數學運算:

a = 1 + 2
b = 1 + 3
c = 2 + 3

該函數還打印出 abc,根據上面的數學,我們期望 a 等於 3b4c5。讓我們運行該程序:

  1. python add_numbers.py
Output
3 4 5

當我們將數字 123 作為參數傳遞給 add_numbers() 函數時,我們會收到預期的輸出。

參數是通常在函數定義中定義為變量的參數。當您運行方法時,可以將值分配給它們,將這些參數傳遞給函數。

關鍵字參數

除了按順序調用參數外,您還可以在函數調用中使用關鍵字參數,在其中調用者通過參數名稱識別參數。

使用關鍵字參數時,可以無需按順序使用參數,因為Python解釋器將使用提供的關鍵字將值與參數匹配。

讓我們創建一個函數,它將顯示用戶的檔案信息。我們將以username(預期為字符串)和followers(預期為整數)的形式傳遞參數給它。

profile.py
# 定義帶有參數的函數
def profile_info(username, followers):
    print("Username: " + username)
    print("Followers: " + str(followers))

在函數定義語句中,usernamefollowers包含在profile_info()函數的括號中。該函數的代碼塊將用戶信息作為字符串打印出來,利用了這兩個參數。

現在,我們可以調用該函數並為其分配參數:

profile.py
def profile_info(username, followers):
    print("Username: " + username)
    print("Followers: " + str(followers))

# 使用上述分配的參數調用函數
profile_info("sammyshark", 945)

# 使用關鍵字參數調用函數
profile_info(username="AlexAnglerfish", followers=342)

在第一個函數呼叫中,我們填入了使用者名稱為sammyshark,追隨者為945的資訊,在第二個函數呼叫中,我們使用了關鍵字參數,將值分配給參數變數。

讓我們執行這個程式:

  1. python profile.py
Output
Username: sammyshark Followers: 945 Username: AlexAnglerfish Followers: 342

輸出顯示了兩個使用者的使用者名稱和追隨者數量。

這也允許我們修改參數的順序,就像這個例子中相同程式的不同呼叫一樣:

profile.py
def profile_info(username, followers):
    print("Username: " + username)
    print("Followers: " + str(followers))

# 修改參數的順序
profile_info(followers=820, username="cameron-catfish")

當我們再次使用python profile.py命令執行程式時,我們將獲得以下輸出:

Output
Username: cameron-catfish Followers: 820

因為函數定義保持了print()語句的相同順序,如果我們使用關鍵字參數,我們將它們傳遞到函數呼叫中的順序並不重要。

預設參數值

我們還可以為一個或兩個參數提供默認值。讓我們為followers參數創建一個默認值,值為1

profile.py
def profile_info(username, followers=1):
    print("Username: " + username)
    print("Followers: " + str(followers))

現在,我們可以只使用分配給使用者名稱的函數,追隨者數量將自動默認為1。如果需要,我們仍然可以更改追隨者數量。

profile.py
def profile_info(username, followers=1):
    print("Username: " + username)
    print("Followers: " + str(followers))

profile_info(username="JOctopus")
profile_info(username="sammyshark", followers=945)

當我們使用python profile.py命令執行程式時,將獲得以下輸出:

Output
Username: JOctopus Followers: 1 Username: sammyshark Followers: 945

提供帶有值的默認參數可以讓我們跳過為每個已有默認值的參數定義值。

返回值

您可以將參數值傳遞給函數,函數也可以生成一個值。

A function can produce a value with the return statement, which will exit a function and optionally pass an expression back to the caller. If you use a return statement with no arguments, the function will return None.

到目前為止,我們已經在函數中使用了print()語句,而不是return語句。讓我們創建一個程序,該程序將返回一個變量,而不是打印它。

在一個名為square.py的新文本文件中,我們將創建一個程序,該程序對參數x進行平方並返回變量y。我們通過將3傳遞給它來運行square()函數,並發出對result變量的打印調用。

square.py
def square(x):
    y = x ** 2
    return y

result = square(3)
print(result)

我們可以運行該程序並獲得輸出:

  1. python square.py
Output
9

返回整數9作為輸出,這是我們通過請求Python找到3的平方所期望的結果。

為了進一步理解return語句的工作原理,我們可以將程序中的return語句註釋掉:

square.py
def square(x):
    y = x ** 2
    # return y

result = square(3)
print(result)

現在,讓我們再次運行該程序:

  1. python square.py
Output
None

在這裡不使用return語句,該程序無法返回一個值,因此該值默認為None

作為另一個例子,在上述的add_numbers.py程式中,我們可以將print()語句替換為return語句。

add_numbers.py
def add_numbers(x, y, z):
    a = x + y
    b = x + z
    c = y + z
    return a, b, c

sums = add_numbers(1, 2, 3)
print(sums)

在函數外部,我們將變數sums設置為調用函數時帶入123所得到的結果,然後我們調用了sums變量的打印。

現在讓我們再次運行這個程式,因為它現在具有return語句:

  1. python add_numbers.py
Output
(3, 4, 5)

我們收到了與之前使用print()語句在函數中收到的相同的數字345作為輸出。這次它作為一個元組返回,因為return語句的表達式列表至少有一個逗號。

函數在遇到return語句時立即退出,無論它們是否返回一個值。

return_loop.py
def loop_five():
    for x in range(0, 25):
        print(x)
        if x == 5:
            # 在 x == 5 時停止函數
            return
    print("This line will not execute.")

loop_five()

for循環內使用return語句會結束函數,因此循環外的那一行將不會運行。如果我們改用break語句,則只有在那時循環才會退出,並且最後的print()行會運行。

return語句退出一個函數,在帶有參數的情況下可能返回一個值。

main()用作函數

儘管在Python中,您可以在程序底部調用函數並運行它(就像我們在上面的示例中所做的那樣),但許多編程語言(如C++和Java)需要一個main函數才能執行。包括一個main()函數,雖然不是必需的,但可以以一種將程序的最重要組件放入一個函數的邏輯方式來結構化我們的Python程序。這還可以使我們的程序更容易讓非Python程序員閱讀。

我們將從在上面的hello.py程序中添加一個main()函數開始。我們將保留我們的hello()函數,然後定義一個main()函數:

hello.py
def hello():
    print("Hello, World!")

def main():

main()函數內部,讓我們包括一個print()語句,以便讓我們知道我們在main()函數中。此外,讓我們在main()函數中調用hello()函數:

hello.py
def hello():
    print("Hello, World!")


def main():
    print("This is the main function")
    hello()

最後,在程序底部我們將調用main()函數:

hello.py
def hello():
    print("Hello, World!")

def main():
    print("This is the main function.")
    hello()

main()

此時,我們可以運行我們的程序:

  1. python hello.py

我們將收到以下輸出:

Output
This is the main function. Hello, World!

因為我們在main()內部調用了hello()函數,然後只調用了main()來運行,所以Hello, World!文本只打印了一次,在告訴我們我們在主函數中的字符串之後。

接下來,我們將使用多個函數,因此值得回顧全局和局部變量的變量範圍。如果在函數塊內定義變量,則只能在該函數內使用該變量。如果想要跨函數使用變量,最好聲明一個全局變量。

在Python中,'__main__'是頂層代碼將執行的範圍名稱。當從標準輸入、腳本或交互式提示運行程序時,它的__name__被設置為'__main__'

因為這個原因,有一個慣例使用以下結構:

if __name__ == '__main__':
    # 當這是主要程序時運行的代碼在這裡

這允許程序文件被用作:

  • 作為主程序運行後面的if語句
  • 作為模塊而不運行後面的if語句。

不包含在此語句中的任何代碼將在運行時執行。如果將程序文件用作模塊,則不在此語句中的代碼在運行次要文件時也將被執行。

讓我們擴展上面的names.py程式,並創建一個名為more_names.py的新文件。在這個程式中,我們將宣告一個全域變量,並修改我們原來的names()函數,使指令分為兩個獨立的函數。

第一個函數has_vowel()將檢查name字符串是否包含元音字母。

第二個函數print_letters()將打印name字符串的每個字母。

more_names.py
# 宣告全域變量 name 以在所有函數中使用
name = str(input('Enter your name: '))


# 定義函數以檢查名字是否包含元音字母
def has_vowel():
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')


# 迭代名字字符串中的每個字母
def print_letters():
    for letter in name:
        print(letter)

有了這個設置,讓我們定義main()函數,其中將包含對has_vowel()print_letters()函數的調用。

more_names.py
# 宣告全域變量 name 以在所有函數中使用
name = str(input('Enter your name: '))


# 定義函數以檢查名字是否包含元音字母
def has_vowel():
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')


# 迭代名字字符串中的每個字母
def print_letters():
    for letter in name:
        print(letter)


# 定義調用其他函數的主要方法
def main():
    has_vowel()
    print_letters()

最後,我們會在文件底部添加if __name__ == '__main__':構造。對於我們的目的,由於我們已經將所有想要在main()函數中執行的功能放入其中,我們將在此if語句後調用main()函數。

more_names.py
# 声明全局变量名称以在所有函数中使用
name = str(input('Enter your name: '))


# 定义函数以检查名称是否包含元音
def has_vowel():
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')


# 遍历名称字符串中的字母
def print_letters():
    for letter in name:
        print(letter)


# 定义调用其他函数的主方法
def main():
    has_vowel()
    print_letters()


# 执行 main() 函数
if __name__ == '__main__':
    main()

現在我們可以運行程序:

  1. python more_names.py

該程序將顯示與names.py程序相同的輸出,但是這裡的代碼更有組織性,可以在不修改的情況下以模塊化方式使用。

如果您不想聲明main()函數,您也可以像這樣結束程序:

more_names.py
...
if __name__ == '__main__':
    has_vowel()
    print_letters()

使用main()作為函數和if __name__ == '__main__':語句可以以邏輯方式組織代碼,使其更具可讀性和模塊化。

結論

函數是程序中執行操作的代碼塊,有助於使我們的代碼可重用和模塊化。

要了解如何使您的代碼更模塊化,您可以閱讀我們關於如何在Python 3中編寫模塊的指南。

Source:
https://www.digitalocean.com/community/tutorials/how-to-define-functions-in-python-3