如何在 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

這裡,函式檢查兩個引數是否都是相同型別(intfloat)。如果它們不是相同型別,則返回錯誤訊息。

儘管上述方法有效,但它不是非常 Pythonic,因為 Python 是一種動態型別語言。因此,我們應該允許混合型別(例如,intfloat)自然地工作,因為 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+ 閱讀量

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告