Rumah > pembangunan bahagian belakang > Tutorial Python > Dalam Python, __subclasscheck__ dan __subclasshook__ ialah dua kaedah khas

Dalam Python, __subclasscheck__ dan __subclasshook__ ialah dua kaedah khas

PHPz
Lepaskan: 2023-09-14 12:37:02
ke hadapan
1994 orang telah melayarinya

Dalam Python, __subclasscheck__ dan __subclasshook__ ialah dua kaedah khas

Python ialah bahasa pengaturcaraan yang boleh disesuaikan secara universal dan berkesan yang telah mendapat populariti sejak sekian lama. Ciri berorientasikan objek Python membolehkan pelaksanaan ciri berkualiti tinggi seperti pewarisan dan polimorfisme. Dalam artikel ini, kita akan mendalami dua teknik yang kurang diketahui tetapi menarik yang membenarkan semakan warisan rekaan tersuai dalam Python: subclasscheck dan subclasshook.

Apakah itu Subclasscheck dan Subclasshook?

Dalam Python, adalah perkara biasa untuk menentukan sama ada kelas ialah subkelas kelas lain dengan menggunakan fungsi issubclass() terbina dalam. Secara lalai, fungsi ini memeriksa pepohon warisan untuk menentukan sambungan antara kelas. Walau bagaimanapun, Python juga menyediakan cara untuk mengatasi tingkah laku lalai ini menggunakan kaedah unik subclasscheck dan subclasshook.

  • __subclasscheck__(cls) Uji sama ada kelas ialah subkelas semua kelas lain dengan memanggil teknik ini menggunakan fungsi issubclass(). Secara lalai ia mengembalikan keputusan ujian yang diwarisi biasa, tetapi ia boleh ditindih untuk mengubah tingkah laku ini.

  • __subclasshook__(cls) Kaedah ini boleh ditakrifkan dalam kelas asas abstrak (ABC) untuk menyesuaikan semakan subkelas yang dilakukan oleh issubclass(). Ia dipanggil oleh pelaksanaan lalai subclasscheck dalam ABC.

Kaedah cangkuk subkelas

Untuk memahami dengan jelas cara kaedah subclasshook berfungsi, mari lihat contoh. Katakan kita mempunyai kelas asas abstrak yang dipanggil "Bentuk" yang mempunyai dua kaedah yang diperlukan: "kawasan" dan "perimeter". Mana-mana kelas yang ingin dianggap sebagai subkelas "Bentuk" mesti melaksanakan kaedah ini.

Langkah 1 Tentukan kelas asas abstrak "Bentuk" menggunakan dua kaedah khusus: "Kawasan" dan "Perimeter".

Langkah 2 Hasilkan kelas tersuai "Bulatan" yang melaksanakan kaedah "kawasan" dan "perimeter" yang ditentukan.

Langkah 3 Timpa kaedah subclasshook dalam kelas 'Shape' untuk menentukan kriteria tersuai untuk menentukan sama ada kelas ialah subkelas. Dalam kes ini, kriterianya ialah kelas harus mempunyai kaedah "Kawasan" dan "Perimeter".

Langkah 4 Gunakan fungsi issubclass() untuk menguji sama ada "Circle" ialah subkelas "Shape". Menggunakan kaedah cangkuk subkelas tersuai, hasilnya adalah "Benar" kerana "Bulatan" memenuhi syarat tersuai.

Contoh

Sekarang, mari buat kelas tersuai "Bulatan" yang melaksanakan kaedah ini -

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))
Salin selepas log masuk

Walaupun kelas "Circle" melaksanakan kaedah yang diperlukan, fungsi issubclass() masih akan mengembalikan "False" apabila menyemak sama ada "Circle" ialah subkelas "Shape" -

Output

False
Salin selepas log masuk

Di sinilah kaedah subclasshook dimainkan. Kita boleh mengatasi kaedah ini dalam kelas "Bentuk" untuk menentukan kriteria tersuai untuk menentukan sama ada kelas ialah subkelas -

Contoh

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))
Salin selepas log masuk

Output

Jika kita menyemak sama ada "Bulatan" ialah subkelas "Bentuk", outputnya adalah seperti berikut.

rreeee

Kaedah semakan subkelas

Dalam sesetengah kes, anda mungkin mahu mengatasi kaedah subclasscheck itu sendiri dan bukannya menggunakan subclasshook. Ini boleh menyediakan kawalan berbutir kelas pertama tambahan untuk ujian warisan. Berikut adalah contoh

Langkah 1 Tentukan kelas asas tersuai "CustomBase" yang mengatasi kaedah semakan subkelas. Daripada menguji sambungan pewarisan biasa, kami menguji sama ada subkelas mempunyai kaedah "magic_attribute" yang boleh dipanggil.

Langkah 2 Jana dua kelas, "DerivedWithMagic" dan "DerivedWithoutMagic". Yang pertama mempunyai kaedah 'atribut_ajaib', manakala yang kedua tidak.

第 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))
Salin selepas log masuk

输出

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

True
False
Salin selepas log masuk

实际用例

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

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

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

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

结论

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

Atas ialah kandungan terperinci Dalam Python, __subclasscheck__ dan __subclasshook__ ialah dua kaedah khas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:tutorialspoint.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan