0Pricing
Python Academy · درس

TypeVar والفئات العامة وProtocol

عرّف أنواعاً عامة قابلة لإعادة الاستخدام، واستخدم التوريث البنيوي الفرعي مع Protocol

TypeVar والفئات العامة وProtocol درس مجاني في Python Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Python Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Python Academy 4 دروس في المجموع.

ما هو TypeVar؟

يعرّف TypeVar متغير نوع — وهو عنصر نائب يمكن أن يمثل أي نوع، ويمكن تقييده عند الحاجة. ويُستخدم في الدوال والفئات العامة.

from typing import TypeVar

T = TypeVar("T")

def identity(value: T) -> T:
    return value

print(identity(42))      # int
print(identity("hello")) # str

الدوال العامة

تتيح الدالة التي تستخدم TypeVar في أنواع المعاملات والقيم المعادة لـ mypy استنتاج نوع القيمة المعادة من نوع الوسيط.

from typing import TypeVar

T = TypeVar("T")

def first(items: list[T]) -> T:
    return items[0]

x: int = first([1, 2, 3])     # mypy knows x is int
s: str = first(["a","b","c"]) # mypy knows s is str

TypeVar المقيّد

مرّر قيود الأنواع إلى TypeVar لتقييد الأنواع المقبولة.

from typing import TypeVar

Numeric = TypeVar("Numeric", int, float)

def double(n: Numeric) -> Numeric:
    return n * 2

print(double(5))    # 10
print(double(2.5))  # 5.0
# double("x")  # mypy error

الفئات العامة

ورّث من Generic[T] لإنشاء فئة تعتمد معلمتها على متغير نوع.

from typing import Generic, TypeVar

T = TypeVar("T")

class Stack(Generic[T]):
    def __init__(self) -> None:
        self._items: list[T] = []

    def push(self, item: T) -> None:
        self._items.append(item)

    def pop(self) -> T:
        return self._items.pop()

stack: Stack[int] = Stack()
stack.push(1)
print(stack.pop())   # 1

متغيرات TypeVar متعددة

استخدم عدة متغيرات TypeVar لجعل فئة أو دالة تعتمد على نوعين مستقلين.

from typing import Generic, TypeVar

K = TypeVar("K")
V = TypeVar("V")

class Pair(Generic[K, V]):
    def __init__(self, key: K, value: V) -> None:
        self.key = key
        self.value = value

p: Pair[str, int] = Pair("age", 30)
print(p.key, p.value)   # age 30

Protocol — التوريث الفرعي البنيوي

يعرّف Protocol واجهةً من خلال الأساليب والسمات التي يجب أن تحتوي عليها الفئة، دون اشتراط التوريث الصريح («الكتابة بأسلوب بطة، مع التحقق من النوع»).

from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None: ...

def render(obj: Drawable) -> None:
    obj.draw()

class Circle:
    def draw(self) -> None:
        print("Drawing circle")

render(Circle())   # works — Circle satisfies Drawable

Protocol مع runtime_checkable

أضف @runtime_checkable إلى Protocol لتمكين عمليات التحقق isinstance() في وقت التشغيل.

from typing import Protocol, runtime_checkable

@runtime_checkable
class Closeable(Protocol):
    def close(self) -> None: ...

class File:
    def close(self) -> None: print("closed")

print(isinstance(File(), Closeable))   # True

Protocol مقابل ABC

تتطلب ABCs توريثًا صريحًا (class Dog(Animal)). أما Protocols فتعمل بالمطابقة البنيوية؛ فإذا كانت الفئة تحتوي على الأساليب الصحيحة، فإنها تفي بالبروتوكول بغض النظر عن التوريث.

from typing import Protocol
from abc import ABC, abstractmethod

# ABC: nominal typing
class Printable(ABC):
    @abstractmethod
    def display(self) -> None: ...

# Protocol: structural typing
class Displayable(Protocol):
    def display(self) -> None: ...

TypeVar مع bound

يقيّد TypeVar("T", bound=BaseClass) ‏T ليكون من نوع BaseClass أو من أي فئة فرعية له.

from typing import TypeVar

class Animal:
    def speak(self) -> str: return "..."

A = TypeVar("A", bound=Animal)

def make_speak(animal: A) -> str:
    return animal.speak()

الاسم المستعار العام — Python 3.12

يقدم Python 3.12 تعليمة type لإنشاء أسماء مستعارة للأنواع بطريقة واضحة، وصيغة class Foo[T] للأنواع العامة دون استيراد TypeVar.

# Python 3.12+
type Vector = list[float]
type Matrix = list[Vector]

class Stack[T]:
    def __init__(self) -> None: self._items: list[T] = []
    def push(self, item: T) -> None: self._items.append(item)
    def pop(self) -> T: return self._items.pop()

نوع Self

يضع Self (من typing في 3.11+) تعليقًا على الأساليب التي تعيد الفئة الحالية، وهو مفيد في الواجهات المتسلسلة والفئات الفرعية.

from typing import Self

class Builder:
    def __init__(self) -> None:
        self.parts: list[str] = []

    def add(self, part: str) -> Self:
        self.parts.append(part)
        return self

b = Builder().add("a").add("b")
print(b.parts)   # ["a", "b"]

تحقق سريع

ما الفرق الأساسي بين Protocol وABC في كتابة أنواع Python؟

مراجعة

ينشئ TypeVar عناصر نائبة للأنواع في الدوال والفئات العامة. وتُستخدم Generic[T] لجعل الفئات تعتمد على معلمة نوع. ويتيح Protocol التوريث الفرعي البنيوي دون توريث صريح. استخدم bound= أو قيود الأنواع على TypeVar لتقييد الأنواع المقبولة.

الأسئلة الشائعة

هل درس «TypeVar والفئات العامة وProtocol» مجاني؟

نعم — نص درس «TypeVar والفئات العامة وProtocol» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Python Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Python Academy 4 دروس في المجموع.

ماذا ستتعلم في «TypeVar والفئات العامة وProtocol»؟

عرّف أنواعاً عامة قابلة لإعادة الاستخدام، واستخدم التوريث البنيوي الفرعي مع Protocol تتمرن على Python Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Python Academy؟

لا تُشترط خبرة سابقة. Python Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «TypeVar والفئات العامة وProtocol»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Python Academy هذا؟

نعم. كل درس في Python Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. أساسيات تعليقات الأنواع
  2. الأنواع المعقدة: List وDict وOptional وUnion
  3. TypeVar والفئات العامة وProtocol
  4. تشغيل mypy وإصلاح أخطاء الأنواع
← العودة إلى Python Academy