首頁 >後端開發 >Python教學 >在Python中,__subclasscheck__和__subclasshook__是兩個特殊方法

在Python中,__subclasscheck__和__subclasshook__是兩個特殊方法

PHPz
PHPz轉載
2023-09-14 12:37:022006瀏覽

在Python中,__subclasscheck__和__subclasshook__是兩個特殊方法

Python 是一種普遍適應性強且有效的程式語言,長期以來一直受到廣泛歡迎。 Python 物件導向的特性允許執行一些高品質的功能,例如繼承和多態性。在這篇文章中,我們將深入研究兩種鮮為人知但迷人的技術,它們允許在 Python 中進行客製化設計的繼承檢查:subclasscheck 和 subclasshook。

什麼是 Subclasscheck 和 Subclasshook?

在 Python 中,透過使用內建的 issubclass() 函數來確定一個類別是否是其他類別的子類別並不罕見。預設情況下,函數會檢查繼承樹來決定課程之間的連接。然而,Python 也提供了一種使用獨特的方法 subclasscheck 和 subclasshook 來覆寫此預設行為的方法。

  • __subclasscheck__(cls) # 透過使用 issubclass() 函數呼叫此技術來測試某個類別是否是所有其他類別的子類別。預設情況下,它會傳回通常繼承測試的結果,但可以重寫它以改變此行為。

  • #__subclasshook__(cls) # 可以在抽象基底類別(ABC) 中定義此方法,以自訂issubclass() 執行的子類別檢查。它由 ABC 中 subclasscheck 的預設實作呼叫。

#子類別鉤子方法

為了清楚了解 subclasshook 方法的工作原理,讓我們來看一個範例。假設我們有一個名為「Shape」的抽象基底類,它有兩個必需的方法:「area」和「perimeter」。任何希望被視為「Shape」子類別的類別都必須實作這些方法。

第 1 步  使用兩種特定方法確定抽象基底類別「形狀」:「面積」和「週長」。

第 2 步  產生一個自訂類別“Circle”,該類別實作指定的方法“area”和“perimeter”。

第 3 步 − 重寫 'Shape' 類別中的 subclasshook 方法以指定用於判斷類別是否為子類別的自訂標準。在這種情況下,標準是該類別應該具有“面積”和“週長”方法。

第 4 步 − 使用 issubclass() 函數測試「Circle」是否是「Shape」的子類別。使用自訂子類別掛鉤方法,結果為“True”,因為“Circle”滿足自訂條件。

範例

現在,讓我們建立一個實作這些方法的自訂類別「Circle」 -

from abc import ABCMeta, abstractmethod

class Shape(metaclass=ABCMeta):
   @abstractmethod
   def area(self):
      pass
   
   @abstractmethod
   def perimeter(self):
      pass
class Circle:
   def __init__(self, radius):
      self.radius = radius
   
   def area(self):
      return 3.14 * self.radius * self.radius
   
   def perimeter(self):
      return 2 * 3.14 * self.radius
print(issubclass(Circle, Shape))

即使「Circle」類別實作了所需的方法,issubclass() 函數在檢查「Circle」是否是「Shape」的子類別時仍將傳回「False」 -

輸出

False

這就是 subclasshook 方法發揮作用的地方。我們可以在「Shape」類別中重寫此方法,以指定確定一個類別是否為子類別的自訂標準 -

範例

class Shape(metaclass=ABCMeta):
   @abstractmethod
   def area(self):
      pass
   
   @abstractmethod
   def perimeter(self):
      pass
   
   @classmethod
   def __subclasshook__(cls, other):
      if cls is Shape:
         if all(hasattr(other, method) for method in ['area', 'perimeter']):
            return True
      return NotImplemented
print(issubclass(Circle, Shape))

輸出

如果我們檢查「Circle」是否是「Shape」的子類,則輸出如下。

True

子類別檢查方法

在某些情況下,您可能想要重寫 subclasscheck 方法本身,而不是使用 subclasshook。這可以為繼承測試提供額外的一流粒度控制。這是一個範例

第 1 步  決定覆蓋子類別檢查方法的自訂基底類別「CustomBase」。我們不是測試一般的繼承連接,而是測試子類別是否有可呼叫的“magic_attribute”方法。

第 2 步 產生兩個類,「DerivedWithMagic」和「DerivedWithoutMagic」。前者有 'magic_attribute' 方法,而後者沒有。

第 3 步  利用 issubclass() 函数来测试“DerivedWithMagic”和“DerivedWithoutMagic”是否是“CustomBase”的子类。对于“DerivedWithMagic”,结论为“True”,因为它具有所需的“magic_attribute”方法;对于“DerivedWithoutMagic”,结论为“False”,因为它不再具有指定的方法。

示例
class CustomBase:
   def __subclasscheck__(self, subclass):
      return (hasattr(sub

class, "magic_attribute") and
callable(getattr(subclass, "magic_attribute")))
class DerivedWithMagic:
def magic_attribute(self):
pass
class DerivedWithoutMagic:
pass
print(issubclass(DerivedWithMagic, CustomBase))
print(issubclass(DerivedWithoutMagic, CustomBase))

输出

如果我们检查“Circle”是否是“Shape”的子类,则输出如下。

True
False

实际用例

虽然 Python 中的默认继承机制适用于大多数场景,但在某些情况下,使用 __subclasscheck__ 和 __subclasshook__ 自定义子类检查可能会有所帮助 -

  • **协议执行**  通过使用这些方法,您可以强制执行子类必须遵守的某些协议。在前面的实例中,我们决定任何被视为“Shape”子类的类都必须执行“area”和“perimeter”方法。

  • **混合课程**  Mixin 类的创建是为了向其他类提供特定的行为,但它们并不意味着用作独立的类。您可以使用 __subclasscheck__ 或 __subclasshook__ 定义自定义继承策略,通过利用 mixin 作为子类来识别类,尽管它们不会立即继承它。

  • **松散耦合**  在某些情况下,最大限度地减少软件系统中组件之间的依赖关系是有益的。通过使用 __subclasscheck__ 和 __subclasshook__,您可以在类之间建立关系,而无需创建严格的继承层次结构。

结论

Python 中的 __subclasscheck__ 和 __subclasshook__ 方法提供了一种强大的方法来自定义继承检查。当您想要强制执行子类关系的特定要求或提供更灵活的继承结构时,这些方法特别有用。通过理解和利用这些特殊方法,您可以创建适应性更强、更健壮的 Python 程序。

以上是在Python中,__subclasscheck__和__subclasshook__是兩個特殊方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:tutorialspoint.com。如有侵權,請聯絡admin@php.cn刪除