abc --- کلاسهای پایه انتزاعی¶
کد منبع: Lib/abc.py
این ماژول زیرساخت لازم برای تعریف کلاسهای پایه انتزاعی (ABCها) در پایتون را فراهم میکند، همانطور که در PEP 3119 شرح داده شده است؛ برای آگاهی از دلیل افزودن این قابلیت به پایتون، این PEP را ببینید. (همچنین PEP 3141 و ماژول numbers را در مورد سلسلهمراتب نوع برای اعداد بر پایه ABCها ببینید.)
ماژول collections تعدادی کلاس ملموس دارد که از ABCها مشتق شدهاند؛ البته میتوان اینها را نیز بیشتر مشتق کرد. علاوه بر این، زیرماژول collections.abc تعدادی ABC دارد که میتوان از آنها برای بررسی اینکه آیا یک کلاس یا نمونه، رابط خاصی را فراهم میکند، استفاده کرد؛ برای مثال، اگر hashable باشد یا یک mapping باشد.
این ماژول، فراکلاس ABCMeta را برای تعریف ABCها و کلاس کمکی ABC را فراهم میکند تا بهعنوان جایگزین، بتوانید ABCها را از طریق ارثبری تعریف کنید:
-
class abc.ABC¶
یک کلاس کمکی که ABCMeta را بهعنوان فراکلاس خود دارد. با این کلاس، میتوان یک کلاس پایه انتزاعی را صرفاً با مشتق شدن از ABC ایجاد کرد و از کاربرد گاه گیجکنندهی فراکلاس اجتناب نمود، برای مثال:
from abc import ABC
class MyABC(ABC):
pass
توجه داشته باشید که نوع ABC همچنان ABCMeta است؛ بنابراین ارثبری از ABC نیازمند رعایت نکات احتیاطی معمول در مورد استفاده از فراکلاس است، زیرا ارثبری چندگانه ممکن است به تعارضهای فراکلاس منجر شود. همچنین میتوان یک کلاس پایه انتزاعی را با ارسال کلیدواژه metaclass و استفاده مستقیم از ABCMeta تعریف کرد، برای مثال:
from abc import ABCMeta
class MyABC(metaclass=ABCMeta):
pass
-
class abc.ABCMeta¶
فراکلاس برای تعریف کلاسهای پایه انتزاعی (ABCها).
از این فراکلاس برای ایجاد یک ABC استفاده کنید. یک ABC بهطور مستقیم قابل زیرکلاسبندی است و سپس بهعنوان یک کلاس میکساین عمل میکند. همچنین میتوانید کلاسهای عینی غیرمرتبط (حتی کلاسهای توکار) و ABCهای غیرمرتبط را بهعنوان «زیرکلاسهای مجازی» ثبت کنید — این کلاسها و زیرکلاسهای مشتقشده از آنها از دید تابع توکار issubclass() زیرکلاسهای ABC ثبتکننده محسوب خواهند شد، اما ABC ثبتکننده در MRO (ترتیب حل متد) آنها ظاهر نخواهد شد و پیادهسازیهای متد تعریفشده توسط ABC ثبتکننده فراخوانیپذیر نخواهند بود (حتی از طریق super() نیز). [1]
کلاسهایی که با فراکلاس ABCMeta ایجاد شدهاند، متد زیر را دارند:
-
register(subclass)¶
subclass را بهعنوان یک «زیرکلاس مجازی» از این ABC ثبت کنید. برای مثال:
from abc import ABC
class MyABC(ABC):
pass
MyABC.register(tuple)
assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)
تغییر یافته در نسخهی 3.3: زیرکلاس ثبتشده را برمیگرداند تا امکان استفاده بهعنوان دکوراتور کلاس فراهم شود.
تغییر یافته در نسخهی 3.4: برای تشخیص فراخوانیهای register()، میتوانید از تابع get_cache_token() استفاده کنید.
همچنین میتوانید این متد را در یک کلاس پایه انتزاعی بازنویسی کنید:
-
__subclasshook__(subclass)¶
(باید بهعنوان متد کلاس تعریف شود.)
بررسی میکند که آیا subclass زیرکلاسی از این ABC در نظر گرفته میشود یا خیر. این بدان معناست که شما میتوانید رفتار issubclass() را بیشتر سفارشیسازی کنید، بدون نیاز به فراخوانی register() برای هر کلاسی که میخواهید آن را زیرکلاسی از ABC در نظر بگیرید. (این متد کلاس از متد __subclasscheck__() در ABC فراخوانی میشود.)
این متد باید True، False یا NotImplemented را برگرداند. اگر True را برگرداند، زیرکلاس بهعنوان زیرکلاسی از این ABC در نظر گرفته میشود. اگر False را برگرداند، زیرکلاس بهعنوان زیرکلاسی از این ABC در نظر گرفته نمیشود، حتی اگر در حالت عادی یک زیرکلاس باشد. اگر NotImplemented را برگرداند، بررسی زیرکلاس با سازوکار معمول ادامه مییابد.
برای نمایش این مفاهیم، این نمونه تعریف ABC را ببینید:
class Foo:
def __getitem__(self, index):
...
def __len__(self):
...
def get_iterator(self):
return iter(self)
class MyIterable(ABC):
@abstractmethod
def __iter__(self):
while False:
yield None
def get_iterator(self):
return self.__iter__()
@classmethod
def __subclasshook__(cls, C):
if cls is MyIterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
MyIterable.register(Foo)
کلاس پایه انتزاعی (ABC) MyIterable متد استاندارد پیمایشپذیر، __iter__()، را بهعنوان یک متد انتزاعی تعریف میکند. پیادهسازی ارائهشده در اینجا همچنان میتواند از زیرکلاسها فراخوانی شود. متد get_iterator() نیز بخشی از کلاس پایه انتزاعی MyIterable است، اما نیازی به بازنویسی آن در کلاسهای مشتقشده غیرانتزاعی نیست.
متد کلاسی __subclasshook__() تعریفشده در اینجا بیان میکند که هر کلاسی که یک متد __iter__() در __dict__ خود (یا در دیکشنری یکی از کلاسهای پایهی خود، که از طریق فهرست __mro__ به آنها دسترسی پیدا میشود) داشته باشد، بهعنوان یک MyIterable نیز در نظر گرفته میشود.
سرانجام، آخرین خط Foo را به یک زیرکلاس مجازی از MyIterable تبدیل میکند، اگرچه متد __iter__() را تعریف نمیکند (از پروتکل پیمایشپذیر بهسبک قدیمی استفاده میکند که بر حسب __len__() و __getitem__() تعریف شده است). توجه داشته باشید که این کار get_iterator را بهعنوان متدی از Foo در دسترس قرار نمیدهد، بنابراین بهصورت جداگانه ارائه شده است.
ماژول abc همچنین دکوراتور زیر را نیز فراهم میکند:
-
@abc.abstractmethod¶
دکوراتوری که متدهای انتزاعی را نشان میدهد.
استفاده از این دکوراتور مستلزم آن است که فراکلاسِ کلاس ABCMeta باشد یا از آن مشتق شده باشد. کلاسی که فراکلاس آن از ABCMeta مشتق شده باشد، نمیتواند نمونهسازی شود، مگر آنکه تمام متدها و ویژگیهای انتزاعی آن بازنویسی شده باشند. میتوان متدهای انتزاعی را با استفاده از هر یک از سازوکارهای معمول فراخوانی 'super' فراخوانی کرد. میتوان از abstractmethod برای اعلام متدهای انتزاعی برای ویژگیها و توصیفگرها استفاده کرد.
افزودن متدهای انتزاعی بهصورت پویا به یک کلاس، یا تلاش برای تغییر وضعیت انتزاعی یک متد یا کلاس پس از ایجاد آن، تنها با استفاده از تابع update_abstractmethods() پشتیبانی میشود. abstractmethod تنها بر زیرکلاسهای مشتقشده با وراثت معمولی تأثیر میگذارد؛ «زیرکلاسهای مجازی» ثبتشده با متد register() مربوط به ABC تحت تأثیر قرار نمیگیرند.
هنگامی که abstractmethod در ترکیب با سایر توصیفگرهای متد اعمال میشود، باید بهعنوان درونیترین دکوراتور اعمال شود، همانطور که در مثالهای استفاده زیر نشان داده شده است:
class C(ABC):
@abstractmethod
def my_abstract_method(self, arg1):
...
@classmethod
@abstractmethod
def my_abstract_classmethod(cls, arg2):
...
@staticmethod
@abstractmethod
def my_abstract_staticmethod(arg3):
...
@property
@abstractmethod
def my_abstract_property(self):
...
@my_abstract_property.setter
@abstractmethod
def my_abstract_property(self, val):
...
@abstractmethod
def _get_x(self):
...
@abstractmethod
def _set_x(self, val):
...
x = property(_get_x, _set_x)
برای تعامل صحیح با سازوکار کلاس پایه انتزاعی، توصیفگر باید خود را با استفاده از __isabstractmethod__ بهعنوان انتزاعی معرفی کند. بهطور کلی، اگر هر یک از متدهای استفادهشده برای تشکیل توصیفگر انتزاعی باشند، این ویژگی باید True باشد. برای مثال، @property توکار پایتون معادل زیر را انجام میدهد:
class Descriptor:
...
@property
def __isabstractmethod__(self):
return any(getattr(f, '__isabstractmethod__', False) for
f in (self._fget, self._fset, self._fdel))
نکته
برخلاف متدهای انتزاعی جاوا، این متدهای انتزاعی ممکن است پیادهسازی داشته باشند. این پیادهسازی را میتوان از طریق سازوکار super() از کلاسی که آن را بازنویسی میکند فراخوانی کرد. این میتواند بهعنوان پایانهای برای فراخوانی super در چارچوبی که از وراثت چندگانهی مشارکتی استفاده میکند، مفید باشد.
ماژول abc همچنین از دکوراتورهای قدیمی زیر پشتیبانی میکند:
-
@abc.abstractclassmethod¶
-
زیرکلاسی از classmethod توکار، که نشاندهندهی یک classmethod انتزاعی است. در سایر موارد، مشابه @abstractmethod است.
این حالت خاص منسوخ شده است، زیرا دکوراتور @classmethod اکنون هنگامی که به یک متد انتزاعی اعمال شود، بهدرستی بهعنوان انتزاعی شناسایی میشود:
class C(ABC):
@classmethod
@abstractmethod
def my_abstract_classmethod(cls, arg):
...
-
@abc.abstractstaticmethod¶
-
زیرکلاسی از staticmethod توکار که نشاندهنده یک staticmethod انتزاعی است. در غیر این صورت، مشابه @abstractmethod است.
این حالت خاص منسوخ شده است، زیرا دکوراتور @staticmethod اکنون هنگامی که به یک متد انتزاعی اعمال شود، بهدرستی بهعنوان انتزاعی شناسایی میشود:
class C(ABC):
@staticmethod
@abstractmethod
def my_abstract_staticmethod(arg):
...
-
@abc.abstractproperty¶
-
زیرکلاسی از property توکار، که نشاندهندهی یک ویژگی انتزاعی است.
این حالت خاص منسوخ شده است، زیرا دکوراتور @property اکنون هنگام اعمال بر یک متد انتزاعی بهدرستی بهعنوان انتزاعی شناسایی میشود:
class C(ABC):
@property
@abstractmethod
def my_abstract_property(self):
...
مثال بالا یک ویژگی فقطخواندنی تعریف میکند؛ شما همچنین میتوانید با علامتگذاری مناسب یک یا چند مورد از متدهای زیربنایی بهعنوان انتزاعی، یک ویژگی انتزاعی با قابلیت خواندن و نوشتن تعریف کنید:
class C(ABC):
@property
def x(self):
...
@x.setter
@abstractmethod
def x(self, val):
...
اگر تنها برخی از کامپوننتها انتزاعی باشند، تنها همان کامپوننتها باید بهروزرسانی شوند تا یک پراپرتی عینی در یک زیرکلاس ایجاد شود:
class D(C):
@C.x.setter
def x(self, val):
...
ماژول abc همچنین توابع زیر را فراهم میکند:
-
abc.get_cache_token()¶
توکن فعلی نهانگاه کلاس پایه انتزاعی را بازمیگرداند.
توکن یک شیء غیرشفاف است (که از آزمون برابری پشتیبانی میکند) و نسخه کنونی نهانگاه کلاس پایه انتزاعی برای زیرکلاسهای مجازی را شناسایی میکند. توکن با هر فراخوانی ABCMeta.register() روی هر ABC تغییر میکند.
-
abc.update_abstractmethods(cls)¶
تابعی برای محاسبهی مجدد وضعیت انتزاعی بودن یک کلاس انتزاعی. اگر متدهای انتزاعی یک کلاس پس از ایجاد آن پیادهسازی یا تغییر کرده باشند، باید این تابع فراخوانی شود. معمولاً این تابع باید از درون یک دکوراتور کلاس فراخوانی شود.
cls را برمیگرداند تا امکان استفاده بهعنوان دکوراتور کلاس فراهم شود.
اگر cls نمونهای از ABCMeta نباشد، هیچ کاری انجام نمیدهد.
نکته
این تابع فرض میکند که ابرکلاسهای cls از قبل بهروزرسانی شدهاند. این تابع هیچ زیرکلاسی را بهروزرسانی نمیکند.
اضافه شده در نسخهی 3.10.
پانویسها
©
حق نشر 2001 Python Software Foundation.
این صفحه تحت مجوز بنیاد نرمافزار پایتون نسخه ۲ منتشر شده است.
مثالها، دستورالعملها، و سایر کدهای موجود در مستندات همچنین تحت مجوز بدون بند BSD منتشر شدهاند.
برای اطلاعات بیشتر به
تاریخچه و مجوز مراجعه کنید.
بنیاد نرمافزار پایتون یک شرکت غیرانتفاعی است.
لطفاً کمک مالی کنید.
آخرین بهروزرسانی در نوامبر 12, 2026 (06:19 UTC).
آیا
اشکالی یافتید؟
ساخته شده با
Sphinx 9.1.0.