如何在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` 的工具。這些方法有助於我們建立靈活且可重用的函式,這些函式可以處理不同型別和數量的引數。

更新於:2024年11月11日

4K+ 次瀏覽

啟動你的職業生涯

完成課程獲得認證

開始學習
廣告