Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Penaipan Itik Memenuhi Petua Jenis: Menggunakan Protokol dalam Python

Penaipan Itik Memenuhi Petua Jenis: Menggunakan Protokol dalam Python

WBOY
WBOYasal
2024-07-31 10:40:341088semak imbas

Duck Typing Meets Type Hints: Using Protocols in Python

Sifat dinamik Python dan sokongan untuk menaip itik telah lama dipuji kerana fleksibilitinya. Walau bagaimanapun, apabila pangkalan kod semakin besar dan lebih kompleks, faedah pemeriksaan jenis statik menjadi semakin jelas. Tetapi bagaimanakah kita boleh menyelaraskan fleksibiliti menaip itik dengan keselamatan pemeriksaan jenis statik? Masukkan kelas Protokol Python.

Dalam tutorial ini, anda akan belajar:

  1. Apakah itu menaip itik dan cara ia disokong dalam Python
  2. Kebaikan dan keburukan menaip itik
  3. Cara Kelas Asas Abstrak (ABC) cuba menyelesaikan isu menaip
  4. Cara menggunakan Protokol untuk mendapatkan yang terbaik dari kedua-dua dunia: fleksibiliti menaip itik dengan semakan jenis statik

Memahami Menaip Itik

Penaipan itik ialah konsep pengaturcaraan di mana jenis atau kelas objek kurang penting daripada kaedah yang ditentukannya. Ia berdasarkan idea bahawa "Jika ia kelihatan seperti itik, berenang seperti itik, dan kuak seperti itik, maka ia mungkin itik."

Dalam Python, penaipan itik disokong sepenuhnya. Contohnya:

class Duck:
    def quack(self):
        print("Quack!")

class Person:
    def quack(self):
        print("I'm imitating a duck!")

def make_it_quack(thing):  # Note: No type hint here
    thing.quack()

duck = Duck()
person = Person()

make_it_quack(duck)    # Output: Quack!
make_it_quack(person)  # Output: I'm imitating a duck!

Dalam contoh ini, make_it_quack tidak mengambil berat tentang jenis perkara. Ia hanya peduli bahawa perkara itu mempunyai kaedah cuak. Harap maklum bahawa tiada pembayang jenis untuk parameter benda, yang tipikal dalam kod jenis itik tetapi boleh membawa kepada isu dalam pangkalan kod yang lebih besar.

Kebaikan dan Keburukan Menaip Itik

Menaip itik menawarkan beberapa kelebihan:

  1. Fleksibiliti: Ia membenarkan kod yang lebih fleksibel yang tidak terikat pada jenis tertentu.
  2. Penggunaan semula kod yang lebih mudah: Anda boleh menggunakan kelas sedia ada dalam konteks baharu tanpa pengubahsuaian.
  3. Penekanan pada tingkah laku: Ia memfokuskan pada perkara yang boleh dilakukan oleh objek, bukannya perkara yang dilakukan.

Walau bagaimanapun, ia juga mempunyai beberapa kelemahan:

  1. Kurang kejelasan: Tidak jelas kaedah yang perlu dilaksanakan oleh objek.
  2. Ralat masa jalan: Ralat berkaitan jenis hanya ditangkap pada masa jalan.
  3. Kurang sokongan IDE: IDE berjuang untuk menyediakan autolengkap yang tepat dan semakan ralat.

Penyelesaian ABC

Satu pendekatan untuk menangani isu ini ialah menggunakan Kelas Asas Abstrak (ABC). Berikut ialah contoh:

from abc import ABC, abstractmethod

class Quacker(ABC):
    @abstractmethod
    def quack(self):
        pass

class Duck(Quacker):
    def quack(self):
        print("Quack!")

class Person(Quacker):
    def quack(self):
        print("I'm imitating a duck!")

def make_it_quack(thing: Quacker):
    thing.quack()

duck = Duck()
person = Person()

make_it_quack(duck)
make_it_quack(person)

Walaupun pendekatan ini menyediakan pemeriksaan jenis yang lebih baik dan antara muka yang lebih jelas, pendekatan ini mempunyai kelemahan:

  1. Ia memerlukan warisan, yang boleh membawa kepada hierarki yang tidak fleksibel.
  2. Ia tidak berfungsi dengan kelas sedia ada yang anda tidak boleh ubah suai.
  3. Ia bertentangan dengan falsafah "menaip itik" Python.

Protokol: Yang Terbaik dari Kedua-dua Dunia

Python 3.8 memperkenalkan kelas Protokol, yang membolehkan kami mentakrifkan antara muka tanpa memerlukan pewarisan. Begini cara kita boleh menggunakannya:

from typing import Protocol

class Quacker(Protocol):
    def quack(self):...

class Duck:
    def quack(self):
        print("Quack!")

class Person:
    def quack(self):
        print("I'm imitating a duck!")

def make_it_quack(thing: Quacker):
    thing.quack()

duck = Duck()
person = Person()

make_it_quack(duck)
make_it_quack(person)

Mari pecahkan perkara ini:

  1. Kami mentakrifkan protokol Quacker yang menentukan antara muka yang kami jangkakan.
  2. Kelas Itik dan Orang kami tidak perlu mewarisi apa-apa.
  3. Kita boleh menggunakan petunjuk jenis dengan make_it_quack untuk menyatakan bahawa ia menjangkakan Quacker.

Pendekatan ini memberi kita beberapa faedah:

  1. Pemeriksaan jenis statik: IDE dan penyemak jenis boleh menangkap ralat sebelum masa jalan.
  2. Tiada warisan diperlukan: Kelas sedia ada berfungsi selagi mereka mempunyai kaedah yang betul.
  3. Antara muka yang jelas: Protokol mentakrifkan dengan jelas kaedah yang diharapkan.

Berikut ialah contoh yang lebih kompleks yang menunjukkan cara Protokol boleh menjadi sekompleks yang diperlukan (Bentuk), memastikan kelas domain anda (Bulatan, Segi Empat) rata:

from typing import Protocol, List

class Drawable(Protocol):
    def draw(self): ...

class Resizable(Protocol):
    def resize(self, factor: float): ...

class Shape(Drawable, Resizable, Protocol):
    pass

def process_shapes(shapes: List[Shape]):
    for shape in shapes:
        shape.draw()
        shape.resize(2.0)

# Example usage
class Circle:
    def draw(self):
        print("Drawing a circle")

    def resize(self, factor: float):
        print(f"Resizing circle by factor {factor}")

class Rectangle:
    def draw(self):
        print("Drawing a rectangle")

    def resize(self, factor: float):
        print(f"Resizing rectangle by factor {factor}")

# This works with any class that has draw and resize methods,
# regardless of its actual type or inheritance
shapes: List[Shape] = [Circle(), Rectangle()]
process_shapes(shapes)

Dalam contoh ini, Circle dan Rectangle tidak mewarisi Shape atau mana-mana kelas lain. Mereka hanya melaksanakan kaedah yang diperlukan (lukis dan ubah saiz). Fungsi process_shapes boleh berfungsi dengan mana-mana objek yang mempunyai kaedah ini, terima kasih kepada protokol Shape.

Ringkasan

Protokol dalam Python menyediakan cara yang berkuasa untuk membawa penaipan statik kepada kod yang ditaip itik. Mereka membenarkan kami menentukan antara muka dalam sistem jenis tanpa memerlukan pewarisan, mengekalkan fleksibiliti menaip itik sambil menambah faedah pemeriksaan jenis statik,

Dengan menggunakan Protokol, anda boleh:

  1. Tentukan antara muka yang jelas untuk kod anda
  2. Dapatkan IDE yang lebih baik, (semakan jenis statik), sokong dan tangkap ralat lebih awal
  3. Kekalkan fleksibiliti menaip itik
  4. Semakan jenis memanfaatkan untuk kelas yang anda tidak dapat ubah suai.

Jika anda ingin mengetahui lebih lanjut tentang Protokol dan pembayang taip dalam Python, lihat dokumentasi Python rasmi pada modul penaipan, atau terokai alat semakan jenis statik lanjutan seperti mypy.

Selamat mengekod, dan semoga itik anda sentiasa cuak dengan keselamatan jenis!

Anda boleh mendapatkan lebih banyak kandungan saya, termasuk surat berita saya di sini

Atas ialah kandungan terperinci Penaipan Itik Memenuhi Petua Jenis: Menggunakan Protokol dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
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