如何在 Python 中過載函式?
在 Python 中,您可以定義一個方法,使其有多種呼叫方式。根據 函式定義,它可以被呼叫零個、一個、兩個或多個引數。這被稱為方法過載。
Python 本身並不像 Java 或 C++ 那樣支援函式過載。但是,可以使用預設引數、可變長度引數以及 functools.singledispatch 等外部庫來實現類似的行為。
使用預設引數進行方法過載
在 Python 中,我們可以透過使用預設引數來模擬函式過載。這使我們能夠使用比函式通常需要的更少的輸入來呼叫函式。如果我們不提供一些輸入,則函式將使用一些預設值。
下面是一個如果不提供一些輸出會發生什麼的示例
class Human: def sayHello(self, name=None): if name is not None: print('Hello ' + name) else: print('Hello') obj = Human() print(obj.sayHello()) # Output: Hello print(obj.sayHello('Rambo')) # Output: Hello Rambo
sayHello() 方法有一個預設引數 name=None,這意味著我們可以帶或不帶傳遞名稱來呼叫該方法。如果我們傳遞一個名稱,它會列印 "Hello" 後跟名稱。否則,它只打印 "Hello"。
在上面的示例中,在呼叫 sayHello() 之後,您可能已經注意到 Python 列印了 None。發生這種情況是因為該函式不返回值,因此 Python 隱式地返回 None。為了避免這種情況,我們可以包含一個 return 語句或在呼叫函式時忽略 None 輸出。
使用多個引數進行函式過載
透過使用預設引數,我們還可以允許函式接受不同數量的引數。例如,同一個函式可以有一個、兩個或任意數量的引數。
下面是如何向單個函式傳遞多個引數的示例。
def add(a, b=0, c=0): return a + b + c print(add(2)) # Output: 2 print(add(3, 2)) # Output: 5 print(add(1, 4, 3)) # Output: 8
在此示例中,add() 函式可以被呼叫一個、兩個或三個引數。如果我們提供較少的引數,其餘引數將自動設定為 0。
使用可變長度引數進行方法過載
使過載成為可能的另一種方法是使用可變長度引數。這允許我們使用 *args 向函式傳遞任意數量的引數。
def add(*args): result = 0 for arg in args: result += arg return result print(add(1, 2, 3)) # Output: 6 print(add(1, 3, 4, 5)) # Output: 13
在這種情況下,add() 方法可以接受任意數量的引數。*args 將它們收集到一個元組中,並且該函式將它們加起來。
基於引數型別的過載
我們還可以透過使用 isinstance() 檢查函式內部每個引數的型別來實現基於引數型別的函式過載。下面是一個示例:
def multiply(a, b): if isinstance(a, int) and isinstance(b, int): return a * b elif isinstance(a, float) and isinstance(b, float): return a * b else: return "Invalid argument types" print(multiply(2, 3)) # Output: 6 print(multiply(2.5, 3.5)) # Output: 8.75 print(multiply(2, 3.5)) # Output: Invalid argument types
這裡,函式檢查兩個引數是否都是相同型別(int 或 float)。如果它們不是相同型別,則返回錯誤訊息。
儘管上述方法有效,但它不是非常 Pythonic,因為 Python 是一種動態型別語言。因此,我們應該允許混合型別(例如,int 和 float)自然地工作,因為 Python 本身支援這種靈活性。
使用 functools.singledispatch 實現真正的函式過載
為了實現基於型別的真正的函式過載,Python 提供了 functools.singledispatch 裝飾器,這是一個外部庫。這使我們能夠根據第一個引數的型別建立函式的不同實現。
from functools import singledispatch @singledispatch def add(a): raise NotImplementedError('Unsupported type') @add.register(int) def _(a): return a + 10 @add.register(str) def _(a): return a + ' overloaded' print(add(10)) # Output: 20 print(add('Hi')) # Output: Hi overloaded
使用 singledispatch,我們可以為不同的型別註冊函式的不同版本,提供一種更靈活、更清晰的方法來實現過載。
為什麼 Python 不原生支援過載
在 Python 中,我們不需要像在 C++ 或 Java 中那樣擔心函式過載,因為它是一種動態型別語言。這意味著我們可以使用一個函式來處理不同型別和數量的引數,方法是使用預設值和可變長度引數。
結論
儘管 Python 不支援函式過載,但我們仍然可以實現它並獲得類似的結果。我們可以使用預設引數和可變長度引數,或者我們可以檢查輸入的型別。如果我們想要真正的基於型別的過載,Python 有一個名為 functools.singledispatch 的工具。這些方法幫助我們建立靈活且可重用的函式,這些函式可以處理不同型別和數量的引數。