Python - 函式



Python 函式是一塊組織好的、可重用的程式碼塊,用於執行單個相關的操作。函式為您的應用程式提供了更好的模組化和高度的程式碼重用。

構建處理邏輯的自頂向下方法涉及定義獨立的可重用函式塊。可以透過傳遞所需資料(稱為引數實參)從任何其他函式呼叫 Python 函式。被呼叫的函式將其結果返回到呼叫環境。

python functions

Python 函式型別

Python 提供以下型別的函式:

序號 型別 & 描述
1

內建函式

Python 的標準庫包含許多內建函式。一些 Python 的內建函式有 print()、int()、len()、sum() 等。這些函式始終可用,因為它們在您啟動 Python 直譯器時就會載入到計算機的記憶體中。

2

內建模組中定義的函式

標準庫還捆綁了許多模組。每個模組都定義了一組函式。這些函式並非隨時可用。您需要從其各自的模組匯入它們到記憶體中。

3

使用者定義函式

除了內建函式和內建模組中的函式外,您還可以建立自己的函式。這些函式稱為使用者定義函式。

定義 Python 函式

您可以定義自定義函式以提供所需的功能。以下是定義 Python 函式的一些簡單規則:

  • 函式塊以關鍵字 def 開頭,後跟函式名稱和括號 ()。

  • 任何輸入引數或實參都應放在這些括號內。您也可以在這些括號內定義引數。

  • 函式的第一條語句可以是可選語句;函式的文件字串或文件字串。

  • 每個函式內的程式碼塊以冒號 (:) 開頭並縮排。

  • 語句 return [expression] 退出函式,可以選擇將表示式傳回給呼叫方。沒有引數的 return 語句與 return None 相同。

定義 Python 函式的語法

def function_name( parameters ):
   "function_docstring"
   function_suite
   return [expression]

預設情況下,引數具有位置行為,您需要按其定義的順序告知它們。

定義函式後,您可以透過從另一個函式或直接從 Python 提示符呼叫它來執行它。

定義 Python 函式的示例

以下示例演示如何定義函式 greetings()。括號為空,因此沒有任何引數。這裡,第一行是文件字串,函式塊以 return 語句結束。

def greetings():
   "This is docstring of greetings function"
   print ("Hello World")
   return

呼叫此函式時,將列印 Hello world 訊息。

呼叫 Python 函式

定義函式只會賦予它一個名稱,指定要包含在函式中的引數並構造程式碼塊。一旦函式的基本結構確定,您就可以使用函式名稱本身來呼叫它。如果函式需要任何引數,則應將它們放在括號內。如果函式不需要任何引數,則應將括號留空。

呼叫 Python 函式的示例

下面是呼叫 printme() 函式的示例:

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print (str)
   return;

# Now you can call the function
printme("I'm first call to user defined function!")
printme("Again second call to the same function")

當執行上述程式碼時,會產生以下輸出:

I'm first call to user defined function!
Again second call to the same function

傳值與傳引用

在像 C 和 C++ 這樣的程式語言中,將變數傳遞給函式主要有兩種方式,分別是 傳值呼叫傳引用呼叫(也稱為按引用傳遞和按值傳遞)。但是,我們在 Python 中將變數傳遞給函式的方式與其他語言不同。

  • 傳值呼叫 - 當呼叫函式時將 變數 傳遞給函式時,實際引數的值會被複制到表示形式引數的變數中。因此,形式引數的任何更改都不會反映到實際引數中。這種傳遞變數的方式稱為傳值呼叫。

  • 傳引用呼叫 - 在這種傳遞變數的方式中,會傳遞對記憶體中物件的引用。形式引數和實際引數(呼叫程式碼中的變數)都引用同一個物件。因此,形式引數的任何更改都會反映到實際引數中。

Pass By Reference Vs Value

Python 使用傳引用機制。由於 Python 中的變數是記憶體中物件的標籤或引用,因此用作實際引數和形式引數的變數實際上都引用記憶體中的同一個物件。我們可以透過檢查傳遞變數的 id() 在傳遞前後是否相同來驗證這一事實。

示例

在下面的示例中,我們正在檢查變數的 id()。

def testfunction(arg):
   print ("ID inside the function:", id(arg))

var = "Hello"
print ("ID before passing:", id(var))
testfunction(var)

如果執行上述程式碼,則會顯示傳遞之前和函式內部的 id()。

ID before passing: 1996838294128
ID inside the function: 1996838294128

這種行為還取決於傳遞的物件是可變的還是不可變的。Python 數值物件是不可變的。當傳遞數值物件,然後函式更改形式引數的值時,它實際上會在記憶體中建立一個新物件,而原始變數保持不變。

示例

以下示例顯示了不可變物件在傳遞給函式時的行為。

def testfunction(arg):
   print ("ID inside the function:", id(arg))
   arg = arg + 1
   print ("new object after increment", arg, id(arg))

var=10
print ("ID before passing:", id(var))
testfunction(var)
print ("value after function call", var)

它將產生以下輸出

ID before passing: 140719550297160
ID inside the function: 140719550297160
new object after increment 11 140719550297192
value after function call 10

現在讓我們將可變物件(例如列表或字典)傳遞給函式。它也是按引用傳遞的,因為列表在傳遞之前和之後的 id() 是相同的。但是,如果我們在函式內部修改列表,則其全域性表示也會反映出更改。

示例

這裡我們傳遞一個列表,追加一個新專案,並檢視原始列表物件的內容,我們會發現它已經改變了。

def testfunction(arg):
   print ("Inside function:",arg)
   print ("ID inside the function:", id(arg))
   arg=arg.append(100)
   
var=[10, 20, 30, 40]
print ("ID before passing:", id(var))
testfunction(var)
print ("list after function call", var)

它將產生以下輸出

ID before passing: 2716006372544
Inside function: [10, 20, 30, 40]
ID inside the function: 2716006372544
list after function call [10, 20, 30, 40, 100]

Python 函式引數

函式引數是在呼叫函式時傳遞給函式的值或變數。函式的行為通常取決於傳遞給它的引數。

在定義函式時,您會在括號內指定一個變數列表(稱為形式引數)。這些引數充當將傳遞給函式的資料的佔位符,當函式被呼叫時。當函式被呼叫時,必須為每個形式引數提供值。這些稱為實際引數。

function arguments

示例

讓我們修改 greetings 函式,並將其名稱作為引數。作為實際引數傳遞給函式的字串在函式內部成為 name 變數。

def greetings(name):
   "This is docstring of greetings function"
   print ("Hello {}".format(name))
   return
   
greetings("Samay")
greetings("Pratima")
greetings("Steven")

此程式碼將產生以下輸出:

Hello Samay
Hello Pratima
Hello Steven

Python 函式引數的型別

根據在定義 Python 函式時引數的宣告方式,它們被分為以下幾類:

位置引數或必選引數

必選引數是按正確的順序傳遞給函式的引數。這裡,函式呼叫中的引數數量必須與函式定義完全匹配,否則程式碼會報錯。

示例

在下面的程式碼中,我們呼叫函式 printme() 沒有任何引數,這會導致錯誤。

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print (str)
   return;

# Now you can call printme function
printme()

當執行上述程式碼時,會產生以下結果:

Traceback (most recent call last):
   File "test.py", line 11, in <module>
      printme();
TypeError: printme() takes exactly 1 argument (0 given)

關鍵字引數

關鍵字引數與函式呼叫相關。當您在函式呼叫中使用關鍵字引數時,呼叫者透過引數名稱識別引數。這允許您跳過引數或將其放置在錯誤的順序,因為 Python 直譯器能夠使用提供的關鍵字將值與引數匹配。

示例 1

以下示例演示如何在 Python 中使用關鍵字引數。

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print (str)
   return;

# Now you can call printme function
printme( str = "My string")

當執行上述程式碼時,會產生以下結果:

My string

示例 2

以下示例提供了更清晰的圖片。請注意,引數的順序無關緊要。

# Function definition is here
def printinfo( name, age ):
   "This prints a passed info into this function"
   print ("Name: ", name)
   print ("Age ", age)
   return;

# Now you can call printinfo function
printinfo( age=50, name="miki" )

當執行上述程式碼時,會產生以下結果:

Name:  miki
Age  50

預設引數

預設引數是指如果在函式呼叫中未為該引數提供值,則假設為預設值的引數。

示例

以下示例說明了預設引數,如果未傳遞,則列印預設年齡:

# Function definition is here
def printinfo( name, age = 35 ):
   "This prints a passed info into this function"
   print ("Name: ", name)
   print ("Age ", age)
   return;

# Now you can call printinfo function
printinfo( age=50, name="miki" )
printinfo( name="miki" )

當執行上述程式碼時,會產生以下結果:

Name:  miki
Age  50
Name:  miki
Age  35

僅限位置引數

只能透過其在函式呼叫中的位置指定的引數稱為 僅限位置引數。它們透過在函式的引數列表中所有僅限位置引數之後放置一個 "/" 來定義。此功能是在 Python 3.8 版本中引入的。

使用這種型別引數的好處是它確保函式以正確的順序使用正確的引數呼叫。僅限位置引數應該作為位置引數傳遞給函式,而不是關鍵字引數。

示例

在以下示例中,我們定義了兩個僅限位置的引數,即“x”和“y”。此方法應該按引數宣告的順序使用位置引數呼叫,否則,我們將收到錯誤。

def posFun(x, y, /, z):
    print(x + y + z)

print("Evaluating positional-only arguments: ")
posFun(33, 22, z=11) 

它將產生以下輸出

Evaluating positional-only arguments: 
66

僅限關鍵字引數

在呼叫函式時必須透過其名稱指定的引數稱為 僅限關鍵字引數。它們透過在函式的引數列表中任何僅限關鍵字引數之前放置一個星號(“*”)來定義。這種型別的引數只能作為關鍵字引數傳遞給函式,而不是位置引數。

示例

在下面的程式碼中,我們定義了一個具有三個僅限關鍵字引數的函式。要呼叫此方法,我們需要傳遞關鍵字引數,否則,我們將遇到錯誤。

def posFun(*, num1, num2, num3):
    print(num1 * num2 * num3)

print("Evaluating keyword-only arguments: ")
posFun(num1=6, num2=8, num3=5) 

它將產生以下輸出

Evaluating keyword-only arguments: 
240

任意引數或可變長度引數

您可能需要為函式處理比定義函式時指定的更多引數。這些引數稱為 可變長度引數,與必選引數和預設引數不同,它們在函式定義中沒有命名。

帶有非關鍵字可變引數的函式的語法如下:

def functionname([formal_args,] *var_args_tuple ):
   "function_docstring"
   function_suite
   return [expression]

一個星號 (*) 放在儲存所有非關鍵字可變引數值的變數名稱之前。如果在函式呼叫期間未指定其他引數,則此元組保持為空。

示例

以下是 Python 可變長度引數的一個簡單示例。

# Function definition is here
def printinfo( arg1, *vartuple ):
   "This prints a variable passed arguments"
   print ("Output is: ")
   print (arg1)
   for var in vartuple:
      print (var)
   return;

# Now you can call printinfo function
printinfo( 10 )
printinfo( 70, 60, 50 )

當執行上述程式碼時,會產生以下結果:

Output is:
10
Output is:
70
60
50

在接下來的幾章中,我們將詳細討論這些函式引數。

Python 函式引數的順序

一個函式可以包含上面定義的任何型別的引數。但是,引數必須按以下順序宣告:

  • 引數列表以僅限位置的引數開頭,後跟斜槓 (/) 符號。

  • 後面跟著常規位置引數,這些引數可能也可能不被呼叫為關鍵字引數。

  • 然後可能有一個或多個具有預設值的 args。

  • 接下來,由以單個星號為字首的變量表示的任意位置引數,該變數被視為元組。它是下一個。

  • 如果函式有任何僅限關鍵字的引數,請在其名稱開始之前放置一個星號。一些僅限關鍵字的引數可能具有預設值。

  • 括號中的最後一個是帶有兩個星號 ** 的引數,用於接受任意數量的關鍵字引數。

下圖顯示了形式引數的順序:

Order Of Formal Arguments

帶有返回值的 Python 函式

在函式定義中,return 關鍵字作為最後一個語句表示函式塊的結束,程式流程返回到呼叫函式。雖然在塊中的最後一個語句之後縮排減少也意味著返回,但使用顯式返回是一個好習慣。

除了流程控制之外,函式還可以將表示式的值返回給呼叫函式。返回表示式的值可以儲存在一個變數中以供進一步處理。

示例

讓我們定義 add() 函式。它將傳遞給它的兩個值相加並返回加法結果。返回值儲存在一個名為 result 的變數中。

def add(x,y):
   z=x+y
   return z
a=10
b=20
result = add(a,b)
print ("a = {} b = {} a+b = {}".format(a, b, result))

它將產生以下輸出:

a = 10 b = 20 a+b = 30

匿名函式

當函式不是以標準方式使用 def 關鍵字宣告時,這些函式稱為 匿名 函式。相反,它們是使用 lambda 關鍵字 定義的。

  • Lambda 表示式可以接受任意數量的引數,但只返回一個表示式的值。它們不能包含命令或多個表示式。

  • 匿名函式不能直接呼叫 print,因為 lambda 需要一個表示式

  • Lambda 函式有自己的區域性名稱空間,不能訪問其引數列表和全域性名稱空間之外的變數。

  • 雖然看起來 lambda 是函式的一行版本,但它們並不等同於 C 或 C++ 中的內聯語句,內聯語句的目的是透過在呼叫期間傳遞函式堆疊分配來提高效能。

語法

lambda 函式的語法只包含一個語句,如下所示:

lambda [arg1 [,arg2,.....argn]]:expression

示例

以下示例說明了 lambda 函式的工作原理:

# Function definition is here
sum = lambda arg1, arg2: arg1 + arg2;

# Now you can call sum as a function
print ("Value of total : ", sum( 10, 20 ))
print ("Value of total : ", sum( 20, 20 ))

當執行上述程式碼時,會產生以下結果:

Value of total :  30
Value of total :  40

變數的作用域

程式中的所有變數可能無法在程式的所有位置訪問。這取決於您在何處聲明瞭一個變數。

變數的作用域確定可以在程式的哪個部分訪問特定識別符號。Python 中變數有兩個基本作用域:

  • 全域性變數
  • 區域性變數

全域性變數與區域性變數

在函式體內部定義的變數具有區域性作用域,在外部定義的變數具有全域性作用域。

這意味著區域性變數只能在宣告它們的函式內部訪問,而全域性變數可以在整個程式體中被所有函式訪問。當您呼叫一個函式時,它內部宣告的變數會被帶入作用域。

示例

以下是一個區域性和全域性作用域的簡單示例:

total = 0; # This is global variable.
# Function definition is here
def sum( arg1, arg2 ):
   # Add both the parameters and return them."
   total = arg1 + arg2; # Here total is local variable.
   print ("Inside the function local total : ", total)
   return total;

# Now you can call sum function
sum( 10, 20 );
print ("Outside the function global total : ", total) 

當執行上述程式碼時,會產生以下結果:

Inside the function local total :  30
Outside the function global total :  0
廣告