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