使用 singledispatch-functools 實現函式過載


函式過載是面向物件程式設計中一個流行的概念,它允許函式具有相同名稱但引數不同的特性。這使開發人員能夠根據輸入引數編寫執行不同操作的函式。然而,Python 不像 Java 或 C++ 等其他面嚮物件語言那樣傳統地支援函式過載。幸運的是,functools 模組中的 singledispatch 函式為 Python 開發人員提供了一種實現函式過載的解決方案。

語法

functools 模組是 Python 標準庫的一部分,不需要任何安裝。要使用 singledispatch 函式,請從 functools 模組匯入它:

from functools import singledispatch

singledispatch 函式修飾執行預設操作的函式。然後,它使用 register() 方法為特定型別註冊其他函式。以下是基本語法:

@singledispatch
def function_name(arg):
   # default implementation

@function_name.register(type)
def _(arg):
   # specific implementation for type

演算法

Python 中的 singledispatch 函式透過為不同型別的引數註冊函式的不同實現來工作。當呼叫該函式時,singledispatch 函式確定引數的型別並呼叫相應的實現。如果引數型別沒有特定的實現,則呼叫預設實現。

  • 使用 @singledispatch 修飾預設函式。

  • 使用 register() 方法為特定型別註冊其他函式。

  • 使用不同的引數型別呼叫它。

  • singledispatch 函式確定引數的型別並呼叫相應的實現。

示例 1 - 整數和字串的過載函式

from functools import singledispatch

@singledispatch
def my_function(arg):
   print("Standard implementation for type: ", type(arg).__name__)

@my_function.register(int)
def _(arg):
   print("Overridden for INT: ", arg)

@my_function.register(str)
def _(arg):
   print("This is the implementation for strings:", arg)
    
x = 1
my_function(x)

x = "Hello"
my_function(x)

# default implementation
my_function(1.0)

輸出

Overridden for INT: 1
This is the implementation for strings: Hello
Standard implementation for type: float

預設實現列印引數的型別,而整數和字串的特定實現列印包含引數值的的訊息。

示例 2 - 列表和元組的過載函式

from functools import singledispatch

@singledispatch
def process_data(arg):
   print("Overridden DATA TYPE-> ", type(arg).__name__)

@process_data.register(list)
def _(arg):
   print("Overridden LIST-> ", arg)

@process_data.register(tuple)
def _(arg):
   print("Overridden TUPLE-> ", arg)
 
process_data(1)
process_data([1, 2, 3])
process_data((1, 2, 3))

輸出

Overridden DATA TYPE-> int
Overridden LIST-> [1, 2, 3]
Overridden TUPLE-> (1, 2, 3)

假設我們想建立一個計算不同形狀(矩形、正方形和圓形)面積的函式。

from functools import singledispatch

@singledispatch
def calculate_area(shape):
   raise NotImplementedError("Unsupported shape type")

@calculate_area.register
def _(shape: tuple):
   if len(shape) != 2:
      raise ValueError("Tuple must have 2 vals")
   return shape[0] * shape[1]

@calculate_area.register
def _(shape: float):
   return 3.14 * shape * shape

@calculate_area.register
def _(shape: int):
   return shape * shape

@calculate_area.register
def _(shape: str):
   raise ValueError("Shape type not supported")

# passing tuple [Rectangle]
print(calculate_area((2, 3)))

# passing only one value [Square]
print(calculate_area(2))

# passing float [Circle]
print(calculate_area(3.0))

輸出

6
4
28.259999999999998
  • calculate_area 函式使用 @singledispatch 進行修飾。

  • 預設實現引發一條包含訊息“不支援的形狀型別”的 NotImplementedError 錯誤。

  • register() 方法用於為不同型別的形狀註冊四個其他實現。

  • 元組的實現透過將長度和寬度相乘來計算矩形的面積。

  • 浮點數的實現使用公式 pi * r^2 計算圓形的面積。

  • 整數的實現透過將邊長自身相乘來計算正方形的面積。

  • 字串的實現引發一條包含訊息“不支援的形狀型別”的 ValueError 錯誤。

現在讓我們使用不同型別的引數呼叫 calculate_area 函式:

>>> calculate_area((4, 5))
20
>>> calculate_area(4.0)
50.24
>>> calculate_area(4)
16
>>> calculate_area("rectangle")
ValueError: Shape type not supported
  • 第一個呼叫使用長度為 2 的元組返回矩形的面積。

  • 第二個呼叫使用浮點數返回圓形的面積。

  • 第三個呼叫使用整數返回正方形的面積。

  • 第四個呼叫使用字串引發 ValueError 錯誤,因為沒有字串的實現。

應用

在需要根據引數型別執行不同操作的情況下,singledispatch 函式特別有用。以下是一些潛在的應用:

  • 資料驗證和操作。

  • 格式化輸出資料。

  • 特定型別的錯誤處理。

結論

總之,Python 不以傳統方式支援函式過載,但 functools 模組以 singledispatch 函式的形式提供了一個有用的解決方案。透過為不同型別的引數註冊不同的實現,singledispatch 函式使開發人員能夠建立能夠根據輸入引數執行不同操作的函式。此強大功能使 Python 更加適合面向物件程式設計任務。

更新於: 2023年8月22日

291 次瀏覽

開啟您的 職業生涯

透過完成課程獲得認證

立即開始
廣告

© . All rights reserved.