En Python, __subclasscheck__ et __subclasshook__ sont deux méthodes spéciales

PHPz
Libérer: 2023-09-14 12:37:02
avant
1988 Les gens l'ont consulté

En Python, __subclasscheck__ et __subclasshook__ sont deux méthodes spéciales

Python est un langage de programmation universellement adaptable et efficace qui gagne en popularité depuis longtemps. Les fonctionnalités orientées objet de Python permettent la mise en œuvre de fonctionnalités de haute qualité telles que l'héritage et le polymorphisme. Dans cet article, nous allons approfondir deux techniques peu connues mais fascinantes qui permettent une vérification d'héritage personnalisée en Python : subclasscheck et subclasshook.

Que sont Subclasscheck et Subclasshook ?

En Python, il n'est pas rare de déterminer si une classe est une sous-classe d'une autre classe en utilisant la fonction intégrée issubclass(). Par défaut, cette fonction examine l'arbre d'héritage pour déterminer les connexions entre les classes. Cependant, Python fournit également un moyen de remplacer ce comportement par défaut à l'aide des méthodes uniques subclasscheck et subclasshook.

  • __subclasscheck__(cls) Testez si une classe est une sous-classe de toutes les autres classes en appelant cette technique à l'aide de la fonction issubclass(). Par défaut, il renvoie les résultats du test hérité habituel, mais il peut être remplacé pour modifier ce comportement.

  • __subclasshook__(cls) Cette méthode peut être définie dans une classe de base abstraite (ABC) pour personnaliser la vérification de sous-classe effectuée par issubclass(). Il est appelé par l'implémentation par défaut de subclasscheck dans ABC.

Méthode de hook de sous-classe

Pour comprendre clairement comment fonctionne la méthode subclasshook, voyons un exemple. Supposons que nous ayons une classe de base abstraite appelée "Shape" qui a deux méthodes requises : "area" et "perimeter". Toute classe souhaitant être considérée comme une sous-classe de « Shape » doit implémenter ces méthodes.

Étape 1 Déterminez la classe de base abstraite "Shape" en utilisant deux méthodes spécifiques : "Area" et "Perimeter".

Étape 2 Générez une classe personnalisée "Circle" qui implémente les méthodes spécifiées "area" et "perimeter".

Étape 3 Remplacez la méthode subclasshook dans la classe 'Shape' pour spécifier des critères personnalisés permettant de déterminer si une classe est une sous-classe. Dans ce cas, le critère est que la classe doit avoir les méthodes « Area » et « Perimeter ».

Étape 4 Utilisez la fonction issubclass() pour tester si "Circle" est une sous-classe de "Shape". En utilisant une méthode de hook de sous-classe personnalisée, le résultat est « True » car « Circle » satisfait la condition personnalisée.

Exemple

Maintenant, créons une classe personnalisée « Circle » qui implémente ces méthodes -

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))
Copier après la connexion

Même si la classe "Circle" implémente la méthode requise, la fonction issubclass() retournera toujours "False" lors de la vérification si "Circle" est une sous-classe de "Shape" -

Sortie

False
Copier après la connexion

C'est là que la méthode subclasshook entre en jeu. Nous pouvons remplacer cette méthode dans la classe "Shape" pour spécifier des critères personnalisés permettant de déterminer si une classe est une sous-classe -

Exemple

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))
Copier après la connexion

Sortie

Si nous vérifions si "Circle" est une sous-classe de "Shape", le résultat est le suivant.

True
Copier après la connexion

Méthode de vérification des sous-classes

Dans certains cas, vous souhaiterez peut-être remplacer la méthode subclasscheck elle-même au lieu d'utiliser un subclasshook. Cela peut fournir un contrôle granulaire supplémentaire de première classe pour les tests d’héritage. Voici un exemple

Étape 1 Déterminez la classe de base personnalisée "CustomBase" qui remplace la méthode de vérification de sous-classe. Au lieu de tester les connexions d'héritage normales, nous testons si la sous-classe possède une méthode "magic_attribute" appelable.

Étape 2 Générez deux classes, "DerivedWithMagic" et "DerivedWithoutMagic". Le premier a une méthode 'magic_attribute', tandis que le second n'en a pas.

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

示例< /h3>
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))
Copier après la connexion

输出

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

True
False
Copier après la connexion

实际用例

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

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

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

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

结论

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:tutorialspoint.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal