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.
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.
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.
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))
Walaupun kelas "Circle" melaksanakan kaedah yang diperlukan, fungsi issubclass() masih akan mengembalikan "False" apabila menyemak sama ada "Circle" ialah subkelas "Shape" -
False
Di sinilah kaedah subclasshook dimainkan. Kita boleh mengatasi kaedah ini dalam kelas "Bentuk" untuk menentukan kriteria tersuai untuk menentukan sama ada kelas ialah subkelas -
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))
Output
Jika kita menyemak sama ada "Bulatan" ialah subkelas "Bentuk", outputnya adalah seperti berikut.
rreeeeDalam 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”,因为它不再具有指定的方法。
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 程序。
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!