Python - 動態繫結



面向物件程式設計中,**動態繫結**的概念與多型密切相關。在 Python 中,動態繫結是在執行時而不是編譯時解析方法或屬性的過程。

根據多型特性,不同的物件對相同的方法呼叫會根據其實現做出不同的響應。此行為是透過方法重寫實現的,其中子類提供其在超類中定義的方法的實現。

Python 直譯器根據物件的型別或類層次結構在執行時確定要呼叫的適當方法或屬性。這意味著要呼叫的特定方法或屬性是根據物件的實際型別動態確定的。

示例

以下示例說明了 Python 中的動態繫結:

class shape:
   def draw(self):
      print ("draw method")
      return

class circle(shape):
   def draw(self):
      print ("Draw a circle")
      return

class rectangle(shape):
   def draw(self):
      print ("Draw a rectangle")
      return

shapes = [circle(), rectangle()]
for shp in shapes:
   shp.draw()

它將產生以下輸出

Draw a circle
Draw a rectangle

正如您所看到的,draw() 方法根據物件的型別動態繫結到相應的實現。這就是 Python 中動態繫結的實現方式。

鴨子型別

另一個與動態繫結密切相關的概念是鴨子型別。物件的適用性取決於是否存在某些方法或屬性,而不是其型別。這使得 Python 具有更大的靈活性和程式碼重用性。

鴨子型別是動態型別語言(如PythonPerlRubyPHPJavascript等)的一個重要特性,它關注物件的行為而不是其具體的型別。根據“鴨子型別”的概念,“如果它走起來像鴨子,叫起來也像鴨子,那麼它一定就是鴨子。”

鴨子型別允許不同型別的物件可以互換使用,只要它們具有所需的方法或屬性。其目標是提高靈活性和程式碼重用性。這是一個更廣泛的概念,它強調物件的行為和介面,而不是正式的型別。

下面是一個鴨子型別的例子:

class circle:
   def draw(self):
      print ("Draw a circle")
      return

class rectangle:
   def draw(self):
      print ("Draw a rectangle")
      return

class area:
   def area(self):
      print ("calculate area")
      return

def duck_function(obj):
   obj.draw()

objects = [circle(), rectangle(), area()]
for obj in objects:
   duck_function(obj)

它將產生以下輸出

Draw a circle
Draw a rectangle
Traceback (most recent call last):
 File "C:\Python311\hello.py", line 21, in <module>
  duck_function(obj)
 File "C:\Python311\hello.py", line 17, in duck_function
 obj.draw()
AttributeError: 'area' object has no attribute 'draw'

鴨子型別背後的最重要的思想是,duck_function()並不關心它接收的物件的具體型別。它只需要物件具有draw()方法。如果一個物件透過具有必要的行為“像鴨子一樣嘎嘎叫”,那麼為了呼叫draw()方法,它就被視為“鴨子”。

因此,在鴨子型別中,關注的是物件的行為而不是其顯式型別,允許不同型別的物件可以互換使用,只要它們表現出所需的行為。

廣告