3. مدل داده

3.1. اشیاء، مقادیر و انواع

اشیاء <Objects> انتزاع پایتون برای داده‌ها هستند. تمام داده‌ها در یک برنامه پایتون به‌وسیله اشیاء یا روابط میان اشیاء نمایش داده می‌شوند. حتی کد نیز به‌وسیله اشیاء نمایش داده می‌شود.

هر شیء یک هویت، یک نوع و یک مقدار دارد. هویت یک شیء پس از ایجاد شدن هرگز تغییر نمی‌کند؛ می‌توانید آن را به‌عنوان نشانی شیء در حافظه در نظر بگیرید. عملگر is هویت دو شیء را مقایسه می‌کند؛ تابع id() عدد صحیحی را برمی‌گرداند که نشان‌دهنده‌ی هویت آن است.

در CPython، id(x) نشانی حافظه‌ای است که x در آن ذخیره شده است.

نوع یک شیء عملیاتی را که آن شیء از آن‌ها پشتیبانی می‌کند (برای مثال، «آیا طول دارد؟») تعیین می‌کند و همچنین مقادیر ممکن برای اشیاء آن نوع را تعریف می‌کند. تابع type() نوع یک شیء را برمی‌گرداند (که خود یک شیء است). همانند هویت یک شیء، type آن نیز تغییرناپذیر است. [1]

مقدار برخی شیء‌ها می‌تواند تغییر کند. به اشیایی که مقدارشان می‌تواند تغییر کند، تغییرپذیر گفته می‌شود؛ به اشیایی که مقدارشان پس از ایجاد شدن تغییرناپذیر است، تغییرناپذیر نامیده می‌شوند. (مقدار یک شیء ظرف تغییرناپذیر که شامل ارجاعی به یک شیء تغییرپذیر است، می‌تواند وقتی مقدار شیء اخیر تغییر کند، تغییر کند؛ با این حال آن ظرف همچنان تغییرناپذیر در نظر گرفته می‌شود، زیرا مجموعه اشیایی که در بر دارد نمی‌تواند تغییر کند. بنابراین، تغییرناپذیری به‌طور دقیق همان داشتن مقدار تغییرناپذیر نیست، بلکه موضوع ظریف‌تری است.) تغییرپذیری یک شیء توسط نوع آن تعیین می‌شود؛ برای نمونه، اعداد، رشته‌ها و تاپل‌ها تغییرناپذیرند، در حالی که دیکشنری‌ها و فهرست‌ها تغییرپذیرند.

اشیاء هرگز به‌صورت صریح تخریب نمی‌شوند؛ با این حال، هنگامی که غیرقابل‌دسترس شوند، ممکن است زباله‌روبی شوند. یک پیاده‌سازی مجاز است زباله‌روبی را به تعویق بیندازد یا به‌کلی از آن صرف‌نظر کند --- اینکه زباله‌روبی چگونه پیاده‌سازی می‌شود، موضوعی مربوط به کیفیت پیاده‌سازی است، به شرطی که هیچ شیء‌ای که هنوز قابل‌دسترس است جمع‌آوری نشود.

CPython در حال حاضر از یک سازوکار شمارش ارجاع با تشخیص با تأخیر (اختیاری) زباله‌های دارای پیوند حلقه‌ای استفاده می‌کند، که بیشتر اشیاء را به‌محض غیرقابل‌دسترس شدن جمع‌آوری می‌کند، اما تضمینی برای جمع‌آوری زباله‌های حاوی ارجاع‌های حلقه‌ای وجود ندارد. برای اطلاعات درباره کنترل جمع‌آوری زباله‌های حلقه‌ای، مستندات ماژول gc را ببینید. پیاده‌سازی‌های دیگر رفتار متفاوتی دارند و ممکن است CPython تغییر کند. به نهایی‌سازی فوری اشیاء هنگام غیرقابل‌دسترس شدن آن‌ها وابسته نباشید (بنابراین باید همیشه پرونده‌ها را به‌صراحت ببندید).

توجه داشته باشید که استفاده از امکانات ردگیری یا اشکال‌زدایی پیاده‌سازی ممکن است اشیایی را که در حالت عادی قابل جمع‌آوری بودند، زنده نگه دارد. همچنین توجه داشته باشید که گرفتن یک استثنا با یک دستور try...except ممکن است اشیایی را زنده نگه دارد.

برخی شیء‌ها حاوی ارجاعات به منابع «خارجی» مانند پرونده‌های باز یا پنجره‌ها هستند. فرض بر این است که این منابع هنگام زباله‌روبی شیء آزاد می‌شوند، اما از آنجا که وقوع زباله‌روبی تضمین نمی‌شود، چنین اشیایی همچنین یک راه صریح برای آزاد کردن منبع خارجی ارائه می‌دهند، که معمولاً یک متد close() است. به‌شدت توصیه می‌شود که برنامه‌ها چنین اشیایی را به‌صورت صریح ببندند. دستور try...finally و دستور with راه‌های مناسبی برای این کار فراهم می‌کنند.

برخی اشیاء شامل ارجاع‌هایی به اشیاء دیگر هستند؛ به این اشیاء ظرف گفته می‌شود. نمونه‌هایی از ظرف‌ها عبارت‌اند از تاپل‌ها، فهرست‌ها و دیکشنری‌ها. این ارجاع‌ها بخشی از مقدار یک ظرف هستند. در بیشتر موارد، وقتی از مقدار یک ظرف صحبت می‌کنیم، منظور ما مقدارها است، نه هویت‌های اشیاء درون آن؛ اما وقتی از تغییرپذیری یک ظرف صحبت می‌کنیم، فقط هویت‌های اشیایی که مستقیماً در آن قرار دارند منظور است. بنابراین، اگر یک ظرف تغییرناپذیر (مانند یک تاپل) شامل ارجاعی به یک شیء تغییرپذیر باشد، با تغییر آن شیء تغییرپذیر، مقدار آن ظرف تغییر می‌کند.

انواع تقریباً بر تمام جنبه‌های رفتار شیء تأثیر می‌گذارند. حتی اهمیت هویت شیء نیز به‌معنایی تحت تأثیر قرار می‌گیرد: برای انواع تغییرناپذیر، عملیاتی که مقادیر جدیدی را محاسبه می‌کنند ممکن است در واقع ارجاعی به هر شیء موجودی با همان نوع و مقدار را برگردانند، در حالی که برای اشیای تغییرپذیر این کار مجاز نیست. برای مثال، پس از a = 1; b = 1، بسته به پیاده‌سازی، ممکن است a و b به شیء یکسانی با مقدار ۱ ارجاع دهند یا ندهند. دلیل آن این است که int یک نوع تغییرناپذیر است، بنابراین می‌توان ارجاع به 1 را دوباره استفاده کرد. این رفتار به پیاده‌سازی استفاده‌شده بستگی دارد، بنابراین نباید به آن اتکا کرد، اما نکته‌ای است که هنگام استفاده از آزمون‌های هویت شیء باید از آن آگاه بود. با این حال، پس از c = []; d = []، تضمین می‌شود که c و d به دو فهرست خالی متفاوت و یکتا که به‌تازگی ایجاد شده‌اند ارجاع می‌دهند. (توجه داشته باشید که e = f = [] شیء یکسان را به هر دو e و f اختصاص می‌دهد.)

3.2. سلسله‌مراتب انواع استاندارد

در زیر فهرستی از انواع توکار پایتون آمده است. ماژول‌های توسعه (که بسته به پیاده‌سازی، به زبان C، Java یا زبان‌های دیگر نوشته شده‌اند) می‌توانند انواع بیشتری تعریف کنند. نسخه‌های آینده پایتون ممکن است انواعی را به سلسله‌مراتب انواع اضافه کنند (مانند اعداد گویا، آرایه‌هایی از اعداد صحیح با ذخیره‌سازی کارآمد و غیره)، اگرچه چنین افزودنی‌هایی اغلب به‌جای آن از طریق کتابخانه استاندارد ارائه خواهند شد.

برخی از توصیف‌های نوع در زیر شامل پاراگرافی هستند که «ویژگی‌های خاص» را فهرست می‌کند. این‌ها ویژگی‌هایی هستند که دسترسی به پیاده‌سازی را فراهم می‌کنند و برای استفاده عمومی در نظر گرفته نشده‌اند. تعریف آن‌ها ممکن است در آینده تغییر کند.

3.2.1. None

این نوع تنها یک مقدار دارد. تنها یک شیء با این مقدار وجود دارد. این شیء از طریق نام توکار None قابل دسترسی است. از آن برای نشان دادن نبود یک مقدار در موقعیت‌های بسیاری استفاده می‌شود، برای مثال، این مقدار از توابعی که به‌طور صریح چیزی را برنمی‌گردانند، برگردانده می‌شود. مقدار حقیقت آن نادرست است.

3.2.2. NotImplemented

این نوع یک مقدار واحد دارد. تنها یک شیء با این مقدار وجود دارد. این شیء از طریق نام توکار NotImplemented قابل دسترسی است. متدهای عددی و متدهای مقایسه‌ی غنی، اگر عملیات را برای عملوندهای ارائه‌شده پیاده‌سازی نمی‌کنند، باید این مقدار را برگردانند. (مفسر سپس بسته به عملگر، عملیات بازتابی یا راه‌حل جایگزین دیگری را امتحان می‌کند.) این مقدار نباید در یک زمینه‌ی بولی ارزیابی شود.

برای جزئیات بیشتر، پیاده‌سازی عملیات حسابی را ببینید.

تغییر یافته در نسخه‌ی 3.9: ارزیابی NotImplemented در زمینه‌ی بولی منسوخ شد.

تغییر یافته در نسخه‌ی 3.14: ارزیابی NotImplemented در زمینه‌ی بولی اکنون یک TypeError پرتاب می‌کند. این مقدار پیش‌تر به True ارزیابی می‌شد و از پایتون 3.9 یک DeprecationWarning نشان می‌داد.

3.2.3. سه‌نقطه (Ellipsis)

این نوع تنها یک مقدار دارد. تنها یک شیء با این مقدار وجود دارد. به این شیء از طریق لفظی ... یا نام توکار Ellipsis دسترسی پیدا می‌شود. مقدار صدق آن درست است.

3.2.4. numbers.Number

این‌ها توسط مقادیر لفظی عددی ایجاد می‌شوند و به‌وسیله‌ی عملگرهای حسابی و توابع توکار حسابی به‌عنوان نتیجه برگردانده می‌شوند. اشیاء عددی تغییرناپذیر هستند؛ پس از ایجاد، مقدار آن‌ها هرگز تغییر نمی‌کند. البته اعداد پایتون به‌شدت با اعداد ریاضی مرتبط هستند، اما مشمول محدودیت‌های بازنمایی عددی در رایانه‌ها هستند.

بازنمایی‌های رشته‌ای کلاس‌های عددی، که توسط __repr__() و __str__() محاسبه می‌شوند، دارای ویژگی‌های زیر هستند:

  • آن‌ها لیترال‌های عددی معتبری هستند که هنگام ارسال به سازنده‌ی کلاسشان، یک شیء با مقدار عددی اصلی تولید می‌کنند.

  • نمایش، در صورت امکان، در مبنای ۱۰ است.

  • صفرهای آغازین، به‌جز احتمالاً یک صفر پیش از نقطه اعشار، نمایش داده نمی‌شوند.

  • صفرهای انتهایی، به‌جز احتمالاً یک صفر پس از نقطه‌ی اعشار، نمایش داده نمی‌شوند.

  • علامت فقط زمانی نمایش داده می‌شود که عدد منفی باشد.

پایتون میان اعداد صحیح، اعداد ممیز شناور و اعداد مختلط تمایز قائل می‌شود:

3.2.4.1. numbers.Integral

این‌ها نشان‌دهنده‌ی عناصری از مجموعه‌ی ریاضی اعداد صحیح (مثبت و منفی) هستند.

توجه

هدف از قوانین بازنمایی اعداد صحیح، ارائه معنادارترین تفسیر از عملیات شیفت و نقاب بر روی اعداد صحیح منفی است.

دو نوع عدد صحیح وجود دارد:

اعداد صحیح (int)

این‌ها اعداد را در محدوده‌ای نامحدود نشان می‌دهند و تنها به حافظه (مجازی) در دسترس محدود هستند. برای عملیات شیفت و نقاب، نمایش دودویی فرض می‌شود و اعداد منفی به‌صورت گونه‌ای از مکمل ۲ نمایش داده می‌شوند که گویی رشته‌ای بی‌نهایت از بیت‌های علامت به سمت چپ امتداد دارد.

بولی‌ها (bool)

این‌ها نماینده‌ی مقادیر صدق False و True هستند. دو شیء نماینده‌ی مقادیر False و True، تنها اشیای بولی هستند. نوع بولی، زیرنوعی از نوع عدد صحیح است و مقادیر بولی تقریباً در همه‌ی زمینه‌ها به‌ترتیب مانند مقادیر ۰ و ۱ رفتار می‌کنند، به این استثنا که وقتی به یک رشته تبدیل شوند، به‌ترتیب رشته‌های "False" یا "True" برگردانده می‌شوند.

3.2.4.2. numbers.Real (float)

این‌ها نشان‌دهنده اعداد ممیز شناور با دقت مضاعف در سطح ماشین هستند. شما برای محدوده پذیرفته‌شده و مدیریت سرریز به معماری ماشین زیربنایی (و پیاده‌سازی C یا Java) وابسته هستید. پایتون از اعداد ممیز شناور با دقت منفرد پشتیبانی نمی‌کند؛ صرفه‌جویی در مصرف پردازنده و حافظه که معمولاً دلیل استفاده از این موارد است، در برابر سربار استفاده از اشیاء در پایتون ناچیز می‌شود، بنابراین دلیلی برای پیچیده کردن زبان با دو نوع عدد ممیز شناور وجود ندارد.

3.2.4.3. numbers.Complex (complex)

این موارد اعداد مختلط را به‌صورت یک جفت عدد ممیز شناور با دقت مضاعف در سطح ماشین نشان می‌دهند. همان ملاحظات مربوط به اعداد ممیز شناور در اینجا نیز صدق می‌کند. بخش‌های حقیقی و موهومی یک عدد مختلط z را می‌توان از طریق ویژگی‌های فقط‌خواندنی z.real و z.imag بازیابی کرد.

3.2.5. دنباله‌ها

این موارد نشان‌دهنده‌ی مجموعه‌های متناهی مرتبی هستند که با اعداد غیرمنفی اندیس‌گذاری شده‌اند. تابع توکار len() تعداد آیتم‌های یک دنباله را برمی‌گرداند. هنگامی که طول یک دنباله n باشد، مجموعه‌ی اندیس شامل اعداد ۰، ۱، ...، n-۱ است. آیتم i از دنباله a با a[i] انتخاب می‌شود. برخی از دنباله‌ها، از جمله دنباله‌های توکار، اندیس‌های منفی را با افزودن طول دنباله تفسیر می‌کنند. برای مثال، a[-2] برابر با a[n-2] است، یعنی دومین آیتم از انتهای دنباله a با طول n.

مقدار حاصل باید یک عدد صحیح نامنفی کمتر از تعداد آیتم‌های دنباله باشد. در غیر این صورت، یک IndexError پرتاب می‌شود.

دنباله‌ها همچنین از اسلایس پشتیبانی می‌کنند: a[start:stop] تمام آیتم‌هایی با اندیس k را انتخاب می‌کند، به‌طوری که start <= k < stop باشد. هنگامی که به‌عنوان عبارت استفاده شود، یک اسلایس دنباله‌ای از همان نوع است. کامنت بالا درباره‌ی اندیس‌های منفی، درباره‌ی موقعیت‌های منفی اسلایس نیز صدق می‌کند. توجه داشته باشید که اگر یک موقعیت اسلایس کمتر از ۰ یا بزرگ‌تر از طول دنباله باشد، هیچ خطایی پرتاب نمی‌شود.

اگر start موجود نباشد یا None باشد، اسلایس چنان رفتار می‌کند که گویی start صفر بوده است. اگر stop موجود نباشد یا None باشد، اسلایس چنان رفتار می‌کند که گویی stop برابر با طول دنباله بوده است.

برخی از دنباله‌ها نیز از «اسلایس گسترده (extended slicing)» با یک پارامتر سوم «گام (step)» پشتیبانی می‌کنند: a[i:j:k] تمام آیتم‌های a را با اندیس x انتخاب می‌کند، که در آن x = i + n*k، n >= 0 و i <= x < j است.

دنباله‌ها بر اساس تغییرپذیری خود متمایز می‌شوند:

3.2.5.1. دنباله‌های تغییرناپذیر

یک شیء از نوع دنباله‌ای تغییرناپذیر، پس از ایجاد نمی‌تواند تغییر کند. (اگر شیء شامل ارجاع‌هایی به اشیای دیگر باشد، آن اشیای دیگر ممکن است تغییرپذیر باشند و بتوان آن‌ها را تغییر داد؛ با این حال، مجموعه‌ی اشیایی که یک شیء تغییرناپذیر مستقیماً به آن‌ها ارجاع دارد، نمی‌تواند تغییر کند.)

انواع زیر دنباله‌های تغییرناپذیر هستند:

رشته‌ها

یک رشته (str) دنباله‌ای از مقادیر است که نویسه‌ها <characters>، یا به‌طور رسمی‌تر، نقاط کد یونیکد را نشان می‌دهند. همه‌ی نقاط کد در بازه‌ی 0 تا 0x10FFFF را می‌توان در یک رشته نمایش داد.

پایتون یک نوع اختصاصی برای نویسه ندارد. در عوض، هر نقطه‌کد در رشته به‌عنوان یک شیء رشته با طول 1 نمایش داده می‌شود.

تابع توکار ord() یک نقطه کد را از صورت رشته‌ای آن به یک عدد صحیح در بازه‌ی 0 تا 0x10FFFF تبدیل می‌کند؛ chr() یک عدد صحیح در بازه‌ی 0 تا 0x10FFFF را به شیء رشته‌ای متناظر به طول 1 تبدیل می‌کند. می‌توان از str.encode() برای تبدیل یک str به bytes با استفاده از کدگذاری متن داده‌شده استفاده کرد، و می‌توان از bytes.decode() برای دستیابی به عمل معکوس استفاده کرد.

تاپل‌ها

آیتم‌های یک tuple، اشیای دلخواه پایتون هستند. تاپل‌های دارای دو یا چند آیتم با فهرست‌هایی از عبارت‌ها که با کاما از هم جدا شده‌اند تشکیل می‌شوند. یک تاپل با یک آیتم (یک «تک‌عضوی») می‌تواند با افزودن یک کاما به یک عبارت تشکیل شود (یک عبارت به‌تنهایی یک تاپل ایجاد نمی‌کند، زیرا باید بتوان از پرانتزها برای گروه‌بندی عبارت‌ها استفاده کرد). یک تاپل خالی می‌تواند با یک جفت پرانتز خالی تشکیل شود.

بایت‌ها

شیء bytes یک آرایه تغییرناپذیر است. آیتم‌ها بایت‌های ۸ بیتی هستند که با اعداد صحیح در بازه‌ی 0 <= x < 256 نمایش داده می‌شوند. مقادیر لفظی bytes (مانند b'abc') و سازنده توکار bytes() را می‌توان برای ایجاد اشیاء bytes استفاده کرد. همچنین، اشیاء bytes را می‌توان از طریق متد decode() به رشته‌ها کدگشایی کرد.

3.2.5.2. دنباله‌های تغییرپذیر

دنباله‌های تغییرپذیر را می‌توان پس از ایجاد شدن تغییر داد. از نمادگذاری‌های زیرنویسی و اسلایس می‌توان به‌عنوان هدف دستورهای انتساب و del (حذف) استفاده کرد.

توجه

ماژول‌های collections و array نمونه‌های بیشتری از انواع دنباله تغییرپذیر ارائه می‌دهند.

در حال حاضر دو نوع دنباله تغییرپذیر ذاتی وجود دارد:

فهرست‌ها

آیتم‌های یک فهرست، اشیای دلخواه پایتون هستند. فهرست‌ها با قرار دادن فهرستی از عبارت‌ها که با کاما از هم جدا شده‌اند، بین کروشه‌ها تشکیل می‌شوند. (توجه داشته باشید که برای تشکیل فهرست‌هایی با طول ۰ یا ۱ به حالت خاصی نیاز نیست.)

آرایه‌های بایت

یک شیء bytearray یک آرایه تغییرپذیر است. این اشیاء با سازنده توکار bytearray() ایجاد می‌شوند. جدای از تغییرپذیر بودن (و بنابراین هش‌ناپذیر (unhashable))، آرایه‌های بایتی در بقیه موارد همان رابط و عملکرد اشیاء تغییرناپذیر bytes را ارائه می‌دهند.

3.2.6. انواع مجموعه

این‌ها نشان‌دهنده‌ی مجموعه‌های متناهی و بدون ترتیب از اشیای یکتا و تغییرناپذیر هستند. به همین دلیل، نمی‌توان آن‌ها را با هیچ زیرنویسی اندیس‌گذاری کرد. با این حال، می‌توان آن‌ها را پیمایش کرد، و تابع توکار len() تعداد آیتم‌های موجود در یک مجموعه را برمی‌گرداند. از کاربردهای رایج مجموعه‌ها می‌توان به بررسی سریع عضویت، حذف موارد تکراری از یک دنباله، و محاسبه‌ی عملیات ریاضی مانند اشتراک، اجتماع، تفاوت، و تفاوت متقارن اشاره کرد.

برای عناصر مجموعه، همان قواعد تغییرناپذیری کلیدهای دیکشنری اعمال می‌شود. توجه داشته باشید که انواع عددی از قواعد عادی مقایسه عددی پیروی می‌کنند: اگر دو عدد در مقایسه برابر باشند (مثلاً 1 و 1.0)، تنها یکی از آن‌ها می‌تواند در یک مجموعه قرار داشته باشد.

در حال حاضر دو نوع مجموعه‌ی درونی وجود دارد:

مجموعه‌ها

این‌ها نشان‌دهنده‌ی یک مجموعه‌ی تغییرپذیر هستند. آن‌ها با سازنده‌ی توکار set() ایجاد می‌شوند و سپس می‌توان آن‌ها را با چندین متد، مانند add()، تغییر داد.

مجموعه‌های فریزشده

این‌ها نشان‌دهنده‌ی یک مجموعه تغییرناپذیر هستند. آن‌ها به‌وسیله‌ی سازنده‌ی توکار frozenset() ایجاد می‌شوند. از آنجا که frozenset تغییرناپذیر و هش‌پذیر است، می‌تواند دوباره به‌عنوان عنصری از مجموعه‌ای دیگر، یا به‌عنوان کلید دیکشنری استفاده شود.

3.2.7. نگاشت‌ها

این‌ها نشان‌دهنده مجموعه‌های متناهی از اشیای اندیس‌دهی‌شده با مجموعه‌های اندیس دلخواه هستند. نمادگذاری اندیس‌دهی a[k] آیتمی را که با k از نگاشت a اندیس‌دهی شده است انتخاب می‌کند؛ می‌توان از آن در عبارت‌ها و به‌عنوان هدف انتساب‌ها یا دستورات del استفاده کرد. تابع توکار len() تعداد آیتم‌های یک نگاشت را برمی‌گرداند.

در حال حاضر تنها یک نوع نگاشت ذاتی وجود دارد:

3.2.7.1. دیکشنری‌ها

این‌ها مجموعه‌های متناهی از اشیاء را نشان می‌دهند که با مقادیر تقریباً دلخواه اندیس‌دهی شده‌اند. تنها انواع مقادیری که به‌عنوان کلید قابل‌قبول نیستند، مقادیری هستند که حاوی فهرست‌ها، دیکشنری‌ها یا سایر انواع تغییرپذیری باشند که به‌جای هویت شیء، بر اساس مقدار مقایسه می‌شوند؛ دلیل این امر آن است که پیاده‌سازی کارآمد دیکشنری‌ها مستلزم آن است که مقدار هش یک کلید ثابت بماند. انواع عددی استفاده‌شده برای کلیدها از قواعد عادی مقایسه عددی پیروی می‌کنند: اگر دو عدد در مقایسه برابر باشند (مثلاً 1 و 1.0)، در این صورت می‌توانند به‌جای یکدیگر برای اندیس‌دهی به یک ورودی دیکشنری استفاده شوند.

دیکشنری‌ها ترتیب درج را حفظ می‌کنند، به این معنا که کلیدها به همان ترتیبی که به‌صورت متوالی در دیکشنری اضافه شده‌اند، تولید می‌شوند. جایگزینی یک کلید موجود، ترتیب را تغییر نمی‌دهد؛ اما حذف یک کلید و درج مجدد آن، به‌جای حفظ جایگاه قبلی‌اش، آن را به انتها اضافه می‌کند.

دیکشنری‌ها تغییرپذیرند؛ می‌توان آن‌ها را با نماد {} ایجاد کرد (بخش نمایش‌های دیکشنری را ببینید).

ماژول‌های توسعه‌ای dbm.ndbm و dbm.gnu نمونه‌های بیشتری از انواع نگاشت را ارائه می‌دهند، همان‌گونه که ماژول collections نیز چنین می‌کند.

تغییر یافته در نسخه‌ی 3.7: دیکشنری‌ها در نسخه‌های پایتون پیش از 3.6 ترتیب درج را حفظ نمی‌کردند. در CPython 3.6، ترتیب درج حفظ می‌شد، اما در آن زمان این موضوع به‌جای یک تضمین زبانی، یک جزئیات پیاده‌سازی در نظر گرفته می‌شد.

3.2.8. انواع فراخوانی‌پذیر

این‌ها انواعی هستند که عملیات فراخوانی تابع (به بخش فراخوانی‌ها مراجعه کنید) می‌تواند بر آن‌ها اعمال شود:

3.2.8.1. توابع تعریف‌شده توسط کاربر

یک شیء تابع تعریف‌شده توسط کاربر، با یک تعریف تابع ایجاد می‌شود (بخش تابع را ببینید). این تابع باید با فهرستی از آرگومان‌ها فراخوانی شود که تعداد آیتم‌های آن برابر با تعداد پارامترهای صوری تابع باشد.

3.2.8.1.1. ویژگی‌های خاص فقط‌خواندنی

ویژگی

معنی

function.__builtins__

ارجاعی به dictionary که فضای نام توکارهای تابع را نگه می‌دارد.

اضافه شده در نسخه‌ی 3.10.

function.__globals__

ارجاعی به دیکشنری که متغیرهای سراسری تابع را در خود نگه می‌دارد — فضای نام سراسری ماژولی که تابع در آن تعریف شده است.

function.__closure__

None یا یک tuple از سلول‌هایی که شامل اتصال‌هایی برای نام‌های مشخص‌شده در ویژگی co_freevars از شیء کد تابع هستند.

یک شیء سلول دارای ویژگی cell_contents است. می‌توان از آن برای دریافت مقدار سلول و همچنین تنظیم مقدار آن استفاده کرد.

3.2.8.1.2. ویژگی‌های ویژه قابل‌نوشتن

بیشتر این ویژگی‌ها نوع مقدار تخصیص‌داده‌شده را بررسی می‌کنند:

ویژگی

معنی

function.__doc__

رشته‌ی مستندسازی تابع، یا None اگر در دسترس نباشد.

function.__name__

نام تابع. همچنین ببینید: ویژگی‌های __name__.

function.__qualname__

نام کامل تابع. همچنین ببینید: ویژگی‌های __qualname__.

اضافه شده در نسخه‌ی 3.3.

function.__module__

نام ماژولی که تابع در آن تعریف شده است، یا None اگر در دسترس نباشد.

function.__defaults__

یک tuple شامل مقادیر پیش‌فرض پارامتر برای آن دسته از پارامترهایی که مقدار پیش‌فرض دارند، یا None در صورتی که هیچ پارامتری مقدار پیش‌فرض نداشته باشد.

function.__code__

شیء کد که بدنه‌ی تابع کامپایل‌شده را نشان می‌دهد.

function.__dict__

فضای نامی که از ویژگی‌های دلخواه تابع پشتیبانی می‌کند. همچنین ببینید: __dict__ attributes.

function.__annotations__

یک دیکشنری شامل حاشیه‌نویسی‌های پارامترها. کلیدهای دیکشنری، نام‌های پارامترها هستند و 'return' برای حاشیه‌نویسی بازگشت، در صورت ارائه شدن. همچنین ببینید: object.__annotations__.

تغییر یافته در نسخه‌ی 3.14: حاشیه‌نویسی‌ها اکنون به‌صورت تنبل ارزیابی می‌شوند. PEP 649 را ببینید.

function.__annotate__

annotate function برای این تابع، یا None اگر این تابع فاقد حاشیه‌نویسی باشد. object.__annotate__ را ببینید.

اضافه شده در نسخه‌ی 3.14.

function.__kwdefaults__

یک دیکشنری شامل مقادیر پیش‌فرض برای پارامترهای فقط کلیدواژه‌ای.

function.__type_params__

یک tuple شامل پارامترهای نوع یک تابع عام.

اضافه شده در نسخه‌ی 3.12.

اشیای تابعی همچنین از دریافت و تنظیم ویژگی‌های دلخواه پشتیبانی می‌کنند، که می‌توان از آن‌ها برای مثال برای اتصال فراداده به توابع استفاده کرد. برای دریافت و تنظیم چنین ویژگی‌هایی از سینتکس نقطه‌ای معمول ویژگی‌ها استفاده می‌شود.

پیاده‌سازی فعلی CPython فقط از ویژگی‌های تابع در توابع تعریف‌شده توسط کاربر پشتیبانی می‌کند. ممکن است در آینده از ویژگی‌های تابع در توابع توکار پشتیبانی شود.

اطلاعات بیشتری درباره تعریف یک تابع را می‌توان از شیء کد آن (قابل دسترسی از طریق ویژگی __code__) بازیابی کرد.

3.2.8.2. متدهای نمونه

یک شیء متد نمونه، یک کلاس، یک نمونه‌ی کلاس و هر شیء فراخوانی‌پذیر (معمولاً یک تابع تعریف‌شده توسط کاربر) را ترکیب می‌کند.

ویژگی‌های خاص فقط‌خواندنی:

method.__self__

به شیء نمونه کلاس اشاره می‌کند که متد به آن متصل است

method.__func__

به شیء تابع اصلی ارجاع می‌دهد

method.__doc__

مستندات متد (مشابه method.__func__.__doc__). اگر تابع اصلی رشته مستندسازی داشته باشد، یک رشته، در غیر این صورت None.

method.__name__

نام متد (همان method.__func__.__name__)

method.__module__

نام ماژولی که متد در آن تعریف شده است، یا None اگر در دسترس نباشد.

متدها همچنین از دسترسی (اما نه تنظیم) به ویژگی‌های دلخواه تابع در شیء تابع زیربنایی پشتیبانی می‌کنند.

اشیای متد تعریف‌شده توسط کاربر ممکن است هنگام دریافت یک ویژگی از یک کلاس (شاید از طریق یک نمونه از آن کلاس) ایجاد شوند، در صورتی که آن ویژگی یک شیء تابع تعریف‌شده توسط کاربر یا یک شیء classmethod باشد.

هنگامی که یک شیء متدِ نمونه با بازیابی یک شیء تابع تعریف‌شده توسط کاربر از یک کلاس از طریق یکی از نمونه‌های آن ایجاد می‌شود، ویژگی __self__ آن، همان نمونه است و شیء متد مقید نامیده می‌شود. ویژگی __func__ متد جدید، شیء تابع اصلی است.

هنگامی که یک شیء متد نمونه با بازیابی یک شیء classmethod از یک کلاس یا نمونه ایجاد می‌شود، ویژگی __self__ آن خود کلاس است، و ویژگی __func__ آن شیء تابعی است که زیربنای متد کلاس است.

هنگامی که یک شیء متد نمونه فراخوانی می‌شود، تابع زیربنایی (__func__) فراخوانی می‌شود و نمونه‌ی کلاس (__self__) در ابتدای فهرست آرگومان‌ها قرار می‌گیرد. برای مثال، وقتی C کلاسی باشد که شامل تعریفی برای تابع f() است و x نمونه‌ای از C باشد، فراخوانی x.f(1) معادل فراخوانی C.f(x, 1) است.

هنگامی که یک شیء متد نمونه از یک شیء classmethod مشتق شود، «نمونه کلاس» ذخیره‌شده در __self__ در واقع خود کلاس خواهد بود، بنابراین فراخوانی x.f(1) یا C.f(1) معادل فراخوانی f(C,1) است که در آن f تابع زیرین است.

توجه داشته باشید که توابع تعریف‌شده توسط کاربر که ویژگی‌های یک نمونه کلاس هستند، به متدهای مقید تبدیل نمی‌شوند؛ این اتفاق فقط زمانی رخ می‌دهد که تابع یک ویژگی کلاس باشد.

3.2.8.3. توابع تولیدگر

A function or method which contains a yield expression (see section عبارت‌های yield) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator's iterator.__next__() method will cause the function to execute until it provides a value using the yield expression. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned.

3.2.8.4. توابع هم‌روال

به تابع یا متدی که با استفاده از async def تعریف‌شده باشد، یک تابع هم‌روال <coroutine function> گفته می‌شود. چنین تابعی، هنگام فراخوانی، یک شیء هم‌روال برمی‌گرداند. این تابع ممکن است شامل عبارت‌های await، و همچنین دستورهای async with و async for باشد. همچنین بخش اشیاء هم‌روال را ببینید.

3.2.8.5. توابع تولیدگر ناهمگام

A function or method which is defined using async def and which contains a yield expression is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function.

فراخوانی متد aiterator.__anext__ پیمایش‌گری ناهمگام، یک awaitable را برمی‌گرداند که هنگامی که await شود، تا زمانی اجرا می‌شود که با استفاده از عبارت yield مقداری ارائه کند. هنگامی که تابع یک دستور return خالی را اجرا کند یا به انتهای خود برسد، استثنای StopAsyncIteration پرتاب می‌شود و پیمایش‌گری ناهمگام به پایان مجموعه‌ی مقادیری که باید yield شوند، رسیده است.

3.2.8.6. توابع توکار

یک شیء تابع توکار، دربرگیرنده‌ای برای یک تابع C است. نمونه‌هایی از توابع توکار عبارت‌اند از len() و math.sin() (math یک ماژول توکار استاندارد است). تعداد و نوع آرگومان‌ها توسط تابع C تعیین می‌شود. ویژگی‌های فقط‌خواندنی ویژه:

  • __doc__ رشته‌ی مستندسازی تابع است، یا None اگر در دسترس نباشد. function.__doc__ را ببینید.

  • __name__ نام تابع است. function.__name__ را ببینید.

  • __self__ روی None تنظیم می‌شود (اما آیتم بعدی را ببینید).

  • __module__ نام ماژولی است که تابع در آن تعریف شده است، یا اگر در دسترس نباشد None است. function.__module__ را ببینید.

3.2.8.7. متدهای توکار

این در واقع نمای متفاوتی از یک تابع توکار است و این بار شامل یک شیء است که به‌عنوان یک آرگومان اضافی ضمنی به تابع C ارسال می‌شود. نمونه‌ای از یک متد توکار alist.append() است، با فرض اینکه alist یک شیء فهرست باشد. در این حالت، ویژگی خاص فقط‌خواندنی __self__ به شیئی که alist به آن اشاره دارد تنظیم می‌شود. (این ویژگی همان معنایی را دارد که در سایر متدهای نمونه دارد.)

3.2.8.8. کلاس‌ها

کلاس‌ها فراخوانی‌پذیر هستند. این اشیاء معمولاً به‌عنوان کارخانه‌هایی برای نمونه‌های جدیدی از خودشان عمل می‌کنند، اما برای انواع کلاسی که __new__() را بازنویسی می‌کنند، تفاوت‌هایی ممکن است وجود داشته باشد. آرگومان‌های فراخوانی به __new__() و، در حالت معمول، به __init__() ارسال می‌شوند تا نمونه‌ی جدید مقداردهی اولیه شود.

3.2.8.9. نمونه‌های کلاس

نمونه‌های کلاس‌های دلخواه را می‌توان با تعریف یک متد __call__() در کلاس آن‌ها فراخوانی‌پذیر کرد.

3.2.9. ماژول‌ها

ماژول‌ها واحد پایه‌ی سازمان‌دهی کد پایتون هستند و توسط سامانه‌ی ایمپورت ایجاد می‌شوند؛ این سامانه یا با دستور import یا با فراخوانی توابعی مانند importlib.import_module() و تابع توکار __import__() فراخوانی می‌شود. یک شیء ماژول فضای نامی دارد که با یک شیء دیکشنری پیاده‌سازی شده است (این همان دیکشنری است که ویژگی __globals__ توابع تعریف‌شده در ماژول به آن ارجاع می‌دهد). ارجاع‌های ویژگی به جست‌وجوها در این دیکشنری تبدیل می‌شوند، برای مثال m.x معادل m.__dict__["x"] است. یک شیء ماژول شامل شیء کد مورد استفاده برای مقداردهی اولیه‌ی ماژول نمی‌شود (زیرا پس از انجام مقداردهی اولیه، دیگر به آن نیازی نیست).

انتساب ویژگی، دیکشنری فضای نام ماژول را به‌روزرسانی می‌کند، برای مثال m.x = 1 معادل m.__dict__["x"] = 1 است.

3.2.9.2. سایر ویژگی‌های قابل‌نوشتن در اشیاء ماژول

افزون بر ویژگی‌های مرتبط با ایمپورت که در بالا فهرست شدند، اشیاء ماژول همچنین دارای ویژگی‌های قابل‌نوشتن زیر نیز هستند:

module.__doc__

رشته مستندسازی ماژول، یا None در صورت عدم دسترسی. همچنین ببینید: __doc__ attributes.

module.__annotations__

دیکشنری شامل حاشیه‌نویسی‌های متغیر که در حین اجرای بدنه ماژول جمع‌آوری شده است. برای بهترین شیوه‌های کار با __annotations__، annotationlib را ببینید.

تغییر یافته در نسخه‌ی 3.14: حاشیه‌نویسی‌ها اکنون به‌صورت تنبل ارزیابی می‌شوند. PEP 649 را ببینید.

module.__annotate__

annotate function این ماژول، یا None اگر ماژول فاقد هرگونه حاشیه‌نویسی باشد. همچنین ببینید: ویژگی‌های __annotate__.

اضافه شده در نسخه‌ی 3.14.

3.2.9.3. دیکشنری‌های ماژول

اشیای ماژول همچنین دارای ویژگی خاص فقط‌خواندنی زیر هستند:

module.__dict__

فضای نام ماژول به‌صورت یک شیء دیکشنری. در میان ویژگی‌های فهرست‌شده در اینجا، __dict__ تنها ویژگی‌ای است که نمی‌توان به آن به‌عنوان یک متغیر سراسری از داخل یک ماژول دسترسی پیدا کرد؛ فقط می‌توان به‌عنوان یک ویژگی روی اشیای ماژول به آن دسترسی داشت.

به دلیل شیوه‌ای که CPython دیکشنری‌های ماژول را پاک می‌کند، دیکشنری ماژول زمانی که ماژول از محدوده خارج می‌شود پاک خواهد شد، حتی اگر دیکشنری هنوز دارای ارجاع‌های زنده باشد. برای جلوگیری از این موضوع، دیکشنری را کپی کنید یا تا زمانی که مستقیماً از دیکشنری آن استفاده می‌کنید، ماژول را نگه دارید.

3.2.10. کلاس‌های سفارشی

انواع کلاس سفارشی معمولاً با تعاریف کلاس ایجاد می‌شوند (بخش کلاس را ببینید). هر کلاس یک فضای نام دارد که با یک شیء دیکشنری پیاده‌سازی شده است. ارجاع‌ها به ویژگی‌های کلاس به جست‌وجوهایی در این دیکشنری تبدیل می‌شوند، برای مثال C.x به C.__dict__["x"] تبدیل می‌شود (اگرچه چند قلاب وجود دارند که امکان روش‌های دیگری برای یافتن ویژگی‌ها را فراهم می‌کنند). هنگامی که نام ویژگی در آنجا یافت نشود، جست‌وجوی ویژگی در کلاس‌های پایه ادامه می‌یابد. این جست‌وجو در کلاس‌های پایه از ترتیب حل متد C3 استفاده می‌کند که حتی در حضور ساختارهای وراثت «الماسی» (diamond) که در آن‌ها چندین مسیر وراثت به یک جد مشترک بازمی‌گردند، به‌درستی رفتار می‌کند. جزئیات بیشتر درباره‌ی C3 MRO مورد استفاده در پایتون را می‌توان در ترتیب حل متد در پایتون 2.3 یافت.

هرگاه ارجاع به یک ویژگی کلاس (مثلاً برای کلاس C) قرار باشد یک شیء متد کلاس بازگرداند، آن شیء به یک شیء متد نمونه تبدیل می‌شود که ویژگی __self__ آن C است. هرگاه قرار باشد یک شیء staticmethod بازگرداند، آن شیء به شیئی تبدیل می‌شود که شیء متد ایستا آن را دربرگرفته است. برای حالت دیگری که در آن ویژگی‌های بازیابی‌شده از یک کلاس ممکن است با ویژگی‌هایی که واقعاً در __dict__ آن قرار دارند متفاوت باشند، بخش پیاده‌سازی توصیف‌گرها را ببینید.

انتساب‌های ویژگی کلاس، دیکشنری کلاس را به‌روزرسانی می‌کنند و هرگز دیکشنری یک کلاس پایه را به‌روزرسانی نمی‌کنند.

می‌توان یک شیء کلاس را فراخوانی کرد (به بالا مراجعه کنید) تا یک نمونه کلاس حاصل شود (به پایین مراجعه کنید).

3.2.10.1. ویژگی‌های خاص

ویژگی

معنی

type.__name__

نام کلاس. همچنین ببینید: ویژگی‌های __name__.

type.__qualname__

نام کامل کلاس. همچنین ببینید: ویژگی‌های __qualname__.

type.__module__

نام ماژولی که کلاس در آن تعریف شده است.

type.__dict__

یک پراکسی نگاشت (mapping proxy) که نمایی فقط‌خواندنی از فضای نام کلاس فراهم می‌کند. همچنین ببینید: ویژگی‌های __dict__.

type.__bases__

یک tuple شامل پایه‌های کلاس. در بیشتر موارد، برای کلاسی که به‌صورت class X(A, B, C) تعریف شده باشد، X.__bases__ دقیقاً برابر با (A, B, C) خواهد بود.

type.__base__

تنها کلاس پایه در زنجیره وراثت که مسئول چیدمان حافظه نمونه‌ها است. این ویژگی در سطح C با tp_base متناظر است.

type.__doc__

رشته‌ی مستندسازی کلاس، یا None اگر تعریف‌نشده باشد. در زیرکلاس‌ها به ارث برده نمی‌شود.

type.__annotations__

دیکشنری حاوی حاشیه‌نویسی‌های متغیر که در طول اجرای بدنه کلاس جمع‌آوری شده‌اند. همچنین ببینید: __annotations__ attributes.

برای بهترین روش‌های کار با __annotations__، لطفاً annotationlib را ببینید. به جای دسترسی مستقیم به این ویژگی، از annotationlib.get_annotations() استفاده کنید.

هشدار

دسترسی مستقیم به ویژگی __annotations__ بر روی یک شیء کلاس ممکن است حاشیه‌نویسی‌هایی برای کلاس نادرست را برگرداند، به‌ویژه در موارد خاصی که کلاس، کلاس پایه‌ی آن، یا یک فراکلاس با from __future__ import annotations تعریف شده باشد. برای جزئیات 749 را ببینید.

این ویژگی در برخی کلاس‌های توکار وجود ندارد. در کلاس‌های تعریف‌شده توسط کاربر بدون __annotations__، این ویژگی یک دیکشنری خالی است.

تغییر یافته در نسخه‌ی 3.14: حاشیه‌نویسی‌ها اکنون به‌صورت تنبل ارزیابی می‌شوند. PEP 649 را ببینید.

type.__annotate__()

annotate function برای این کلاس، یا در صورتی که این کلاس annotation نداشته باشد، None. همچنین ببینید: ویژگی‌های __annotate__.

اضافه شده در نسخه‌ی 3.14.

type.__type_params__

یک tuple شامل پارامترهای نوع یک کلاس عام.

اضافه شده در نسخه‌ی 3.12.

type.__static_attributes__

یک tuple شامل نام ویژگی‌هایی از این کلاس است که توسط هر تابعی در بدنه‌ی آن از طریق self.X اختصاص داده می‌شوند.

اضافه شده در نسخه‌ی 3.13.

type.__firstlineno__

شماره‌ی خط نخستِ تعریف کلاس، از جمله دکوراتورها. تنظیم ویژگی __module__، آیتم __firstlineno__ را از دیکشنری نوع حذف می‌کند.

اضافه شده در نسخه‌ی 3.13.

type.__mro__

tuple از کلاس‌هایی که هنگام جست‌وجوی کلاس‌های پایه در حین حل متد در نظر گرفته می‌شوند.

3.2.10.2. متدهای ویژه

علاوه بر ویژگی‌های ویژه‌ای که در بالا شرح داده شد، دو متد زیر نیز برای تمام کلاس‌های پایتون در دسترس است:

type.mro()

یک فراکلاس می‌تواند این متد را بازنویسی کند تا ترتیب حل متد برای نمونه‌های آن سفارشی‌سازی شود. این متد در هنگام نمونه‌سازی از کلاس فراخوانی می‌شود، و نتیجه‌ی آن در __mro__ ذخیره می‌شود.

type.__subclasses__()

هر کلاس فهرستی از ارجاع‌های ضعیف به زیرکلاس‌های مستقیم خود نگه می‌دارد. این متد فهرستی از تمام آن ارجاع‌هایی که هنوز زنده هستند را برمی‌گرداند. این فهرست به ترتیب تعریف است. مثال:

>>> class A: pass
>>> class B(A): pass
>>> A.__subclasses__()
[<class 'B'>]

3.2.11. نمونه‌های کلاس

یک نمونه کلاس با فراخوانی یک شیء کلاس ایجاد می‌شود. یک نمونه کلاس دارای یک فضای نام است که به‌صورت یک دیکشنری پیاده‌سازی شده است و نخستین مکانی است که ارجاع‌های به ویژگی در آن جستجو می‌شوند. هنگامی که یک ویژگی در آنجا پیدا نشود و کلاس نمونه دارای ویژگی‌ای با آن نام باشد، جستجو با ویژگی‌های کلاس ادامه می‌یابد. اگر یک ویژگی کلاس پیدا شود که یک شیء تابع تعریف‌شده توسط کاربر باشد، آن به یک شیء متد نمونه تبدیل می‌شود که ویژگی __self__ آن همان نمونه است. اشیاء متد ایستا و متد کلاس نیز تبدیل می‌شوند؛ در بالا، ذیل «کلاس‌ها» را ببینید. برای راه دیگری که در آن ویژگی‌های یک کلاس که از طریق نمونه‌های آن بازیابی می‌شوند ممکن است با اشیایی که واقعاً در __dict__ کلاس ذخیره شده‌اند متفاوت باشند، بخش پیاده‌سازی توصیف‌گرها را ببینید. اگر هیچ ویژگی کلاس پیدا نشود و کلاس شیء دارای متد __getattr__() باشد، آن متد برای برآورده کردن جستجو فراخوانی می‌شود.

انتساب‌ها و حذف‌های ویژگی، دیکشنری نمونه را به‌روزرسانی می‌کنند و هرگز دیکشنری کلاس را به‌روزرسانی نمی‌کنند. اگر کلاس متد __setattr__() یا __delattr__() داشته باشد، این متد به‌جای به‌روزرسانی مستقیم دیکشنری نمونه فراخوانی می‌شود.

نمونه‌های کلاس می‌توانند در صورت داشتن متدهایی با نام‌های خاص معین، مانند اعداد، دنباله‌ها یا نگاشت‌ها رفتار کنند. به بخش نام متدهای ویژه مراجعه کنید.

3.2.11.1. ویژگی‌های خاص

object.__class__

کلاسی که یک نمونه‌ی کلاس به آن تعلق دارد.

object.__dict__

دیکشنری یا شیء نگاشت دیگری که برای ذخیره ویژگی‌های (قابل نوشتن) یک شیء استفاده می‌شود. همه نمونه‌ها دارای ویژگی __dict__ نیستند؛ برای جزئیات بیشتر، بخش __slots__ را ببینید.

3.2.12. اشیای ورودی/خروجی (که به اشیای پرونده نیز شناخته می‌شوند)

یک file object نمایانگر یک پرونده باز است. میان‌برهای مختلفی برای ایجاد اشیای پرونده در دسترس است: تابع توکار open()، و همچنین os.popen()، os.fdopen() و متد makefile() از اشیای سوکت (و شاید نیز از طریق سایر توابع یا متدهای ارائه‌شده توسط ماژول‌های توسعه).

اشیاء پرونده متدهای رایجی را که در زیر فهرست شده‌اند، پیاده‌سازی می‌کنند تا استفاده در کد عام ساده‌تر شود. انتظار می‌رود که مدیران زمینه‌ی دستور with باشند.

اشیاء sys.stdin، sys.stdout و sys.stderr به اشیاء پرونده‌ای متناظر با جریان‌های ورودی، خروجی و خطای استاندارد مفسر مقداردهی اولیه می‌شوند؛ همه‌ی آن‌ها در حالت متنی باز هستند و بنابراین از رابط تعریف‌شده توسط کلاس انتزاعی io.TextIOBase پیروی می‌کنند.

file.read(size=-1, /)

حداکثر به‌اندازه‌ی size داده از پرونده بازیابی می‌شود. برای سهولت، اگر size مشخص‌نشده باشد یا -1 باشد، تمام داده‌های موجود بازیابی می‌شود.

file.write(data, /)

data را در پرونده ذخیره کنید.

file.close()

هر بافری را تخلیه کنید و پرونده زیربنایی را ببندید.

3.2.13. انواع داخلی

چند نوع که به‌صورت داخلی توسط مفسر استفاده می‌شوند، در دسترس کاربر قرار می‌گیرند. تعریف آن‌ها ممکن است در نسخه‌های آینده مفسر تغییر کند، اما برای کامل بودن در اینجا ذکر شده‌اند.

3.2.13.1. اشیاء کد

اشیای کد نشان‌دهنده کد پایتون قابل‌اجرای بایت‌کامپایل‌شده، یا بایت‌کد هستند. تفاوت میان یک شیء کد و یک شیء تابع این است که شیء تابع شامل یک ارجاع صریح به سراسری‌های تابع (ماژولی که تابع در آن تعریف شده است) است، در حالی که شیء کد حاوی هیچ زمینه‌ای نیست؛ همچنین مقادیر پیش‌فرض آرگومان‌ها در شیء تابع ذخیره می‌شوند، نه در شیء کد (زیرا نشان‌دهنده مقادیری هستند که در ران‌تایم محاسبه می‌شوند). برخلاف اشیای تابع، اشیای کد تغییرناپذیرند و هیچ ارجاعی (مستقیم یا غیرمستقیم) به اشیای تغییرپذیر ندارند.

3.2.13.1.1. ویژگی‌های خاص فقط‌خواندنی
codeobject.co_name

نام تابع

codeobject.co_qualname

نام کامل تابع

اضافه شده در نسخه‌ی 3.11.

codeobject.co_argcount

تعداد کل پارامترهای جایگاهی تابع (شامل پارامترهای فقط جایگاهی و پارامترهای دارای مقادیر پیش‌فرض)

codeobject.co_posonlyargcount

تعداد پارامترهای فقط جایگاهی تابع (از جمله آرگومان‌های دارای مقادیر پیش‌فرض)

codeobject.co_kwonlyargcount

تعداد پارامترهای فقط کلیدواژه‌ای تابع (شامل آرگومان‌های دارای مقادیر پیش‌فرض)

codeobject.co_nlocals

تعداد متغیرهای محلی استفاده‌شده در تابع (شامل پارامترها)

codeobject.co_varnames

یک tuple شامل نام‌های متغیرهای محلی در تابع (که با نام پارامترها شروع می‌شود)

codeobject.co_cellvars

یک tuple شامل نام‌های متغیرهای محلی که از حداقل یک محدوده تودرتو درون تابع به آن‌ها ارجاع داده شده است

codeobject.co_freevars

یک tuple شامل نام‌های متغیرهای آزاد (بستار) است که یک محدوده تودرتو در یک محدوده بیرونی به آن‌ها ارجاع می‌دهد. همچنین function.__closure__ را ببینید.

توجه: ارجاع‌ها به نام‌های سراسری و توکار گنجانده نشده‌اند.

codeobject.co_code

رشته‌ای که نشان‌دهنده‌ی دنباله‌ی دستورالعمل‌های بایت‌کد در تابع است

codeobject.co_consts

یک tuple شامل مقادیر لفظی استفاده‌شده در بایت‌کد تابع

codeobject.co_names

یک tuple شامل نام‌هایی که توسط بایت‌کد در تابع استفاده می‌شوند

codeobject.co_filename

نام پرونده‌ای که کد از آن کامپایل شده است

codeobject.co_firstlineno

شماره‌ی اولین خط تابع

codeobject.co_lnotab

رشته‌ای که نگاشت از آفست‌های بایت‌کد به شماره‌های خط را کدگذاری می‌کند. برای جزئیات، به کد منبع مفسر مراجعه کنید.

منسوخ شده از نسخه‌ی 3.12: این ویژگی از اشیای کد منسوخ شده است و ممکن است در پایتون 3.15 حذف شود.

codeobject.co_stacksize

اندازه‌ی پشته‌ی مورد نیاز شیء کد

codeobject.co_flags

یک integer که تعدادی از پرچم‌های مفسر را کدگذاری می‌کند.

بیت‌های پرچم زیر برای co_flags تعریف شده‌اند: در صورتی که تابع از سینتکس *arguments برای پذیرش تعداد دلخواهی از آرگومان‌های جایگاهی استفاده کند، بیت 0x04 تنظیم می‌شود؛ در صورتی که تابع از سینتکس **keywords برای پذیرش آرگومان‌های کلیدواژه‌ای دلخواه استفاده کند، بیت 0x08 تنظیم می‌شود؛ در صورتی که تابع یک تولیدگر باشد، بیت 0x20 تنظیم می‌شود. برای جزئیات درباره‌ی معنای هر پرچمی که ممکن است وجود داشته باشد، به پرچم‌های بیتی اشیای کد مراجعه کنید.

اعلامیه‌های ویژگی‌های آینده (برای مثال، from __future__ import division) همچنین از بیت‌هایی در co_flags استفاده می‌کنند تا نشان دهند آیا یک شیء کد با فعال بودن یک ویژگی خاص کامپایل شده است یا خیر. compiler_flag را ببینید.

سایر بیت‌ها در co_flags برای استفاده‌ی داخلی محفوظ هستند.

اگر یک شیء کد نمایانگر یک تابع باشد و دارای یک رشته مستندسازی باشد، بیت CO_HAS_DOCSTRING در co_flags تنظیم می‌شود و اولین آیتم در co_consts، رشته مستندسازی تابع است.

3.2.13.1.2. متدهای اشیای کد
codeobject.co_positions()

یک پیمایش‌پذیر بر روی موقعیت‌های کد منبع هر دستور بایت‌کد در شیء کد برمی‌گرداند.

این پیمایش‌گر tuples شامل (start_line, end_line, start_column, end_column) را برمی‌گرداند. تاپل i-ام متناظر با موقعیت کد منبعی است که به واحد کد i-ام کامپایل شده است. اطلاعات ستون، آفست‌های بایتی utf-8 با اندیس‌گذاری از ۰ در خط منبع داده‌شده است.

این اطلاعات جایگاهی ممکن است وجود نداشته باشد. فهرستی غیرجامع از مواردی که ممکن است این اتفاق بیفتد:

  • اجرای مفسر با -X no_debug_ranges.

  • بارگذاری یک پرونده pyc که هنگام استفاده از -X no_debug_ranges کامپایل شده است.

  • تاپل‌های موقعیت متناظر با دستورالعمل‌های مصنوعی.

  • شماره‌های خط و ستونی که به دلیل محدودیت‌های خاص پیاده‌سازی نمی‌توانند بازنمایی شوند.

هنگامی که این اتفاق می‌افتد، برخی یا همه‌ی عناصر تاپل می‌توانند None باشند.

اضافه شده در نسخه‌ی 3.11.

توجه

این قابلیت نیازمند ذخیره‌سازی موقعیت‌های ستون در اشیای کد است که ممکن است منجر به افزایش جزئی مصرف دیسک پرونده‌های پایتون کامپایل‌شده یا مصرف حافظه مفسر شود. برای اجتناب از ذخیره‌سازی اطلاعات اضافی و/یا غیرفعال کردن چاپ اطلاعات اضافی ردگیری پشته، می‌توان از پرچم خط فرمان -X no_debug_ranges یا متغیر محیطی PYTHONNODEBUGRANGES استفاده کرد.

codeobject.co_lines()

یک پیمایش‌گر برمی‌گرداند که اطلاعاتی را درباره‌ی بازه‌های متوالی بایت‌کدs تولید می‌کند. هر آیتم تولیدشده یک tuple به‌صورت (start, end, lineno) است:

  • start (یک int) آفست شروع محدوده‌ی بایت‌کد را نشان می‌دهد (این آفست شامل خود مقدار است)

  • end (یک int) آفست (غیرشامل) پایان محدوده‌ی بایت‌کد را نشان می‌دهد

  • lineno یک int است که شماره‌ی خط محدوده‌ی بایت‌کد را نشان می‌دهد، یا اگر بایت‌کدهای محدوده‌ی داده‌شده شماره‌ی سطری نداشته باشند، None است

آیتم‌های تولیدشده ویژگی‌های زیر را خواهند داشت:

  • اولین بازه‌ی تولیدشده دارای start برابر با ۰ خواهد بود.

  • بازه‌های (start, end) غیرنزولی و متوالی خواهند بود. یعنی برای هر جفت tuplestart دومی برابر با end اولی خواهد بود.

  • هیچ بازه‌ای معکوس نخواهد بود: در تمام سه‌تایی‌ها end >= start است.

  • آخرین tuple تولیدشده دارای end برابر با اندازه‌ی بایت‌کد خواهد بود.

بازه‌های با عرض صفر، که در آن‌ها start == end است، مجاز هستند. بازه‌های با عرض صفر برای سطرهایی استفاده می‌شوند که در کد منبع وجود دارند، اما توسط کامپایلر بایت‌کد حذف شده‌اند.

اضافه شده در نسخه‌ی 3.10.

همچنین ملاحظه نمائید

PEP 626 - شماره‌های خط دقیق برای اشکال‌زدایی و سایر ابزارها.

PEP معرفی‌کننده‌ی متد co_lines().

codeobject.replace(**kwargs)

یک کپی از شیء کد با مقادیر جدید برای فیلدهای مشخص‌شده برمی‌گرداند.

تابع عام copy.replace() نیز از اشیای کد پشتیبانی می‌کند.

اضافه شده در نسخه‌ی 3.8.

3.2.13.2. اشیای فریم

اشیاء فریم نشان‌دهنده‌ی فریم‌های اجرا هستند. این اشیاء ممکن است در اشیاء ردگیری پشته ظاهر شوند و همچنین به توابع ردگیری ثبت‌شده ارسال شوند.

3.2.13.2.1. ویژگی‌های خاص فقط‌خواندنی
frame.f_back

به فریم پشته‌ی قبلی اشاره می‌کند (به سمت فراخواننده)، یا اگر این پایین‌ترین فریم پشته باشد، None است

frame.f_code

شیء کد در حال اجرا در این فریم. دسترسی به این ویژگی، یک رویداد حسابرسی object.__getattr__ را با آرگومان‌های obj و "f_code" پرتاب می‌کند.

frame.f_locals

نگاشتی که فریم برای جست‌وجوی متغیرهای محلی از آن استفاده می‌کند. اگر فریم به یک محدوده بهینه‌شده اشاره کند، ممکن است یک شیء پراکسی با نوشتن‌همزمان (write-through) برگردانده شود.

تغییر یافته در نسخه‌ی 3.13: یک پراکسی برای محدوده‌های بهینه‌شده بازمی‌گرداند.

frame.f_globals

دیکشنری استفاده‌شده توسط فریم برای جستجوی متغیرهای سراسری

frame.f_builtins

دیکشنری مورد استفاده فریم برای جستجوی نام‌های توکار (ذاتی)

frame.f_lasti

«دستورالعمل دقیق» شیء فریم (این اندیسی در رشته‌ی بایت‌کد شیء کد است)

frame.f_generator

شیء تولیدگر یا هم‌روال که مالک این فریم است، یا None اگر فریم یک تابع معمولی باشد.

اضافه شده در نسخه‌ی 3.14.

3.2.13.2.2. ویژگی‌های ویژه قابل‌نوشتن
frame.f_trace

اگر None نباشد، این یک تابع است که برای رویدادهای مختلف در حین اجرای کد فراخوانی می‌شود (این مورد توسط اشکال‌زداها استفاده می‌شود). معمولاً برای هر خط منبع جدید، یک رویداد فعال می‌شود (به f_trace_lines مراجعه کنید).

frame.f_trace_lines

این ویژگی را روی False تنظیم کنید تا راه‌اندازی یک رویداد ردگیری برای هر خط منبع غیرفعال شود.

frame.f_trace_opcodes

این ویژگی را روی True تنظیم کنید تا امکان درخواست رویدادهای به‌ازای هر opcode فراهم شود. توجه داشته باشید که اگر استثناهای پرتاب‌شده توسط تابع ردگیری به تابع در حال ردگیری راه یابند، ممکن است به رفتار تعریف‌نشده‌ی مفسر منجر شود.

frame.f_lineno

شماره خط جاری فریم — نوشتن در آن از درون یک تابع ردگیری (trace function)، باعث پرش به خط داده‌شده می‌شود (فقط برای پایین‌ترین فریم). یک اشکال‌زدا می‌تواند با نوشتن در این ویژگی، یک دستور Jump (معروف به Set Next Statement) را پیاده‌سازی کند.

3.2.13.2.3. متدهای شیء فریم

اشیای فریم از یک متد پشتیبانی می‌کنند:

frame.clear()

این متد تمام ارجاع‌ها به متغیرهای محلی را که فریم نگه‌داری می‌کند، پاک می‌کند. همچنین، اگر فریم به یک تولیدگر تعلق داشته باشد، تولیدگر نهایی‌سازی می‌شود. این کار به شکستن چرخه‌های ارجاع شامل اشیاء فریم کمک می‌کند (برای مثال هنگام گرفتن یک استثنا و ذخیره‌ی ردگیری پشته آن برای استفاده‌ی بعدی).

اگر فریم در حال حاضر در حال اجرا یا معلق باشد، RuntimeError پرتاب می‌شود.

اضافه شده در نسخه‌ی 3.4.

تغییر یافته در نسخه‌ی 3.13: تلاش برای پاک‌سازی یک فریم معلق، باعث پرتاب RuntimeError می‌شود (همان‌گونه که همواره در مورد فریم‌های در حال اجرا نیز صادق بوده است).

3.2.13.3. اشیای ردگیری پشته

اشیاء ردگیری نمایانگر ردگیری پشته‌ی یک استثنا هستند. یک شیء ردگیری به‌طور ضمنی هنگام رخ‌دادن یک استثنا ایجاد می‌شود، و همچنین می‌تواند به‌طور صریح با فراخوانی types.TracebackType ایجاد شود.

تغییر یافته در نسخه‌ی 3.7: اشیای ردگیری پشته اکنون می‌توانند به‌صورت صریح از کد پایتون نمونه‌سازی شوند.

در مورد ردگیری‌های پشته‌ای که به‌طور ضمنی ایجاد می‌شوند، هنگامی که جست‌وجو برای یک هندلر استثنا موجب باز شدن پشته‌ی اجرا می‌شود، در هر سطح بازشده یک شیء ردگیری پشته پیش از ردگیری پشته‌ی فعلی درج می‌شود. هنگامی که برنامه وارد یک هندلر استثنا می‌شود، ردگیری پشته در دسترس برنامه قرار می‌گیرد. (به بخش try مراجعه کنید.) این ردگیری پشته به‌عنوان سومین آیتم از تاپلی که sys.exc_info() برمی‌گرداند، و به‌عنوان ویژگی __traceback__ استثنای گرفته‌شده قابل دسترسی است.

هنگامی که برنامه فاقد هندلری مناسبی باشد، ردگیری پشته (به‌خوبی قالب‌بندی‌شده) به جریان خطای استاندارد نوشته می‌شود؛ اگر مفسر تعاملی باشد، این ردگیری پشته نیز به‌عنوان sys.last_traceback در اختیار کاربر قرار می‌گیرد.

برای ردگیری‌های پشته‌ای که به‌صراحت ایجاد می‌شوند، تعیین نحوه اتصال ویژگی‌های tb_next برای تشکیل یک ردگیری پشته کامل، بر عهده ایجادکننده ردگیری پشته است.

ویژگی‌های خاص فقط‌خواندنی:

traceback.tb_frame

به فریم اجرای سطح فعلی اشاره می‌کند.

دسترسی به این ویژگی، یک رویداد حسابرسی object.__getattr__ را با آرگومان‌های obj و "tb_frame" پرتاب می‌کند.

traceback.tb_lineno

شماره‌ی سطری که استثنا در آن رخ داده است را می‌دهد

traceback.tb_lasti

نشان‌دهنده‌ی «دستور دقیق» است.

شماره خط و آخرین دستور در ردگیری پشته ممکن است با شماره خطِ شیء فریم آن متفاوت باشد، اگر استثنا در یک دستور try بدون بند except منطبق یا با بند finally رخ داده باشد.

traceback.tb_next

ویژگی نوشتنی ویژه tb_next، سطح بعدی در ردگیری پشته (به سمت فریمی که استثنا در آن رخ داده است) است، یا اگر سطح بعدی وجود نداشته باشد، None است.

تغییر یافته در نسخه‌ی 3.7: این ویژگی اکنون قابل نوشتن است

3.2.13.4. اشیای اسلایس

از اشیای اسلایسی (slice) برای نمایش اسلایس‌ها در متدهای __getitem__() استفاده می‌شود. این اشیاء همچنین توسط تابع توکار slice() ایجاد می‌شوند.

ویژگی‌های فقط‌خواندنی ویژه: start کران پایین است؛ stop کران بالا است؛ step مقدار گام است؛ هرکدام در صورت حذف‌شدن None است. این ویژگی‌ها می‌توانند هر نوعی داشته باشند.

اشیای اسلایس از یک متد پشتیبانی می‌کنند:

slice.indices(self, length)

این متد یک آرگومان عدد صحیح به نام length می‌گیرد و اطلاعاتی درباره‌ی اسلایسی را محاسبه می‌کند که شیء اسلایس، در صورت اعمال بر دنباله‌ای با length آیتم، توصیف می‌کند. این متد یک تاپل از سه عدد صحیح برمی‌گرداند؛ این مقادیر به‌ترتیب اندیس‌های start و stop و step یا طول گام اسلایس هستند. اندیس‌های ناموجود یا خارج از محدوده به شیوه‌ای سازگار با اسلایس‌های معمولی مدیریت می‌شوند.

3.2.13.5. اشیای متد ایستا

اشیای متد ایستا راهی برای خنثی کردن تبدیل اشیای تابع به اشیای متد که در بالا توضیح داده شد، فراهم می‌کنند. یک شیء متد ایستا، پوششی برای هر شیء دیگر است، معمولاً یک شیء متد تعریف‌شده توسط کاربر. هنگامی که یک شیء متد ایستا از یک کلاس یا یک نمونه از کلاس بازیابی می‌شود، شیئی که واقعاً برگردانده می‌شود، شیء پوشیده‌شده است که مشمول هیچ تبدیل دیگری نمی‌شود. اشیای متد ایستا همچنین قابل فراخوانی هستند. اشیای متد ایستا توسط سازنده‌ی توکار staticmethod() ایجاد می‌شوند.

3.2.13.6. اشیای متد کلاس

یک شیء متد کلاس، مانند یک شیء متد ایستا، دربرگیرنده‌ای بر گرد شیء دیگری است که نحوه‌ی بازیابی آن شیء از کلاس‌ها و نمونه‌های کلاس را تغییر می‌دهد. رفتار اشیای متد کلاس در چنین بازیابی‌ای در بالا، ذیل "instance methods" توضیح داده شده است. اشیای متد کلاس با سازنده‌ی توکار classmethod() ایجاد می‌شوند.

3.3. نام متدهای ویژه

یک کلاس می‌تواند عملیات خاصی را که با سینتکس ویژه فراخوانی می‌شوند (مانند عملیات حسابی یا اندیس‌گذاری و اسلایس) با تعریف متدهایی با نام‌های ویژه پیاده‌سازی کند. این رویکرد پایتون به اضافه‌بارگذاری عملگر <operator overloading> (operator overloading) است و به کلاس‌ها اجازه می‌دهد رفتار خود را در قبال عملگرهای زبان تعریف کنند. برای نمونه، اگر کلاسی متدی به نام __getitem__() تعریف کند و x نمونه‌ای از این کلاس باشد، آنگاه x[i] تقریباً معادل type(x).__getitem__(x, i) است. به‌جز در مواردی که ذکر شده است، تلاش برای اجرای یک عملیات، هنگامی که متد مناسبی تعریف نشده باشد، باعث پرتاب یک استثنا می‌شود (معمولاً AttributeError یا TypeError).

تنظیم یک متد ویژه روی None نشان می‌دهد که عملیات متناظر در دسترس نیست. برای مثال، اگر کلاسی __iter__() را روی None تنظیم کند، آن کلاس پیمایش‌پذیر نیست، بنابراین فراخوانی iter() روی نمونه‌های آن، استثنای TypeError را پرتاب می‌کند (بدون بازگشت به __getitem__()). [2]

هنگام پیاده‌سازی کلاسی که هر نوع توکار را شبیه‌سازی می‌کند، مهم است که شبیه‌سازی تنها تا حدی پیاده‌سازی شود که برای شیء مدل‌سازی‌شده منطقی باشد. برای مثال، برخی دنباله‌ها ممکن است با بازیابی المان‌های منفرد به‌خوبی کار کنند، اما استخراج یک اسلایس ممکن است منطقی نباشد. (یک نمونه از این موارد، رابط NodeList در مدل اشیاء سند W3C است.)

3.3.1. سفارشی‌سازی پایه

object.__new__(cls[, ...])

برای ایجاد یک نمونه جدید از کلاس cls فراخوانی می‌شود. __new__() یک متد ایستا است (که به‌صورت یک حالت خاص در نظر گرفته شده است، بنابراین نیازی نیست آن را به‌عنوان متد ایستا اعلام کنید) که کلاسی را که نمونه‌ای از آن درخواست شده است به‌عنوان اولین آرگومان خود دریافت می‌کند. آرگومان‌های باقی‌مانده همان آرگومان‌هایی هستند که به عبارت سازنده‌ی شیء (فراخوانی کلاس) ارسال می‌شوند. مقدار بازگشتی __new__() باید نمونه جدید شیء باشد (معمولاً نمونه‌ای از cls).

پیاده‌سازی‌های معمول، یک نمونه جدید از کلاس را با فراخوانی متد __new__() ابرکلاس از طریق super().__new__(cls[, ...]) با آرگومان‌های مناسب ایجاد می‌کنند و سپس نمونه‌ی تازه ایجادشده را در صورت لزوم پیش از بازگرداندن آن اصلاح می‌کنند.

اگر __new__() در حین ساخت شیء فراخوانی شود و یک نمونه از cls را برگرداند، آنگاه متد __init__() نمونه جدید مانند __init__(self[, ...]) فراخوانی خواهد شد، که در آن self نمونه جدید است و آرگومان‌های باقی‌مانده همان‌هایی هستند که به سازنده شیء ارسال شده‌اند.

اگر __new__() نمونه‌ای از cls را برنگرداند، آنگاه متد __init__() آن نمونه جدید فراخوانی نخواهد شد.

__new__() عمدتاً به این منظور در نظر گرفته شده است که زیرکلاس‌های انواع تغییرناپذیر (مانند int، str یا tuple) بتوانند ایجاد نمونه را سفارشی‌سازی کنند. همچنین معمولاً در فراکلاس‌های سفارشی بازنویسی می‌شود تا ایجاد کلاس سفارشی‌سازی شود.

object.__init__(self[, ...])

پس از ایجاد نمونه (توسط __new__())، اما پیش از بازگرداندن آن به فراخواننده، فراخوانی می‌شود. آرگومان‌ها همان‌هایی هستند که به عبارت سازنده‌ی کلاس ارسال شده‌اند. اگر کلاس پایه دارای متد __init__() باشد، متد __init__() کلاس مشتق، در صورت وجود، باید به‌صراحت آن را فراخوانی کند تا مقداردهی اولیه‌ی صحیح بخش کلاس پایه‌ی نمونه تضمین شود؛ برای مثال: super().__init__([args...]).

از آنجا که __new__() و __init__() در ساخت اشیاء با هم کار می‌کنند (__new__() برای ایجاد آن، و __init__() برای سفارشی‌سازی آن)، هیچ مقداری غیر از None نباید توسط __init__() برگردانده شود؛ این کار باعث می‌شود یک TypeError در ران‌تایم پرتاب شود.

object.__del__(self)

هنگامی که نمونه در شرف نابودی است، فراخوانی می‌شود. به این متد همچنین نهایی‌ساز (finalizer) یا (به‌نادرستی) تخریب‌کننده نیز گفته می‌شود. اگر یک کلاس پایه دارای متد __del__() باشد، متد __del__() کلاس مشتق، در صورت وجود، باید به‌صراحت آن را فراخوانی کند تا حذف صحیح بخش کلاس پایه از نمونه تضمین شود.

این امکان وجود دارد (هرچند توصیه نمی‌شود!) که متد __del__() نابودی نمونه را با ایجاد ارجاعی جدید به آن به تعویق بیندازد. به این کار رستاخیز شیء گفته می‌شود. اینکه هنگامی که شیء رستاخیزیافته در آستانه نابودی است، __del__() برای بار دوم فراخوانی می‌شود یا خیر، وابسته به پیاده‌سازی است؛ پیاده‌سازی فعلی CPython آن را فقط یک بار فراخوانی می‌کند.

تضمینی وجود ندارد که متدهای __del__() برای اشیایی که هنگام خروج مفسر هنوز وجود دارند، فراخوانی شوند. weakref.finalize راه سرراستی برای ثبت یک تابع پاک‌سازی فراهم می‌کند تا هنگامی که یک شیء زباله‌روبی می‌شود، فراخوانی شود.

توجه

del x مستقیماً x.__del__() را فراخوانی نمی‌کند — اولی شمار ارجاع x را یک واحد کاهش می‌دهد، و دومی تنها زمانی فراخوانی می‌شود که شمار ارجاع x به صفر برسد.

ممکن است یک چرخه‌ی ارجاع مانع از صفر شدن شمار ارجاع یک شیء شود. در این حالت، این چرخه بعداً توسط زباله‌روبی حلقه‌ای شناسایی و حذف می‌شود. یکی از علل رایج چرخه‌های ارجاع این است که یک استثنا در یک متغیر محلی گرفته‌شده باشد. در این صورت، متغیرهای محلی فریم به آن استثنا ارجاع می‌دهند؛ آن استثنا به ردگیری پشته‌ی خودش ارجاع می‌دهد؛ و آن ردگیری پشته نیز به متغیرهای محلی تمام فریم‌های گرفته‌شده در ردگیری پشته ارجاع می‌دهد.

همچنین ملاحظه نمائید

مستندات ماژول gc.

هشدار

به دلیل شرایط ناپایداری که متدهای __del__() در آن‌ها فراخوانی می‌شوند، استثناهایی که در حین اجرای آن‌ها رخ می‌دهند نادیده گرفته می‌شوند و در عوض هشداری در sys.stderr چاپ می‌شود. به‌ویژه:

  • __del__() ممکن است هنگامی که کد دلخواهی در حال اجرا است فراخوانی شود، از جمله از هر نخ دلخواهی. اگر __del__() نیاز به گرفتن قفلی یا فراخوانی هر منبع مسدودکننده‌ی دیگری داشته باشد، ممکن است بن‌بست رخ دهد، زیرا ممکن است آن منبع از قبل توسط کدی گرفته شده باشد که برای اجرای __del__() وقفه خورده است.

  • __del__() ممکن است در جریان خاموش شدن مفسر اجرا شود. در نتیجه، ممکن است متغیرهای سراسری‌ای که برای دسترسی به آن‌ها نیاز دارد (از جمله ماژول‌های دیگر) پیش‌تر حذف شده یا روی None تنظیم شده باشند. پایتون تضمین می‌کند که متغیرهای سراسری‌ای که نامشان با یک زیرخط آغاز می‌شود، پیش از آنکه سایر متغیرهای سراسری حذف شوند، از ماژول خود حذف می‌شوند؛ اگر هیچ ارجاع دیگری به چنین متغیرهای سراسری‌ای وجود نداشته باشد، این موضوع می‌تواند به اطمینان از این‌که ماژول‌های ایمپورت‌شده در زمانی که متد __del__() فراخوانی می‌شود هنوز در دسترس هستند کمک کند.

object.__repr__(self)

توسط تابع توکار repr() فراخوانی می‌شود تا بازنمایی رشته‌ای «رسمی» یک شیء را محاسبه کند. تا حد امکان، این بازنمایی باید شبیه یک عبارت معتبر پایتون باشد که بتوان از آن برای بازسازی یک شیء با همان مقدار استفاده کرد (با فرض محیط مناسب). اگر این ممکن نیست، باید رشته‌ای به شکل <...some useful description...> برگردانده شود. مقدار بازگشتی باید یک شیء رشته باشد. اگر یک کلاس __repr__() را تعریف کند اما __str__() را تعریف نکند، آنگاه هنگامی که به بازنمایی رشته‌ای «غیررسمی» از نمونه‌های آن کلاس نیاز باشد، از __repr__() نیز استفاده می‌شود.

این معمولاً برای اشکال‌زدایی استفاده می‌شود، بنابراین مهم است که بازنمایی سرشار از اطلاعات و بدون ابهام باشد. یک پیاده‌سازی پیش‌فرض توسط خود کلاس object ارائه شده است.

object.__str__(self)

توسط str(object)، پیاده‌سازی پیش‌فرض __format__() و تابع توکار print() فراخوانی می‌شود تا بازنمایی رشته‌ای «غیررسمی» یا به‌خوبی قابل‌چاپ یک شیء را محاسبه کند. مقدار بازگشتی باید یک شیء str باشد.

این متد با object.__repr__() تفاوت دارد، زیرا انتظاری وجود ندارد که __str__() یک عبارت معتبر پایتون را برگرداند: می‌توان از یک بازنمایی مناسب‌تر یا مختصرتر استفاده کرد.

پیاده‌سازی پیش‌فرض تعریف‌شده توسط نوع توکار object، object.__repr__() را فراخوانی می‌کند.

object.__bytes__(self)

توسط bytes فراخوانی می‌شود تا بازنمایی رشته‌بایتی یک شیء را محاسبه کند. این متد باید یک شیء bytes برگرداند. خود کلاس object این متد را ارائه نمی‌دهد.

object.__format__(self, format_spec)

توسط تابع توکار format() فراخوانی می‌شود، و به‌تبع آن، در ارزیابی مقادیر لفظی رشته‌ای قالب‌بندی‌شده و متد str.format() نیز فراخوانی می‌شود تا یک نمایش رشته‌ای «قالب‌بندی‌شده» از یک شیء تولید کند. آرگومان format_spec رشته‌ای است که شامل توصیفی از گزینه‌های قالب‌بندی موردنظر است. تفسیر آرگومان format_spec بر عهده‌ی نوعی است که __format__() را پیاده‌سازی می‌کند، هرچند بیشتر کلاس‌ها یا قالب‌بندی را به یکی از انواع توکار محول می‌کنند، یا از سینتکس مشابهی برای گزینه‌های قالب‌بندی استفاده می‌کنند.

برای شرح سینتکس قالب‌بندی استاندارد، به زبان کوچک مشخصات قالب‌بندی مراجعه کنید.

مقدار بازگشتی باید یک شیء رشته‌ای باشد.

پیاده‌سازی پیش‌فرض کلاس object باید یک رشته‌ی format_spec خالی دریافت کند. این پیاده‌سازی به __str__() واگذار می‌شود.

تغییر یافته در نسخه‌ی 3.4: خود متد __format__ در object، در صورت دریافت هر رشته‌ی غیرخالی، یک TypeError پرتاب می‌کند.

تغییر یافته در نسخه‌ی 3.7: object.__format__(x, '') اکنون معادل str(x) است، نه format(str(x), '').

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

این‌ها متدهای به‌اصطلاح «مقایسه غنی» (rich comparison) هستند. تناظر میان نمادهای عملگر و نام متدها به این صورت است: x<y، x.__lt__(y) را فراخوانی می‌کند، x<=y، x.__le__(y) را فراخوانی می‌کند، x==y، x.__eq__(y) را فراخوانی می‌کند، x!=y، x.__ne__(y) را فراخوانی می‌کند، x>y، x.__gt__(y) را فراخوانی می‌کند، و x>=y، x.__ge__(y) را فراخوانی می‌کند.

یک متد مقایسه غنی (rich comparison method) ممکن است در صورتی که عملیات را برای یک جفت آرگومان داده‌شده پیاده‌سازی نکند، شیء یکتای NotImplemented را برگرداند. طبق قرارداد، برای یک مقایسه موفق، False و True برگردانده می‌شوند. با این حال، این متدها می‌توانند هر مقداری را برگردانند، بنابراین اگر عملگر مقایسه در یک زمینه بولی (به‌عنوان مثال، در شرط یک دستور if) استفاده شود، پایتون bool() را روی مقدار فراخوانی می‌کند تا تعیین کند که نتیجه درست است یا نادرست.

به‌طور پیش‌فرض، object __eq__() را با استفاده از is پیاده‌سازی می‌کند و در صورت مقایسه‌ی نادرست، NotImplemented را برمی‌گرداند: True if x is y else NotImplemented. برای __ne__()، به‌طور پیش‌فرض به __eq__() ارجاع می‌دهد و نتیجه را معکوس می‌کند، مگر آنکه نتیجه NotImplemented باشد. هیچ رابطه‌ی ضمنی دیگری میان عملگرهای مقایسه‌ای یا پیاده‌سازی‌های پیش‌فرض وجود ندارد؛ برای مثال، درست بودن (x<y or x==y) دلالتی بر x<=y ندارد. برای تولید خودکار عملیات‌های مرتب‌سازی از یک عملیات ریشه، @functools.total_ordering را ببینید.

به‌طور پیش‌فرض، کلاس object پیاده‌سازی‌هایی سازگار با مقایسه‌های مقدار ارائه می‌دهد: مقایسه برابری بر اساس هویت شیء انجام می‌شود، و مقایسه‌های ترتیبی TypeError را پرتاب می‌کنند. هر متد پیش‌فرض ممکن است این نتایج را مستقیماً تولید کند، اما همچنین ممکن است NotImplemented را برگرداند.

برای چند نکته‌ی مهم درباره‌ی ایجاد اشیای هش‌پذیر (hashable) که از عملیات مقایسه‌ی سفارشی پشتیبانی می‌کنند و به‌عنوان کلیدهای دیکشنری قابل استفاده هستند، پاراگراف مربوط به __hash__() را ببینید.

نسخه‌هایی با آرگومان‌های جابه‌جاشده برای این متدها وجود ندارد (برای استفاده در زمانی که آرگومان چپ از عملیات پشتیبانی نمی‌کند، اما آرگومان راست پشتیبانی می‌کند)؛ بلکه __lt__() و __gt__() بازتاب یکدیگرند، __le__() و __ge__() بازتاب یکدیگرند، و __eq__() و __ne__() بازتاب خودشان هستند. اگر عملوندها از انواع مختلف باشند و نوع عملوند راست زیرکلاس مستقیم یا غیرمستقیم از نوع عملوند چپ باشد، متد بازتابی عملوند راست اولویت دارد؛ در غیر این صورت، متد عملوند چپ اولویت دارد. زیرکلاس‌سازی مجازی در نظر گرفته نمی‌شود.

هرگاه هیچ متد مناسبی مقداری به‌جز NotImplemented برنگرداند، عملگرهای == و != به‌ترتیب به is و is not بازمی‌گردند.

object.__hash__(self)

توسط تابع توکار hash() و برای عملیات روی اعضای مجموعه‌های هش‌شده شامل set، frozenset و dict فراخوانی می‌شود. متد __hash__() باید یک عدد صحیح برگرداند. تنها ویژگی مورد نیاز این است که اشیایی که در مقایسه با هم برابر هستند، مقدار هش یکسانی داشته باشند؛ توصیه می‌شود مقادیر هش اجزای شیء را که در مقایسه کردن اشیاء نیز نقش دارند، با بسته‌بندی آن اجزا در یک تاپل و هش کردن تاپل، با هم ترکیب کنید. مثال:

def __hash__(self):
    return hash((self.name, self.nick, self.color))

توجه

hash() مقدار بازگشتی از متد سفارشی __hash__() یک شیء را به اندازه‌ی Py_ssize_t کوتاه می‌کند. این عرض معمولاً در ساخت‌های ۶۴ بیتی ۸ بایت و در ساخت‌های ۳۲ بیتی ۴ بایت است. اگر __hash__() یک شیء باید در ساخت‌هایی با اندازه‌های بیتی مختلف تعامل داشته باشد، حتماً عرض را در همه‌ی ساخت‌های پشتیبانی‌شده بررسی کنید. یک راه آسان برای این کار استفاده از python -c "import sys; print(sys.hash_info.width)" است.

اگر کلاسی متد __eq__() را تعریف نکند، نباید عملیات __hash__() را نیز تعریف کند؛ اگر __eq__() را تعریف کند اما __hash__() را تعریف نکند، نمونه‌های آن به‌عنوان آیتم در مجموعه‌های هش‌پذیر قابل استفاده نخواهند بود. اگر کلاسی اشیاء تغییرپذیر را تعریف کند و متد __eq__() را پیاده‌سازی کند، نباید __hash__() را پیاده‌سازی کند، زیرا پیاده‌سازی مجموعه‌های hashable ایجاب می‌کند که مقدار هش یک کلید تغییرناپذیر باشد (اگر مقدار هش شیء تغییر کند، در سطل هش اشتباه قرار خواهد گرفت).

کلاس‌های تعریف‌شده توسط کاربر به‌طور پیش‌فرض متدهای __eq__() و __hash__() را دارند (که از کلاس object به ارث رسیده‌اند)؛ با آن‌ها، همه‌ی اشیاء نابرابر مقایسه می‌شوند (به‌جز با خودشان) و x.__hash__() مقدار مناسبی برمی‌گرداند، به‌گونه‌ای که x == y مستلزم برقراری هر دو مورد x is y و hash(x) == hash(y) است.

کلاسی که __eq__() را بازتعریف می‌کند و __hash__() را تعریف نمی‌کند، __hash__() آن به‌طور ضمنی برابر None قرار می‌گیرد. هنگامی که متد __hash__() یک کلاس برابر None باشد، نمونه‌های آن کلاس وقتی برنامه‌ای تلاش کند مقدار هش آن‌ها را دریافت کند، یک TypeError مناسب را پرتاب می‌کنند و همچنین هنگام بررسی isinstance(obj, collections.abc.Hashable) به‌درستی به‌عنوان هش‌ناپذیر (unhashable) شناسایی می‌شوند.

اگر کلاسی که __eq__() را بازنویسی می‌کند نیاز داشته باشد پیاده‌سازی __hash__() از کلاس والد را حفظ کند، باید این موضوع به‌صراحت با تنظیم __hash__ = <ParentClass>.__hash__ به مفسر اعلام شود.

اگر کلاسی که __eq__() را بازنویسی نمی‌کند، بخواهد پشتیبانی از هش را غیرفعال کند، باید __hash__ = None را در تعریف کلاس قرار دهد. کلاسی که __hash__() خودش را به‌گونه‌ای تعریف می‌کند که صریحاً استثنای TypeError را پرتاب می‌کند، با یک فراخوانی isinstance(obj, collections.abc.Hashable) به‌اشتباه به‌عنوان هش‌پذیر شناسایی می‌شود.

توجه

به‌طور پیش‌فرض، مقادیر __hash__() برای اشیاء str و bytes با یک مقدار تصادفی غیرقابل‌پیش‌بینی «نمک‌زده» (salted) می‌شوند. اگرچه این مقادیر درون یک فرآیند پایتون منفرد ثابت می‌مانند، اما بین اجراهای مکرر پایتون قابل پیش‌بینی نیستند.

این موضوع برای محافظت در برابر محروم‌سازی از سرویس ناشی از ورودی‌های انتخاب‌شده با دقت که از بدترین حالت عملکرد درج در دیکشنری با پیچیدگی O(n2) سوءاستفاده می‌کنند، در نظر گرفته شده است. برای جزئیات https://ocert.org/advisories/ocert-2011-003.html را ببینید.

تغییر مقادیر هش بر ترتیب تکرار مجموعه‌ها تأثیر می‌گذارد. پایتون هرگز تضمینی درباره این ترتیب نداده است (و معمولاً بین ساخت‌های ۳۲ بیتی و ۶۴ بیتی متفاوت است).

همچنین PYTHONHASHSEED را ببینید.

تغییر یافته در نسخه‌ی 3.3: تصادفی‌سازی هش به‌طور پیش‌فرض فعال است.

object.__bool__(self)

برای پیاده‌سازی آزمون مقدار درستی و عملیات توکار bool() فراخوانی می‌شود؛ باید False یا True را برگرداند. هنگامی که این متد تعریف‌نشده باشد، اگر __len__() تعریف‌شده باشد، فراخوانی می‌شود و در صورتی که نتیجه آن غیر از صفر باشد، شیء درست محسوب می‌شود. اگر کلاسی هیچ‌کدام از __len__() و __bool__() را تعریف‌نکرده باشد (که در مورد خود کلاس object نیز صادق است)، تمام نمونه‌های آن درست محسوب می‌شوند.

3.3.2. سفارشی‌سازی دسترسی به ویژگی

می‌توان متدهای زیر را برای سفارشی‌سازی معنای دسترسی به ویژگی (استفاده از x.name، انتساب به آن، یا حذف آن) در نمونه‌های کلاس تعریف کرد.

object.__getattr__(self, name)

هنگامی فراخوانی می‌شود که دسترسی پیش‌فرض به ویژگی با AttributeError شکست بخورد (یا __getattribute__() یک AttributeError پرتاب می‌کند، زیرا name یک ویژگی نمونه یا ویژگی‌ای در درخت کلاس برای self نیست؛ یا __get__() یک پراپرتی name، AttributeError پرتاب می‌کند). این متد باید یا مقدار ویژگی (محاسبه‌شده) را برگرداند یا یک استثنای AttributeError پرتاب کند. خود کلاس object این متد را ارائه نمی‌دهد.

توجه داشته باشید که اگر ویژگی از طریق سازوکار معمولی پیدا شود، __getattr__() فراخوانی نمی‌شود. (این یک عدم تقارن عمدی بین __getattr__() و __setattr__() است.) این کار هم به دلایل کارایی و هم به این دلیل انجام شده است که در غیر این صورت __getattr__() هیچ راهی برای دسترسی به سایر ویژگی‌های نمونه نخواهد داشت. توجه داشته باشید که حداقل برای متغیرهای نمونه، می‌توانید با درج نکردن هیچ مقداری در دیکشنری ویژگی‌های نمونه (و در عوض درج آن‌ها در شیء دیگری) کنترل کامل را در دست بگیرید. برای راهی که واقعاً کنترل کامل بر دسترسی به ویژگی‌ها را به دست می‌دهد، متد __getattribute__() را در زیر ببینید.

object.__getattribute__(self, name)

برای پیاده‌سازی دسترسی به ویژگی‌های نمونه‌های کلاس، به‌صورت غیرشرطی فراخوانی می‌شود. اگر کلاس همچنین __getattr__() را تعریف کرده باشد، دومی فراخوانی نخواهد شد مگر آنکه __getattribute__() آن را به‌صورت صریح فراخوانی کند یا AttributeError را پرتاب کند. این متد باید مقدار ویژگی (محاسبه‌شده) را برگرداند یا استثنای AttributeError را پرتاب کند. برای جلوگیری از بازگشت بی‌پایان در این متد، پیاده‌سازی آن باید همیشه متد کلاس پایه با همین نام را برای دسترسی به هر ویژگی که لازم دارد فراخوانی کند، برای مثال object.__getattribute__(self, name).

توجه

این متد ممکن است همچنان هنگام جست‌وجوی متدهای ویژه به‌عنوان نتیجه‌ی فراخوانی ضمنی از طریق سینتکس زبان یا توابع توکار دور زده شود. جست‌وجوی متد ویژه را ببینید.

برای برخی دسترسی‌های حساس به ویژگی، یک رویداد حسابرسی object.__getattr__ را با آرگومان‌های obj و name پرتاب می‌کند.

object.__setattr__(self, name, value)

هنگامی که برای انتساب یک ویژگی اقدام شود، فراخوانی می‌شود. این به‌جای سازوکار معمول (یعنی ذخیره‌ی مقدار در دیکشنری نمونه) فراخوانی می‌شود. name نام ویژگی است و value مقداری است که باید به آن انتساب شود.

اگر __setattr__() بخواهد مقداری را به یک ویژگی نمونه اختصاص دهد، باید متد کلاس پایه با همین نام را فراخوانی کند، برای مثال object.__setattr__(self, name, value).

برای برخی انتساب‌های حساس ویژگی، یک رویداد حسابرسی object.__setattr__ را با آرگومان‌های obj، name و value پرتاب می‌کند.

object.__delattr__(self, name)

مانند __setattr__() اما برای حذف ویژگی به جای انتساب. این باید فقط زمانی پیاده‌سازی شود که del obj.name برای شیء معنادار باشد.

برای حذف برخی ویژگی‌های حساس، یک رویداد حسابرسی object.__delattr__ را با آرگومان‌های obj و name پرتاب می‌کند.

object.__dir__(self)

هنگامی که dir() روی شیء فراخوانی شود، فراخوانی می‌شود. باید یک پیمایش‌پذیر برگردانده شود. dir() پیمایش‌پذیر برگردانده‌شده را به یک فهرست تبدیل می‌کند و آن را مرتب می‌سازد.

3.3.2.1. سفارشی‌سازی دسترسی به ویژگی‌های ماژول

module.__getattr__()
module.__dir__()

همچنین می‌توان از نام‌های ویژه __getattr__ و __dir__ برای سفارشی‌سازی دسترسی به ویژگی‌های ماژول استفاده کرد. تابع __getattr__ در سطح ماژول باید یک آرگومان بپذیرد که نام یک ویژگی است و مقدار محاسبه‌شده را برگرداند یا یک AttributeError پرتاب کند. اگر یک ویژگی در شیء ماژول از طریق جست‌وجوی عادی، یعنی object.__getattribute__() پیدا نشد، آنگاه __getattr__ در __dict__ ماژول جست‌وجو می‌شود، پیش از آنکه یک AttributeError پرتاب شود. اگر پیدا شد، با نام ویژگی فراخوانی می‌شود و نتیجه برگردانده می‌شود.

تابع __dir__ نباید هیچ آرگومانی بپذیرد، و باید یک پیمایش‌پذیر از رشته‌ها برگرداند که نشان‌دهنده‌ی نام‌های قابل دسترسی در ماژول است. در صورت وجود، این تابع جایگزین جستجوی استاندارد dir() در یک ماژول می‌شود.

module.__class__

برای سفارشی‌سازی دقیق‌تر رفتار ماژول (تنظیم ویژگی‌ها، پراپرتی‌ها و غیره)، می‌توان ویژگی __class__ یک شیء ماژول را روی یک زیرکلاس از types.ModuleType تنظیم کرد. برای مثال:

import sys
from types import ModuleType

class VerboseModule(ModuleType):
    def __repr__(self):
        return f'Verbose {self.__name__}'

    def __setattr__(self, attr, value):
        print(f'Setting {attr}...')
        super().__setattr__(attr, value)

sys.modules[__name__].__class__ = VerboseModule

توجه

تعریف __getattr__ ماژول و تنظیم __class__ ماژول تنها بر جست‌وجوهای انجام‌شده با استفاده از سینتکس دسترسی به ویژگی تأثیر می‌گذارند -- دسترسی مستقیم به متغیرهای سراسری ماژول (چه توسط کد داخل ماژول و چه از طریق ارجاع به دیکشنری متغیرهای سراسری ماژول) تحت تأثیر قرار نمی‌گیرد.

تغییر یافته در نسخه‌ی 3.5: ویژگی __class__ ماژول اکنون قابل نوشتن است.

اضافه شده در نسخه‌ی 3.7: ویژگی‌های __getattr__ و __dir__ ماژول.

همچنین ملاحظه نمائید

PEP 562 - ماژول __getattr__ و __dir__

توابع __getattr__ و __dir__ در ماژول‌ها را شرح می‌دهد.

3.3.2.2. پیاده‌سازی توصیف‌گرها

متدهای زیر فقط زمانی اعمال می‌شوند که نمونه‌ای از کلاس شامل متد (یک کلاس به‌اصطلاح توصیف‌گر) در یک کلاس مالک قرار داشته باشد (توصیف‌گر باید یا در دیکشنری کلاس مالک باشد یا در دیکشنری کلاس یکی از والدین آن). در مثال‌های زیر، «ویژگی» به ویژگی‌ای اشاره دارد که نام آن، کلید پراپرتی در __dict__ کلاس مالک است. خود کلاس object هیچ‌کدام از این پروتکل‌ها را پیاده‌سازی نمی‌کند.

object.__get__(self, instance, owner=None)

برای دریافت ویژگی کلاس مالک (دسترسی به ویژگی کلاس) یا ویژگی نمونه‌ای از آن کلاس (دسترسی به ویژگی نمونه) فراخوانی می‌شود. آرگومان اختیاری owner کلاس مالک است، در حالی که instance نمونه‌ای است که دسترسی به ویژگی از طریق آن انجام شده است، یا None وقتی که دسترسی به ویژگی از طریق owner انجام شده است.

این متد باید مقدار ویژگی محاسبه‌شده را برگرداند یا استثنای AttributeError را پرتاب کند.

PEP 252 مشخص می‌کند که __get__() با یک یا دو آرگومان فراخوانی‌پذیر است. توصیف‌گرهای توکار خود پایتون از این مشخصات پشتیبانی می‌کنند؛ با این حال، احتمال دارد برخی ابزارهای شخص ثالث توصیف‌گرهایی داشته باشند که به هر دو آرگومان نیاز دارند. پیاده‌سازی __getattribute__() خود پایتون همیشه هر دو آرگومان را ارسال می‌کند، چه لازم باشند چه نباشند.

object.__set__(self, instance, value)

فراخوانی می‌شود تا ویژگیِ نمونه instance از کلاس مالک را به مقدار جدید value تنظیم کند.

توجه داشته باشید که افزودن __set__() یا __delete__() نوع توصیف‌گر را به یک «توصیف‌گر داده (data descriptor)» تغییر می‌دهد. برای جزئیات بیشتر، فراخوانی توصیف‌گرها را ببینید.

object.__delete__(self, instance)

برای حذف ویژگی روی یک نمونه instance از کلاس مالک فراخوانی می‌شود.

نمونه‌هایی از توصیف‌گرها ممکن است همچنین دارای ویژگی __objclass__ باشند:

object.__objclass__

ویژگی __objclass__ توسط ماژول inspect به‌عنوان مشخص‌کننده‌ی کلاسی که این شیء در آن تعریف‌شده است تفسیر می‌شود (تنظیم مناسب این ویژگی می‌تواند به درون‌نگری ویژگی‌های پویای کلاس در ران‌تایم کمک کند). برای اشیاء فراخوانی‌پذیر، این ویژگی ممکن است نشان دهد که نمونه‌ای از نوع داده‌شده (یا یک زیرکلاس) به‌عنوان اولین آرگومان جایگاهی انتظار می‌رود یا الزامی است (برای مثال، CPython این ویژگی را برای متدهای مقیدنشده‌ای که در C پیاده‌سازی‌شده‌اند تنظیم می‌کند).

3.3.2.3. فراخوانی توصیف‌گرها

به‌طور کلی، توصیف‌گر یک ویژگی شیء با «رفتار پیوندی» است؛ ویژگی‌ای که دسترسی به آن با متدهای پروتکل توصیف‌گر بازنویسی شده است: __get__()، __set__() و __delete__(). اگر هر یک از آن متدها برای شیئی تعریف شده باشند، به آن شیء توصیف‌گر گفته می‌شود.

رفتار پیش‌فرض برای دسترسی به ویژگی این است که ویژگی از دیکشنری یک شیء دریافت، تنظیم یا حذف شود. برای مثال، a.x دارای یک زنجیره جستجو است که با a.__dict__['x'] آغاز می‌شود، سپس به type(a).__dict__['x'] می‌رسد و از میان کلاس‌های پایه‌ی type(a) به‌جز فراکلاس‌ها ادامه می‌یابد.

با این حال، اگر مقدار جستجوشده شیئی باشد که یکی از متدهای توصیف‌گر را تعریف می‌کند، پایتون ممکن است رفتار پیش‌فرض را نادیده بگیرد و در عوض متد توصیف‌گر را فراخوانی کند. اینکه این امر در کجای زنجیره اولویت رخ می‌دهد، به این بستگی دارد که کدام متدهای توصیف‌گر تعریف شده‌اند و چگونه فراخوانی شده‌اند.

نقطه‌ی شروع برای فراخوانی توصیف‌گر، یک اتصال، a.x است. نحوه‌ی جمع‌آوری آرگومان‌ها به a بستگی دارد:

فراخوانی مستقیم

ساده‌ترین و کم‌رایج‌ترین فراخوانی زمانی است که کد کاربر مستقیماً یک متد توصیف‌گر را فراخوانی می‌کند: x.__get__(a).

اتصال نمونه

در صورت اتصال به یک نمونه از شیء، a.x به فراخوانی type(a).__dict__['x'].__get__(a, type(a)) تبدیل می‌شود.

اتصال کلاس

در صورت اتصال به یک کلاس، A.x به فراخوانی A.__dict__['x'].__get__(None, A) تبدیل می‌شود.

اتصال super

یک جستجوی نقطه‌ای مانند super(A, a).x، در a.__class__.__mro__ به دنبال یک کلاس پایه B پس از A می‌گردد و سپس B.__dict__['x'].__get__(a, A) را برمی‌گرداند. اگر توصیف‌گر نباشد، x بدون تغییر برگردانده می‌شود.

برای پیوندهای نمونه، اولویت فراخوانی توصیف‌گر به این بستگی دارد که کدام متدهای توصیف‌گر تعریف شده‌اند. یک توصیف‌گر می‌تواند هر ترکیبی از __get__()، __set__() و __delete__() را تعریف کند. اگر __get__() را تعریف نکند، آنگاه دسترسی به ویژگی، خود شیء توصیف‌گر را برمی‌گرداند، مگر اینکه مقداری در دیکشنری نمونه‌ی شیء وجود داشته باشد. اگر توصیف‌گر __set__() و/یا __delete__() را تعریف کند، یک توصیف‌گر داده است؛ اگر هیچ‌کدام را تعریف نکند، یک توصیف‌گر غیرداده است. به‌طور معمول، توصیف‌گرهای داده هر دو __get__() و __set__() را تعریف می‌کنند، در حالی که توصیف‌گرهای غیرداده فقط متد __get__() را دارند. توصیف‌گرهای داده‌ای که __get__() و __set__() (و/یا __delete__()) را تعریف کرده باشند، همیشه بازتعریفی در دیکشنری نمونه را بی‌اثر می‌کنند. در مقابل، نمونه‌ها می‌توانند توصیف‌گرهای غیرداده را بی‌اثر کنند.

متدهای پایتون (از جمله آن‌هایی که با @staticmethod و @classmethod دکور شده‌اند) به‌عنوان توصیف‌گرهای غیرداده‌ای پیاده‌سازی شده‌اند. بر همین اساس، نمونه‌ها می‌توانند متدها را بازتعریف و بازنویسی کنند. این امر به نمونه‌های منفرد اجازه می‌دهد رفتارهایی را کسب کنند که با سایر نمونه‌های همان کلاس متفاوت است.

دکوراتور @property به‌عنوان یک توصیف‌گر داده (data descriptor) پیاده‌سازی شده است. بر همین اساس، نمونه‌ها نمی‌توانند رفتار یک پراپرتی را بازنویسی کنند.

3.3.2.4. __slots__

__slots__ به ما اجازه می‌دهد اعضای داده (مانند پراپرتی‌ها) را به‌صراحت اعلام کنیم و از ایجاد __dict__ و __weakref__ جلوگیری کنیم (مگر آنکه صریحاً در __slots__ اعلام شده باشند یا در یک والد در دسترس باشند.)

فضای صرفه‌جویی‌شده در مقایسه با استفاده از __dict__ می‌تواند قابل‌توجه باشد. سرعت جست‌وجوی ویژگی نیز می‌تواند به‌طور قابل‌توجهی بهبود یابد.

object.__slots__

می‌توان یک رشته، پیمایش‌پذیر، یا دنباله‌ای از رشته‌ها شامل نام متغیرهای مورد استفاده توسط نمونه‌ها را به این متغیر کلاس اختصاص داد. __slots__ فضایی را برای متغیرهای اعلام‌شده رزرو می‌کند و از ایجاد خودکار __dict__ و __weakref__ برای هر نمونه جلوگیری می‌کند.

نکاتی درباره استفاده از __slots__:

  • هنگام ارث‌بری از کلاسی بدون __slots__، ویژگی‌های __dict__ و __weakref__ نمونه‌ها همیشه قابل دسترسی خواهند بود.

  • بدون یک متغیر __dict__، نمی‌توان متغیرهای جدیدی را که در تعریف __slots__ فهرست نشده‌اند، به نمونه‌ها انتساب داد. تلاش برای انتساب به یک نام متغیر فهرست‌نشده باعث پرتاب AttributeError می‌شود. اگر انتساب پویای متغیرهای جدید مدنظر است، '__dict__' را به دنباله‌ای از رشته‌ها در تعریف __slots__ اضافه کنید.

  • بدون یک متغیر __weakref__ برای هر نمونه، کلاس‌هایی که __slots__ را تعریف می‌کنند، از ارجاع‌های ضعیف (weak references) به نمونه‌های خود پشتیبانی نمی‌کنند. اگر به پشتیبانی از ارجاع‌های ضعیف نیاز است، '__weakref__' را به دنباله‌ای از رشته‌ها در اعلام __slots__ اضافه کنید.

  • __slots__ در سطح کلاس با ایجاد توصیف‌گرها برای هر نام متغیر پیاده‌سازی می‌شوند. در نتیجه، نمی‌توان از ویژگی‌های کلاس برای تنظیم مقادیر پیش‌فرض متغیرهای نمونه تعریف‌شده توسط __slots__ استفاده کرد؛ در غیر این صورت، ویژگی کلاس انتساب توصیف‌گر را بازنویسی می‌کند.

  • عملکرد تعریف __slots__ به کلاسی که در آن تعریف‌شده است محدود نمی‌شود. __slots__ تعریف‌شده در کلاس‌های والد، در کلاس‌های فرزند در دسترس است. با این حال، نمونه‌های یک زیرکلاس فرزند، __dict__ و __weakref__ خواهند داشت، مگر آنکه زیرکلاس نیز __slots__ را تعریف کند (که باید فقط شامل نام‌های جایگاه‌های اضافی باشد).

  • اگر یک کلاس یک جایگاه را تعریف کند که در یک کلاس پایه نیز تعریف شده است، متغیر نمونه‌ای که توسط جایگاه کلاس پایه تعریف شده است، غیرقابل‌دسترس است (مگر با بازیابی توصیف‌گر آن به‌صورت مستقیم از کلاس پایه). این موضوع معنای برنامه را تعریف‌نشده می‌کند. در آینده، ممکن است یک بررسی برای جلوگیری از این حالت اضافه شود.

  • اگر __slots__ غیرخالی برای کلاسی مشتق‌شده از "variable-length" built-in type مانند int، bytes و tuple تعریف شده باشد، TypeError پرتاب خواهد شد.

  • هر پیمایش‌پذیر غیررشته‌ای را می‌توان به __slots__ انتساب داد.

  • اگر از یک dictionary برای انتساب __slots__ استفاده شود، کلیدهای دیکشنری به‌عنوان نام‌های جایگاه استفاده خواهند شد. می‌توان از مقادیر دیکشنری برای فراهم کردن رشته‌مستندهای هر ویژگی استفاده کرد که توسط inspect.getdoc() شناسایی می‌شوند و در خروجی help() نمایش داده می‌شوند.

  • انتساب __class__ تنها در صورتی امکان‌پذیر است که هر دو کلاس __slots__ یکسانی داشته باشند.

  • می‌توان از وراثت چندگانه با چندین کلاس والد دارای جایگاه استفاده کرد، اما فقط یک والد مجاز است ویژگی‌های ایجادشده توسط جایگاه‌ها را داشته باشد (سایر کلاس‌های پایه باید چیدمان‌های جایگاه خالی داشته باشند)؛ موارد نقض، TypeError را پرتاب می‌کنند.

  • اگر یک پیمایش‌گر برای __slots__ استفاده شود، آنگاه یک descriptor برای هر یک از مقادیر آن iterator ایجاد می‌شود. با این حال، ویژگی __slots__ یک iterator خالی خواهد بود.

3.3.3. سفارشی‌سازی ایجاد کلاس

هرگاه کلاسی از کلاس دیگری ارث ببرد، __init_subclass__() در کلاس والد فراخوانی می‌شود. به این ترتیب، می‌توان کلاس‌هایی نوشت که رفتار زیرکلاس‌ها را تغییر می‌دهند. این موضوع ارتباط نزدیکی با دکوراتورهای کلاس دارد، اما در حالی که دکوراتورهای کلاس فقط بر کلاس مشخصی که به آن اعمال می‌شوند تأثیر می‌گذارند، __init_subclass__ صرفاً بر زیرکلاس‌های آینده‌ی کلاسی که متد را تعریف می‌کند اعمال می‌شود.

classmethod object.__init_subclass__(cls)

این متد هر زمان که از کلاس حاوی آن زیرکلاس ساخته شود، فراخوانی می‌شود. cls در این حالت زیرکلاس جدید است. اگر به‌عنوان یک متد نمونه معمولی تعریف شده باشد، این متد به‌طور ضمنی به یک متد کلاس تبدیل می‌شود.

آرگومان‌های کلیدواژه‌ای که به یک کلاس جدید داده می‌شوند، به __init_subclass__ کلاس والد منتقل می‌شوند. برای سازگاری با کلاس‌های دیگری که از __init_subclass__ استفاده می‌کنند، باید آرگومان‌های کلیدواژه‌ای مورد نیاز را جدا کنید و بقیه را به کلاس پایه منتقل کنید، به این صورت:

class Philosopher:
    def __init_subclass__(cls, /, default_name, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.default_name = default_name

class AustralianPhilosopher(Philosopher, default_name="Bruce"):
    pass

پیاده‌سازی پیش‌فرض object.__init_subclass__ هیچ کاری انجام نمی‌دهد، اما اگر با هر آرگومانی فراخوانی شود، خطایی پرتاب می‌کند.

توجه

راهنمای فراکلاس metaclass توسط سایر بخش‌های سازوکار نوع مصرف می‌شود و هرگز به پیاده‌سازی‌های __init_subclass__ ارسال نمی‌شود. فراکلاس واقعی (نه راهنمای صریح) به‌صورت type(cls) قابل دسترسی است.

اضافه شده در نسخه‌ی 3.6.

هنگامی که یک کلاس ایجاد می‌شود، type.__new__() متغیرهای کلاس را پیمایش می‌کند و برای آن‌هایی که یک قلاب __set_name__() دارند، کال‌بک انجام می‌دهد.

object.__set_name__(self, owner, name)

به‌طور خودکار در زمان ایجاد کلاس مالک owner فراخوانی می‌شود. شیء به name در آن کلاس اختصاص داده شده است:

class A:
    x = C()  # Automatically calls: x.__set_name__(A, 'x')

اگر متغیر کلاس پس از ایجاد کلاس انتساب داده شود، __set_name__() به‌طور خودکار فراخوانی نمی‌شود. در صورت نیاز، می‌توان __set_name__() را مستقیماً فراخوانی کرد:

class A:
   pass

c = C()
A.x = c                  # The hook is not called
c.__set_name__(A, 'x')   # Manually invoke the hook

برای جزئیات بیشتر ایجاد شیء کلاس را ببینید.

اضافه شده در نسخه‌ی 3.6.

3.3.3.1. فراکلاس‌ها

به‌طور پیش‌فرض، کلاس‌ها با استفاده از type() ساخته می‌شوند. بدنه کلاس در یک فضای نام جدید اجرا می‌شود و نام کلاس به‌صورت محلی به نتیجه type(name, bases, namespace) متصل می‌شود.

فرآیند ایجاد کلاس را می‌توان با ارسال آرگومان کلیدواژه‌ای metaclass در خط تعریف کلاس، یا با ارث‌بری از یک کلاس موجود که شامل چنین آرگومانی است، سفارشی کرد. در مثال زیر، هر دو MyClass و MySubclass نمونه‌هایی از Meta هستند:

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass

هر آرگومان کلیدواژه‌ای دیگری که در تعریف کلاس مشخص شده باشد، به تمام عملیات فراکلاس که در زیر توضیح داده شده‌اند، منتقل می‌شود.

هنگامی که تعریف کلاس اجرا می‌شود، مراحل زیر رخ می‌دهد:

  • ورودی‌های MRO حل می‌شوند؛

  • فراکلاس مناسب تعیین می‌شود؛

  • فضای نام کلاس آماده می‌شود؛

  • بدنه‌ی کلاس اجرا می‌شود؛

  • شیء کلاس ایجاد می‌شود.

3.3.3.2. حل مدخل‌های MRO

object.__mro_entries__(self, bases)

اگر پایه‌ای که در تعریف کلاس ظاهر می‌شود، نمونه‌ای از type نباشد، آنگاه یک متد __mro_entries__() روی پایه جستجو می‌شود. اگر یک متد __mro_entries__() پیدا شود، هنگام ایجاد کلاس، پایه با نتیجه‌ی فراخوانی __mro_entries__() جایگزین می‌شود. این متد با تاپل پایه‌های اصلی که به پارامتر bases ارسال‌شده است فراخوانی می‌شود و باید یک تاپل از کلاس‌ها را برگرداند که به‌جای پایه استفاده خواهند شد. تاپل برگردانده‌شده ممکن است خالی باشد: در این موارد، از پایه‌ی اصلی چشم‌پوشی می‌شود.

همچنین ملاحظه نمائید

types.resolve_bases()

پایه‌هایی که نمونه‌ای از type نیستند، به‌صورت پویا حل می‌شوند.

types.get_original_bases()

بازیابی «پایه‌های اصلی» یک کلاس پیش از تغییرات اعمال‌شده توسط __mro_entries__().

PEP 560

پشتیبانی هسته از ماژول typing و انواع عام.

3.3.3.3. تعیین فراکلاس مناسب

فراکلاس مناسب برای تعریف یک کلاس به صورت زیر تعیین می‌شود:

  • اگر هیچ کلاس پایه‌ای و هیچ فراکلاس صریحی داده نشود، از type() استفاده می‌شود؛

  • اگر یک فراکلاس صریح داده شده باشد و آن نه نمونه‌ای از type() باشد، آنگاه مستقیماً به‌عنوان فراکلاس استفاده می‌شود؛

  • اگر نمونه‌ای از type() به‌عنوان فراکلاس صریح داده شود، یا کلاس‌های پایه تعریف‌شده باشند، آنگاه مشتق‌شده‌ترین فراکلاس استفاده می‌شود.

مشتق‌ترین فراکلاس از میان فراکلاس مشخص‌شده به‌صورت صریح (در صورت وجود) و فراکلاس‌های همه‌ی کلاس‌های پایه مشخص‌شده (یعنی type(cls)) انتخاب می‌شود. مشتق‌ترین فراکلاس، فراکلاسی است که زیرنوع همه این فراکلاس‌های نامزد باشد. اگر هیچ‌یک از فراکلاس‌های نامزد این معیار را برآورده نکنند، تعریف کلاس با TypeError شکست خواهد خورد.

3.3.3.4. آماده‌سازی فضای نام کلاس

پس از شناسایی فراکلاس مناسب، فضای نام کلاس آماده می‌شود. اگر فراکلاس دارای ویژگی __prepare__ باشد، به‌صورت namespace = metaclass.__prepare__(name, bases, **kwds) فراخوانی می‌شود (که در آن آرگومان‌های کلیدواژه‌ای اضافی، در صورت وجود، از تعریف کلاس می‌آیند). متد __prepare__ باید به‌صورت یک classmethod پیاده‌سازی شود. فضای نام برگردانده‌شده توسط __prepare__ به __new__ ارسال می‌شود، اما هنگامی که شیء نهایی کلاس ایجاد می‌شود، فضای نام در یک dict جدید کپی می‌شود.

اگر فراکلاس ویژگی __prepare__ نداشته باشد، فضای نام کلاس به‌صورت یک نگاشت ترتیب‌دار خالی مقداردهی اولیه می‌شود.

همچنین ملاحظه نمائید

PEP 3115 - فراکلاس‌ها در Python 3000

قلاب فضای نام __prepare__ معرفی شد

3.3.3.5. اجرای بدنه کلاس

بدنه‌ی کلاس (تقریباً) به‌صورت exec(body, globals(), namespace) اجرا می‌شود. تفاوت اصلی با یک فراخوانی عادی exec() این است که محدوده‌بندی لغوی به بدنه‌ی کلاس (از جمله هر متدی) اجازه می‌دهد هنگامی که تعریف کلاس داخل یک تابع رخ می‌دهد، به نام‌هایی از محدوده‌های جاری و بیرونی ارجاع دهد.

با این حال، حتی زمانی که تعریف کلاس درون تابع رخ می‌دهد، متدهای تعریف‌شده درون کلاس همچنان نمی‌توانند نام‌های تعریف‌شده در محدوده کلاس را ببینند. دسترسی به متغیرهای کلاس باید از طریق اولین پارامتر متدهای نمونه یا کلاس، یا از طریق ارجاع ضمنی __class__ با محدوده لغوی که در بخش بعدی توضیح داده‌شده است، انجام شود.

3.3.3.6. ایجاد شیء کلاس

پس از آنکه فضای نام کلاس با اجرای بدنه کلاس پر شد، شیء کلاس با فراخوانی metaclass(name, bases, namespace, **kwds) ایجاد می‌شود (کلیدواژه‌های اضافی ارسال‌شده در اینجا همان کلیدواژه‌هایی هستند که به __prepare__ ارسال می‌شوند).

این شیء کلاس همان چیزی است که توسط قالب بدون آرگومانِ super() به آن ارجاع داده خواهد شد. __class__ یک ارجاع ضمنی به closure است که اگر هر متدی در بدنه کلاس به __class__ یا super ارجاع دهد، توسط کامپایلر ایجاد می‌شود. این امر به قالب بدون آرگومانِ super() اجازه می‌دهد کلاس در حال تعریف را بر اساس محدوده واژگانی به‌درستی شناسایی کند، در حالی که کلاس یا نمونه‌ای که برای انجام فراخوانی جاری استفاده شده است، بر اساس اولین آرگومان ارسال‌شده به متد شناسایی می‌شود.

در CPython 3.6 و نسخه‌های بعد از آن، سلول __class__ به‌عنوان یک آیتم __classcell__ در فضای نام کلاس به فراکلاس ارسال می‌شود. در صورت وجود، این مورد باید تا فراخوانی type.__new__ منتقل شود تا کلاس به‌درستی مقداردهی اولیه شود. عدم انجام این کار منجر به RuntimeError در پایتون 3.8 خواهد شد.

هنگام استفاده از فراکلاس پیش‌فرض type، یا هر فراکلاسی که در نهایت type.__new__ را فراخوانی می‌کند، مراحل سفارشی‌سازی اضافی زیر پس از ایجاد شیء کلاس اجرا می‌شوند:

  1. متد type.__new__ همه‌ی ویژگی‌های موجود در فضای نام کلاس را که متد __set_name__() را تعریف می‌کنند، جمع‌آوری می‌کند؛

  2. آن متدهای __set_name__ با کلاسی که در حال تعریف است و نام اختصاص‌داده‌شده به آن ویژگی خاص فراخوانی می‌شوند؛

  3. قلاب __init_subclass__() روی والد مستقیم کلاس جدید در ترتیب حل متد آن فراخوانی می‌شود.

پس از ایجاد شیء کلاس، این شیء به دکوراتورهای کلاس گنجانده‌شده در تعریف کلاس (در صورت وجود) پاس داده می‌شود و شیء حاصل به‌عنوان کلاس تعریف‌شده در فضای نام محلی مقید می‌شود.

هنگامی که یک کلاس جدید توسط type.__new__ ایجاد می‌شود، شیئی که به‌عنوان پارامتر فضای نام ارائه شده است به یک نگاشت ترتیبی جدید کپی می‌شود و شیء اصلی دور انداخته می‌شود. نسخه‌ی جدید در یک پراکسی فقط‌خواندنی قرار می‌گیرد، که به ویژگی __dict__ شیء کلاس تبدیل می‌شود.

همچنین ملاحظه نمائید

PEP 3135 - super جدید

ارجاع ضمنی __class__ در بستار (closure) را توصیف می‌کند

3.3.3.7. کاربردهای فراکلاس‌ها

کاربردهای بالقوه‌ی فراکلاس‌ها بی‌کران است. برخی از ایده‌هایی که بررسی شده‌اند شامل شمارش (enum)، گزارش‌گیری، بررسی رابط، واگذاری خودکار، ایجاد خودکار ویژگی، پراکسی‌ها، چارچوب‌ها و قفل/همگام‌سازی خودکار منابع هستند.

3.3.4. سفارشی‌سازی بررسی‌های نمونه و زیرکلاس

متدهای زیر برای بازنویسی رفتار پیش‌فرض توابع توکار isinstance() و issubclass() استفاده می‌شوند.

به‌ویژه، فراکلاس abc.ABCMeta این متدها را پیاده‌سازی می‌کند تا امکان افزودن کلاس‌های پایه انتزاعی (ABCها) به‌عنوان «کلاس‌های پایه مجازی» به هر کلاس یا نوعی (از جمله انواع توکار)، از جمله سایر ABCها، فراهم شود.

type.__instancecheck__(self, instance)

اگر instance باید به‌عنوان نمونه‌ای (مستقیم یا غیرمستقیم) از class در نظر گرفته شود، مقدار درست برمی‌گرداند. اگر تعریف شده باشد، برای پیاده‌سازی isinstance(instance, class) فراخوانی می‌شود.

type.__subclasscheck__(self, subclass)

اگر subclass باید به‌عنوان یک زیرکلاس (مستقیم یا غیرمستقیم) از class در نظر گرفته شود، مقدار true برمی‌گرداند. اگر تعریف شده باشد، برای پیاده‌سازی issubclass(subclass, class) فراخوانی می‌شود.

توجه داشته باشید که این متدها بر روی نوع (فراکلاس) یک کلاس جستجو می‌شوند. آن‌ها نمی‌توانند به‌عنوان متدهای کلاس در خود کلاس تعریف شوند. این موضوع با جستجوی متدهای ویژه‌ای که بر روی نمونه‌ها فراخوانی می‌شوند، سازگار است؛ با این تفاوت که در این حالت، خود نمونه یک کلاس است.

همچنین ملاحظه نمائید

PEP 3119 - معرفی کلاس‌های پایه انتزاعی

شامل مشخصاتی برای سفارشی‌سازی رفتار isinstance() و issubclass() از طریق __instancecheck__() و __subclasscheck__() است، همراه با انگیزه‌ی این قابلیت در زمینه افزودن کلاس‌های پایه انتزاعی (ماژول abc را ببینید) به زبان.

3.3.5. شبیه‌سازی انواع عام

هنگام استفاده از حاشیه‌نویسی‌های نوع، اغلب مفید است که یک نوع عام را با استفاده از نماد کروشه‌ای پایتون پارامتری کنید. برای مثال، ممکن است از حاشیه‌نویسی list[int] برای نشان دادن یک list استفاده شود که در آن همه‌ی عناصر از نوع int هستند.

همچنین ملاحظه نمائید

PEP 484 - راهنماهای نوع

آشنایی با چارچوب پایتون برای حاشیه‌نویسی‌های نوع

انواع نام مستعار عام

مستندات اشیایی که کلاس‌های عام پارامتریزه را نشان می‌دهند

عام‌ها، عام‌های تعریف‌شده توسط کاربر و typing.Generic

مستنداتی درباره چگونگی پیاده‌سازی کلاس‌های عام که می‌توانند در ران‌تایم پارامتردهی شوند و برای بررسی‌کننده‌های نوع ایستا قابل درک باشند.

یک کلاس به‌طور کلی تنها در صورتی می‌تواند پارامتریزه (parameterized) شود که متد کلاس ویژه __class_getitem__() را تعریف کند.

classmethod object.__class_getitem__(cls, key)

یک شیء را برمی‌گرداند که نشان‌دهنده‌ی تخصصی‌سازی یک کلاس عام با آرگومان‌های نوع یافت‌شده در key است.

هنگامی که روی یک کلاس تعریف شود، __class_getitem__() به‌طور خودکار یک متد کلاس است. بنابراین، نیازی نیست که هنگام تعریف با @classmethod آراسته شود.

3.3.5.1. هدف از __class_getitem__

هدف از __class_getitem__() این است که امکان پارامتری‌سازی کلاس‌های عام کتابخانه استاندارد در ران‌تایم فراهم شود، تا بتوان راهنماهای نوع را آسان‌تر به این کلاس‌ها اعمال کرد.

برای پیاده‌سازی کلاس‌های عام سفارشی که بتوانند در ران‌تایم پارامتریزه شوند و برای بررسی‌کننده‌های نوع ایستا قابل درک باشند، کاربران باید یا از کلاسی در کتابخانه استاندارد که از قبل __class_getitem__() را پیاده‌سازی کرده است ارث‌بری کنند، یا از typing.Generic ارث‌بری کنند که پیاده‌سازی خود از __class_getitem__() را دارد.

پیاده‌سازی‌های سفارشی از __class_getitem__() روی کلاس‌هایی که خارج از کتابخانه استاندارد تعریف شده‌اند ممکن است توسط بررسی‌کننده‌های نوع شخص ثالث مانند mypy درک نشوند. استفاده از __class_getitem__() روی هر کلاسی برای اهدافی غیر از اشاره‌گذاری نوع (type hinting) توصیه نمی‌شود.

3.3.5.2. __class_getitem__ در برابر __getitem__

معمولاً عملیات subscription روی یک شیء با استفاده از کروشه‌ها، متد نمونه __getitem__() تعریف‌شده در کلاس آن شیء را فراخوانی می‌کند. با این حال، اگر شیءای که این عملیات روی آن انجام می‌شود خودش یک کلاس باشد، ممکن است به‌جای آن، متد کلاس __class_getitem__() فراخوانی شود. __class_getitem__() باید در صورتی که به‌درستی تعریف شده باشد، یک شیء GenericAlias برگرداند.

هنگام مواجهه با عبارت obj[x]، مفسر پایتون برای تصمیم‌گیری درباره‌ی این‌که __getitem__() یا __class_getitem__() باید فراخوانی شود، فرآیندی شبیه به فرآیند زیر را دنبال می‌کند:

from inspect import isclass

def subscribe(obj, x):
    """Return the result of the expression 'obj[x]'"""

    class_of_obj = type(obj)

    # If the class of obj defines __getitem__,
    # call class_of_obj.__getitem__(obj, x)
    if hasattr(class_of_obj, '__getitem__'):
        return class_of_obj.__getitem__(obj, x)

    # Else, if obj is a class and defines __class_getitem__,
    # call obj.__class_getitem__(x)
    elif isclass(obj) and hasattr(obj, '__class_getitem__'):
        return obj.__class_getitem__(x)

    # Else, raise an exception
    else:
        raise TypeError(
            f"'{class_of_obj.__name__}' object is not subscriptable"
        )

در پایتون، همه‌ی کلاس‌ها خود نمونه‌هایی از کلاس‌های دیگر هستند. کلاسِ یک کلاس به عنوان فراکلاس آن کلاس شناخته می‌شود، و بیشتر کلاس‌ها کلاس type را به عنوان فراکلاس خود دارند. type متد __getitem__() را تعریف نمی‌کند، به این معنا که عبارت‌هایی مانند list[int]، dict[str, float] و tuple[str, bytes] همگی منجر به فراخوانی __class_getitem__() می‌شوند:

>>> # list has class "type" as its metaclass, like most classes:
>>> type(list)
<class 'type'>
>>> type(dict) == type(list) == type(tuple) == type(str) == type(bytes)
True
>>> # "list[int]" calls "list.__class_getitem__(int)"
>>> list[int]
list[int]
>>> # list.__class_getitem__ returns a GenericAlias object:
>>> type(list[int])
<class 'types.GenericAlias'>

با این حال، اگر کلاسی دارای فراکلاس سفارشی باشد که __getitem__() را تعریف می‌کند، زیرنویسی کلاس ممکن است منجر به رفتار متفاوتی شود. مثالی از این را می‌توان در ماژول enum یافت:

>>> from enum import Enum
>>> class Menu(Enum):
...     """A breakfast menu"""
...     SPAM = 'spam'
...     BACON = 'bacon'
...
>>> # Enum classes have a custom metaclass:
>>> type(Menu)
<class 'enum.EnumMeta'>
>>> # EnumMeta defines __getitem__,
>>> # so __class_getitem__ is not called,
>>> # and the result is not a GenericAlias object:
>>> Menu['SPAM']
<Menu.SPAM: 'spam'>
>>> type(Menu['SPAM'])
<enum 'Menu'>

همچنین ملاحظه نمائید

PEP 560 - پشتیبانی هسته‌ای از ماژول typing و انواع عام

معرفی __class_getitem__() و شرح اینکه چه زمانی یک زیرنویسی منجر به فراخوانی __class_getitem__() به‌جای __getitem__() می‌شود

3.3.6. شبیه‌سازی اشیاء فراخوانی‌پذیر

object.__call__(self[, args...])

هنگامی فراخوانی می‌شود که نمونه به‌عنوان یک تابع «فراخوانی» شود؛ اگر این متد تعریف شده باشد، x(arg1, arg2, ...) تقریباً معادل type(x).__call__(x, arg1, ...) است. خود کلاس object این متد را ارائه نمی‌دهد.

3.3.7. شبیه‌سازی انواع ظرف (container types)

متدهای زیر را می‌توان برای پیاده‌سازی اشیای ظرف تعریف کرد. خود کلاس object هیچ‌کدام از آن‌ها را ارائه نمی‌دهد. ظرف‌ها معمولاً دنباله‌ها (مانند فهرست‌ها یا تاپل‌ها) یا نگاشت‌ها (مانند دیکشنری‌ها) هستند، اما می‌توانند نشان‌دهنده ظرف‌های دیگری نیز باشند. دسته اول متدها یا برای شبیه‌سازی یک دنباله به کار می‌روند یا برای شبیه‌سازی یک نگاشت؛ تفاوت این است که برای یک دنباله، کلیدهای مجاز باید اعداد صحیح k باشند که 0 <= k < N، که در آن N طول دنباله است، یا اشیای slice باشند که محدوده‌ای از آیتم‌ها را تعریف می‌کنند. همچنین توصیه می‌شود که نگاشت‌ها متدهای keys()، values()، items()، get()، clear()، setdefault()، pop()، popitem()، copy() و update() را با رفتاری مشابه متدهای اشیای دیکشنری استاندارد پایتون ارائه کنند. ماژول collections.abc یک کلاس پایه انتزاعی به نام MutableMapping ارائه می‌کند تا به ایجاد آن متدها از یک مجموعه پایه شامل __getitem__()، __setitem__()، __delitem__() و keys() کمک کند.

دنباله‌های تغییرپذیر باید متدهای append()، clear()، count()، extend()، index()، insert()، pop()، remove() و reverse() را، مانند اشیای list استاندارد پایتون، فراهم کنند. در نهایت، انواع دنباله‌ای باید جمع (به معنای الحاق) و ضرب (به معنای تکرار) را با تعریف متدهای __add__()، __radd__()، __iadd__()، __mul__()، __rmul__() و __imul__() که در ادامه توضیح داده شده‌اند، پیاده‌سازی کنند؛ آن‌ها نباید عملگرهای عددی دیگری را تعریف کنند.

توصیه می‌شود که هم نگاشت‌ها و هم دنباله‌ها متد __contains__() را پیاده‌سازی کنند تا امکان استفاده‌ی کارآمد از عملگر in فراهم شود؛ برای نگاشت‌ها، in باید کلیدهای نگاشت را جستجو کند؛ برای دنباله‌ها، باید مقادیر را جستجو کند. همچنین توصیه می‌شود که هم نگاشت‌ها و هم دنباله‌ها متد __iter__() را پیاده‌سازی کنند تا امکان پیمایش کارآمد ظرف فراهم شود؛ برای نگاشت‌ها، __iter__() باید کلیدهای شیء را پیمایش کند؛ برای دنباله‌ها، باید مقادیر را پیمایش کند.

object.__len__(self)

برای پیاده‌سازی تابع توکار len() فراخوانی می‌شود. باید طول شیء را برگرداند، که یک عدد صحیح >= ۰ است. همچنین، شیئی که متد __bool__() را تعریف نکرده باشد و متد __len__() آن صفر برگرداند، در یک زمینه بولی نادرست در نظر گرفته می‌شود.

در CPython، طول باید حداکثر sys.maxsize باشد. اگر طول بزرگ‌تر از sys.maxsize باشد، برخی قابلیت‌ها (مانند len()) ممکن است OverflowError را پرتاب کنند. برای جلوگیری از پرتاب OverflowError در آزمون مقدار درستی، یک شیء باید متد __bool__() را تعریف کند.

object.__length_hint__(self)

برای پیاده‌سازی operator.length_hint() فراخوانی می‌شود. باید یک طول تخمینی برای شیء برگرداند (که ممکن است بیشتر یا کمتر از طول واقعی باشد). طول باید یک عدد صحیح >= ۰ باشد. مقدار بازگشتی همچنین می‌تواند NotImplemented باشد، که همان‌طور با آن رفتار می‌شود که گویی متد __length_hint__ اصلاً وجود ندارد. این متد صرفاً یک بهینه‌سازی است و هرگز برای صحت ضروری نیست.

اضافه شده در نسخه‌ی 3.4.

object.__getitem__(self, subscript)

برای پیاده‌سازی زیرنویسی (subscription)، یعنی self[subscript]، فراخوانی می‌شود. برای جزئیات سینتکس، زیرنویسی‌ها و اسلایس کردن‌ها را ببینید.

دو نوع شیء توکار وجود دارند که از زیرنویسی از طریق __getitem__() پشتیبانی می‌کنند:

  • دنباله‌ها، که در آن‌ها زیرنویس (که به آن اندیس، شماره نیز نامیده می‌شود) باید یک عدد صحیح یا یک شیء slice باشد. برای رفتار مورد انتظار، از جمله مدیریت اشیاء slice و اندیس‌های منفی، مستندات دنباله را ببینید.

  • نگاشت‌ها، که در آن‌ها subscript نیز key نامیده می‌شود. برای رفتار مورد انتظار، مستندات نگاشت را ببینید.

اگر زیرنویس از نوع نامناسبی باشد، __getitem__() باید TypeError را پرتاب کند. اگر زیرنویس مقدار نامناسبی داشته باشد، __getitem__() باید LookupError یا یکی از زیرکلاس‌های آن را پرتاب کند (IndexError برای دنباله‌ها؛ KeyError برای نگاشت‌ها).

توجه

اسلایس توسط __getitem__()، __setitem__() و __delitem__() مدیریت می‌شود. فراخوانی مانند

a[1:2] = b

ترجمه می‌شود به

a[slice(1, 2, None)] = b

و غیره. آیتم‌های غایب اسلایس همیشه با None پر می‌شوند.

توجه

پروتکل پیمایش دنباله (که برای مثال در حلقه‌های for استفاده می‌شود)، انتظار دارد که برای اندیس‌های غیرمجاز، یک IndexError پرتاب شود تا امکان تشخیص صحیح پایان یک دنباله فراهم شود.

توجه

هنگام زیرنویسی یک کلاس، ممکن است متد کلاسی ویژه‌ی __class_getitem__() به‌جای __getitem__() فراخوانی شود. برای جزئیات بیشتر، __class_getitem__ در برابر __getitem__ را ببینید.

object.__setitem__(self, key, value)

برای پیاده‌سازی انتساب به self[key] فراخوانی می‌شود. همان نکته‌ای که برای __getitem__() ذکر شد، در اینجا نیز صدق می‌کند. این متد باید فقط برای نگاشت‌ها در صورتی پیاده‌سازی شود که اشیاء از تغییر مقادیر مربوط به کلیدها پشتیبانی کنند یا بتوان کلیدهای جدیدی افزود، یا برای دنباله‌ها در صورتی که بتوان عناصر را جایگزین کرد. برای مقادیر نامناسب کلید نیز باید همان استثناهایی پرتاب شوند که برای متد __getitem__() پرتاب می‌شوند.

object.__delitem__(self, key)

برای پیاده‌سازی حذف self[key] فراخوانی می‌شود. همان نکته‌ای که برای __getitem__() ذکر شد، صدق می‌کند. این متد باید فقط برای نگاشت‌ها در صورتی پیاده‌سازی شود که اشیاء از حذف کلیدها پشتیبانی می‌کنند، یا برای دنباله‌ها در صورتی که بتوان عناصر را از دنباله حذف کرد. برای مقادیر نامعتبر key نیز باید همان استثناهایی پرتاب شوند که برای متد __getitem__() پرتاب می‌شوند.

object.__missing__(self, key)

توسط dict.__getitem__() فراخوانی می‌شود تا self[key] را برای زیرکلاس‌های دیکشنری پیاده‌سازی کند، هنگامی که کلید در دیکشنری وجود ندارد.

object.__iter__(self)

این متد زمانی فراخوانی می‌شود که یک پیمایش‌گر برای یک ظرف مورد نیاز باشد. این متد باید یک شیء پیمایش‌گر جدید را برگرداند که بتواند تمام اشیای درون ظرف را پیمایش کند. برای نگاشت‌ها، باید کلیدهای ظرف را پیمایش کند.

object.__reversed__(self)

در صورت وجود، توسط تابع توکار reversed() برای پیاده‌سازی پیمایش معکوس فراخوانی می‌شود. باید یک شیء پیمایش‌گر جدید برگرداند که تمام اشیای درون ظرف را به ترتیب معکوس پیمایش می‌کند.

اگر متد __reversed__() فراهم نشده باشد، تابع توکار reversed() به استفاده از پروتکل دنباله (__len__() و __getitem__()) متوسل می‌شود. اشیایی که از پروتکل دنباله پشتیبانی می‌کنند، باید تنها در صورتی __reversed__() را فراهم کنند که بتوانند پیاده‌سازی کارآمدتر از پیاده‌سازی ارائه‌شده توسط reversed() فراهم کنند.

عملگرهای آزمون عضویت (in و not in) معمولاً به‌صورت یک پیمایش از میان یک ظرف پیاده‌سازی می‌شوند. با این حال، اشیای ظرف می‌توانند متد ویژه زیر را با پیاده‌سازی کارآمدتری فراهم کنند، که همچنین نیازی به پیمایش‌پذیر بودن شیء ندارد.

object.__contains__(self, item)

برای پیاده‌سازی عملگرهای آزمون عضویت فراخوانی می‌شود. باید در صورتی که item در self وجود دارد، مقدار درست و در غیر این صورت مقدار نادرست را برگرداند. برای اشیای نگاشت، باید کلیدهای نگاشت به جای مقادیر یا جفت‌های کلید-آیتم در نظر گرفته شوند.

برای شیءهایی که __contains__() را تعریف نمی‌کنند، آزمون عضویت ابتدا پیمایش را از طریق __iter__() امتحان می‌کند، سپس پروتکل قدیمی پیمایش دنباله‌ای از طریق __getitem__() را به‌کار می‌گیرد؛ بخش مربوط در مرجع زبان را ببینید.

3.3.8. شبیه‌سازی انواع عددی

متدهای زیر را می‌توان برای شبیه‌سازی اشیاء عددی تعریف کرد. متدهای متناظر با عملیاتی که توسط نوع خاصی از عدد پیاده‌سازی‌شده پشتیبانی نمی‌شوند (مثلاً عملیات بیتی برای اعداد غیرصحیح) باید تعریف‌نشده باقی بمانند.

object.__add__(self, other)
object.__sub__(self, other)
object.__mul__(self, other)
object.__matmul__(self, other)
object.__truediv__(self, other)
object.__floordiv__(self, other)
object.__mod__(self, other)
object.__divmod__(self, other)
object.__pow__(self, other[, modulo])
object.__lshift__(self, other)
object.__rshift__(self, other)
object.__and__(self, other)
object.__xor__(self, other)
object.__or__(self, other)

این متدها برای پیاده‌سازی عملیات حسابی دودویی (+، -، *، @، /، //، %، divmod()، pow()، **، <<، >>، &، ^، |) فراخوانی می‌شوند. برای مثال، برای ارزیابی عبارت x + y، در صورتی که x نمونه‌ای از کلاسی باشد که متد __add__() دارد، type(x).__add__(x, y) فراخوانی می‌شود. متد __divmod__() باید معادل استفاده از __floordiv__() و __mod__() باشد؛ نباید به __truediv__() مرتبط باشد. توجه داشته باشید که اگر قرار است نسخه‌ی سه‌آرگومانی تابع توکار pow() پشتیبانی شود، __pow__() باید به‌گونه‌ای تعریف شود که آرگومان سوم اختیاری را بپذیرد.

اگر یکی از آن متدها از عملیات با آرگومان‌های ارائه‌شده پشتیبانی نکند، باید NotImplemented را برگرداند.

object.__radd__(self, other)
object.__rsub__(self, other)
object.__rmul__(self, other)
object.__rmatmul__(self, other)
object.__rtruediv__(self, other)
object.__rfloordiv__(self, other)
object.__rmod__(self, other)
object.__rdivmod__(self, other)
object.__rpow__(self, other[, modulo])
object.__rlshift__(self, other)
object.__rrshift__(self, other)
object.__rand__(self, other)
object.__rxor__(self, other)
object.__ror__(self, other)

این متدها برای پیاده‌سازی عملیات حسابی دودویی (+، -، *، @، /، //، %، divmod()، pow()، **، <<، >>، &، ^، |) با عملوندهای بازتابی (تعویض‌شده) فراخوانی می‌شوند. این توابع تنها زمانی فراخوانی می‌شوند که عملوندها از انواع متفاوت باشند، وقتی عملوند چپ از عملیات متناظر پشتیبانی نکند [3]، یا کلاس عملوند راست از کلاس عملوند چپ مشتق شده باشد. [4] برای مثال، برای ارزیابی عبارت x - y، که در آن y نمونه‌ای از کلاسی است که متد __rsub__() را دارد، type(y).__rsub__(y, x) در صورتی فراخوانی می‌شود که type(x).__sub__(x, y) مقدار NotImplemented را برگرداند یا type(y) زیرکلاسی از type(x) باشد. [5]

توجه داشته باشید که اگر قرار است نسخه‌ی سه‌آرگومانی تابع توکار pow() پشتیبانی شود، __rpow__() باید به‌گونه‌ای تعریف شود که یک آرگومان سوم اختیاری را بپذیرد.

تغییر یافته در نسخه‌ی 3.14: pow() با ۳ آرگومان اکنون در صورت لزوم تلاش می‌کند __rpow__() را فراخوانی کند. پیش از این، فقط در pow() با ۲ آرگومان و عملگر توان دودویی فراخوانی می‌شد.

توجه

اگر نوع عملوند راست، زیرکلاسی از نوع عملوند چپ باشد و آن زیرکلاس پیاده‌سازی متفاوتی از متد بازتابی برای آن عملیات ارائه کند، این متد پیش از متد غیربازتابی عملوند چپ فراخوانی می‌شود. این رفتار به زیرکلاس‌ها اجازه می‌دهد عملیات نیاکان خود را بازنویسی کنند.

object.__iadd__(self, other)
object.__isub__(self, other)
object.__imul__(self, other)
object.__imatmul__(self, other)
object.__itruediv__(self, other)
object.__ifloordiv__(self, other)
object.__imod__(self, other)
object.__ipow__(self, other[, modulo])
object.__ilshift__(self, other)
object.__irshift__(self, other)
object.__iand__(self, other)
object.__ixor__(self, other)
object.__ior__(self, other)

این متدها برای پیاده‌سازی انتساب‌های حسابی افزوده (+=، -=، *=، @=، /=، //=، %=، **=، <<=، >>=، &=، ^=، |=) فراخوانی می‌شوند. این متدها باید تلاش کنند عملیات را به‌صورت درجا (با تغییر self) انجام دهند و نتیجه را برگردانند (که می‌تواند self باشد، اما لازم نیست self باشد). اگر متد ویژهی تعریف نشده باشد، یا اگر آن متد NotImplemented را برگرداند، انتساب افزوده به متدهای عادی بازمی‌گردد. برای مثال، اگر x نمونه‌ای از یک کلاس دارای متد __iadd__() باشد، x += y معادل x = x.__iadd__(y) است. اگر __iadd__() وجود نداشته باشد، یا اگر x.__iadd__(y) NotImplemented را برگرداند، x.__add__(y) و y.__radd__(x) در نظر گرفته می‌شوند، همان‌طور که در ارزیابی x + y انجام می‌شود. در شرایط خاص، انتساب افزوده می‌تواند به خطاهای غیرمنتظره منجر شود (به چرا a_tuple[i] += ['item'] در حالی که عمل جمع کار می‌کند، استثنا پرتاب می‌کند؟ مراجعه کنید)، اما این رفتار در واقع بخشی از مدل داده است.

object.__neg__(self)
object.__pos__(self)
object.__abs__(self)
object.__invert__(self)

برای پیاده‌سازی عملیات حسابی یک‌عملوندی (-، +، abs() و ~) فراخوانی می‌شود.

object.__complex__(self)
object.__int__(self)
object.__float__(self)

برای پیاده‌سازی توابع توکار complex()، int() و float() فراخوانی می‌شود. باید مقداری از نوع مناسب برگرداند.

object.__index__(self)

برای پیاده‌سازی operator.index() فراخوانی می‌شود، و هرگاه پایتون نیاز داشته باشد شیء عددی را بدون از دست دادن اطلاعات به یک شیء عدد صحیح تبدیل کند (مانند اسلایس کردن، یا در توابع توکار bin()، hex() و oct()). وجود این متد نشان می‌دهد که شیء عددی از نوع عدد صحیح است. باید یک عدد صحیح برگرداند.

اگر __int__()، __float__() و __complex__() تعریف‌نشده باشند، توابع توکار متناظر int()، float() و complex() به __index__() بازمی‌گردند.

object.__round__(self[, ndigits])
object.__trunc__(self)
object.__floor__(self)
object.__ceil__(self)

برای پیاده‌سازی تابع توکار round() و توابع math یعنی trunc()، floor() و ceil() فراخوانی می‌شود. مگر اینکه ndigits به __round__() ارسال شود، تمام این متدها باید مقدار شیء را به‌صورت قطع‌شده به یک Integral (معمولاً یک int) برگردانند.

تغییر یافته در نسخه‌ی 3.14: int() دیگر به متد __trunc__() ارجاع نمی‌دهد.

3.3.9. مدیران زمینه‌ی دستور with

یک مدیر زمینه (context manager) شیء است که زمینه‌ی ران‌تایمی را که باید هنگام اجرای یک دستور with برقرار شود، تعریف می‌کند. مدیر زمینه، ورود به زمینه‌ی ران‌تایم مورد نظر برای اجرای بلوک کد و خروج از آن را مدیریت می‌کند. مدیرهای زمینه به‌طور معمول با استفاده از دستور with (که در بخش with توضیح داده شده است) فراخوانی می‌شوند، اما می‌توان از آن‌ها نیز با فراخوانی مستقیم متدهایشان استفاده کرد.

کاربردهای رایج مدیرهای زمینه شامل ذخیره و بازیابی انواع مختلفی از وضعیت سراسری، قفل و باز کردن منابع، بستن پرونده‌های بازشده و غیره است.

برای اطلاعات بیشتر درباره مدیرهای زمینه، Context Manager Types را ببینید. خود کلاس object متدهای مدیر زمینه را فراهم نمی‌کند.

object.__enter__(self)

وارد زمینه ران‌تایم مرتبط با این شیء می‌شود. دستور with مقدار بازگشتی این متد را به هدف(های) مشخص‌شده در بند as دستور، در صورت وجود، مقید می‌کند.

object.__exit__(self, exc_type, exc_value, traceback)

خروج از زمینه‌ی ران‌تایم مرتبط با این شیء. پارامترها استثنایی را توصیف می‌کنند که باعث خروج از زمینه شده است. اگر زمینه بدون استثنا خارج شد، هر سه آرگومان None خواهند بود.

اگر استثنایی ارائه شده باشد و متد بخواهد آن استثنا را سرکوب کند (یعنی از انتشار آن جلوگیری کند)، باید یک مقدار درست برگرداند. در غیر این صورت، هنگام خروج از این متد، استثنا به‌صورت عادی پردازش خواهد شد.

توجه داشته باشید که متدهای __exit__() نباید استثنای دریافتی را بازپرتاب کنند؛ این مسئولیت فراخواننده است.

همچنین ملاحظه نمائید

PEP 343 - دستور "with"

مشخصات، پیش‌زمینه و مثال‌های دستور with پایتون.

3.3.10. سفارشی‌سازی آرگومان‌های جایگاهی در تطبیق الگوی کلاس

هنگام استفاده از نام یک کلاس در یک الگو، آرگومان‌های جایگاهی در الگو به‌طور پیش‌فرض مجاز نیستند، یعنی case MyClass(x, y) معمولاً بدون پشتیبانی ویژه در MyClass نامعتبر است. برای استفاده از این نوع الگو، کلاس باید یک ویژگی __match_args__ تعریف کند.

object.__match_args__

می‌توان تاپلی از رشته‌ها را به این متغیر کلاس اختصاص داد. هنگامی که از این کلاس در یک الگوی کلاس با آرگومان‌های جایگاهی استفاده شود، هر آرگومان جایگاهی با استفاده از مقدار متناظر در __match_args__ به‌عنوان کلیدواژه، به یک آرگومان کلیدواژه‌ای تبدیل می‌شود. نبود این ویژگی معادل تنظیم آن به () است.

برای مثال، اگر MyClass.__match_args__ برابر ("left", "center", "right") باشد، به این معنا است که case MyClass(x, y) معادل case MyClass(left=x, center=y) است. توجه داشته باشید که تعداد آرگومان‌های الگو باید کمتر یا مساوی تعداد عناصر __match_args__ باشد؛ اگر بیشتر باشد، تلاش برای تطبیق الگو باعث پرتاب TypeError می‌شود.

اضافه شده در نسخه‌ی 3.10.

همچنین ملاحظه نمائید

PEP 634 - تطبیق الگوی ساختاری

مشخصات دستور match پایتون.

3.3.11. شبیه‌سازی انواع بافر

پروتکل بافر راهی را فراهم می‌کند که اشیای پایتون بتوانند دسترسی کارآمد به یک آرایه‌ی حافظه‌ی سطح پایین را در معرض قرار دهند. این پروتکل توسط انواع توکار مانند bytes و memoryview پیاده‌سازی شده است، و کتابخانه‌های شخص ثالث ممکن است انواع بافر بیشتری تعریف کنند.

اگرچه انواع بافر معمولاً به زبان C پیاده‌سازی می‌شوند، اما پیاده‌سازی این پروتکل در پایتون نیز امکان‌پذیر است.

object.__buffer__(self, flags)

هنگامی که یک بافراز self درخواست شود، فراخوانی می‌شود (برای مثال، توسط سازنده memoryview). آرگومان flags یک عدد صحیح است که نشان‌دهنده نوع بافر درخواست‌شده است و برای مثال بر فقط‌خواندنی یا قابل‌نوشتن بودن بافر برگردانده‌شده تأثیر می‌گذارد. inspect.BufferFlags راه مناسبی برای تفسیر پرچم‌ها فراهم می‌کند. این متد باید یک شیء memoryview را برگرداند.

ایمنی نخی: در پایتون free-threaded، پیاده‌سازی‌ها باید هر شمارنده‌ی اکسپورت داخلی را با استفاده از عملیات اتمی مدیریت کنند. این متد باید برای فراخوانی همزمان از چندین نخ ایمن باشد، و داده‌های زیربنایی بافر برگردانده‌شده باید تا زمانی که فراخوانی متناظر با __release_buffer__() به پایان برسد، معتبر باقی بمانند. برای جزئیات، Thread safety for memoryview objects را ببینید.

object.__release_buffer__(self, buffer)

زمانی فراخوانی می‌شود که دیگر نیازی به یک بافر نباشد. آرگومان buffer یک شیء memoryview است که پیش‌تر توسط __buffer__() بازگردانده شده است. این متد باید هر منبع مرتبط با بافر را آزاد کند. این متد باید None را برگرداند.

ایمنی نخ: در پایتون free-threaded، هر کاهش شمارنده‌ی خروجی (export counter) باید با عملیات اتمی انجام شود. پاک‌سازی منابع باید ایمن از نظر نخ باشد، زیرا ممکن است آزادسازی نهایی با آزادسازی‌های همزمان از نخ‌های دیگر رقابت کند.

اشیای بافر که نیازی به انجام هیچ‌گونه پاک‌سازی ندارند، لازم نیست این متد را پیاده‌سازی کنند.

اضافه شده در نسخه‌ی 3.12.

همچنین ملاحظه نمائید

PEP 688 - دسترسی‌پذیر کردن پروتکل بافر در پایتون

متدهای __buffer__ و __release_buffer__ پایتون را معرفی می‌کند.

collections.abc.Buffer

ABC برای نوع‌های بافر.

3.3.12. حاشیه‌نویسی‌ها

توابع، کلاس‌ها و ماژول‌ها ممکن است شامل حاشیه‌نویسی‌ها باشند که راهی برای مرتبط کردن اطلاعات (معمولاً راهنمایی‌های نوع) با یک نماد هستند.

object.__annotations__

این ویژگی شامل حاشیه‌نویسی‌های یک شیء است. این ویژگی به‌صورت تنبل ارزیابی می‌شود، بنابراین دسترسی به آن ممکن است کد دلخواهی را اجرا کند و استثناهایی را پرتاب کند. اگر ارزیابی موفقیت‌آمیز باشد، این ویژگی به دیکشنری‌ای تنظیم می‌شود که نگاشتی از نام متغیرها به حاشیه‌نویسی‌ها است.

تغییر یافته در نسخه‌ی 3.14: حاشیه‌نویسی‌ها اکنون به‌صورت تنبل ارزیابی می‌شوند.

object.__annotate__(format)

یک annotate function. یک شیء دیکشنری جدید برمی‌گرداند که نام ویژگی‌ها/پارامترها را به مقادیر حاشیه‌نویسیآن‌ها نگاشت می‌کند.

یک پارامتر قالب می‌گیرد که مشخص می‌کند مقادیر حاشیه‌نویسی‌ها باید در چه قالبی ارائه شوند. این پارامتر باید عضوی از نوع شمارشی (enum) annotationlib.Format باشد، یا یک عدد صحیح با مقداری متناظر با یکی از اعضای آن نوع شمارشی.

اگر یک تابع حاشیه‌نویسی از قالب درخواست‌شده پشتیبانی نکند، باید NotImplementedError را پرتاب کند. توابع حاشیه‌نویسی باید همیشه از قالب VALUE پشتیبانی کنند؛ آن‌ها نباید هنگام فراخوانی با این قالب، NotImplementedError() را پرتاب کنند.

هنگام فراخوانی با قالب VALUE، یک تابع annotate ممکن است NameError را پرتاب کند؛ هنگامی که با درخواست هر قالب دیگری فراخوانی شود، نباید NameError را پرتاب کند.

اگر یک شیء هیچ حاشیه‌نویسی‌ای نداشته باشد، بهتر است __annotate__ روی None تنظیم شود (نمی‌توان آن را حذف کرد)، نه روی تابعی که یک دیکشنری خالی برمی‌گرداند.

اضافه شده در نسخه‌ی 3.14.

همچنین ملاحظه نمائید

PEP 649 --- ارزیابی به‌تعویق‌افتاده‌ی حاشیه‌نویسی با استفاده از توصیف‌گرها

معرفی ارزیابی تنبل حاشیه‌نویسی‌ها و تابع __annotate__.

3.3.13. جست‌وجوی متد ویژه

برای کلاس‌های سفارشی، کارکرد صحیح فراخوانی‌های ضمنی متدهای ویژه تنها زمانی تضمین می‌شود که این متدها روی نوع شیء تعریف شده باشند، نه در دیکشنری نمونه شیء. همین رفتار دلیل آن است که کد زیر یک استثنا پرتاب می‌کند:

>>> class C:
...     pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()

منطق پشت این رفتار به تعدادی از متدهای ویژه مانند __hash__() و __repr__() بازمی‌گردد که توسط همه اشیاء، از جمله اشیاء نوع، پیاده‌سازی شده‌اند. اگر جستجوی ضمنی این متدها از فرآیند جستجوی مرسوم استفاده می‌کرد، هنگام فراخوانی روی خود شیء نوع با شکست مواجه می‌شدند:

>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument

تلاش نادرست برای فراخوانی یک متد غیرمقید (unbound method) از یک کلاس به این روش، گاهی با عنوان «سردرگمی فراکلاس» شناخته می‌شود، و با دور زدن نمونه هنگام جستجوی متدهای ویژه، از آن اجتناب می‌شود:

>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True

علاوه بر دور زدن هر یک از ویژگی‌های نمونه به منظور حفظ صحت، جست‌وجوی ضمنی متد خاص معمولاً حتی متد __getattribute__() فراکلاس شیء را نیز دور می‌زند:

>>> class Meta(type):
...     def __getattribute__(*args):
...         print("Metaclass getattribute invoked")
...         return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
...     def __len__(self):
...         return 10
...     def __getattribute__(*args):
...         print("Class getattribute invoked")
...         return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__()                 # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c)          # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c)                      # Implicit lookup
10

دور زدن سازوکار __getattribute__() به این شیوه، امکان قابل‌توجهی برای بهینه‌سازی‌های سرعت درون مفسر فراهم می‌کند، به بهای از دست رفتن مقداری انعطاف‌پذیری در مدیریت متدهای ویژه (متد ویژه باید روی خود شیء کلاس تنظیم شود تا به‌طور یکنواخت توسط مفسر فراخوانی شود).

3.4. هم‌روال‌ها

3.4.1. اشیای قابل await (Awaitable Objects)

یک شیء awaitable معمولاً یک متد __await__() را پیاده‌سازی می‌کند. اشیای هم‌روال که از توابع async def برگردانده می‌شوند، awaitable هستند.

توجه

اشیای generator iterator بازگردانده‌شده از تولیدگرهایی که با types.coroutine() دکور شده‌اند، نیز قابل await (awaitable) هستند، اما __await__() را پیاده‌سازی نمی‌کنند.

object.__await__(self)

باید یک پیمایش‌گر را برگرداند. باید برای پیاده‌سازی اشیای awaitable استفاده شود. برای مثال، asyncio.Future این متد را پیاده‌سازی می‌کند تا با عبارت await سازگار باشد. خود کلاس object، awaitable نیست و این متد را ارائه نمی‌دهد.

توجه

زبان هیچ محدودیتی بر نوع یا مقدار اشیایی که پیمایش‌گر برگردانده‌شده از __await__ تولید می‌کند، اعمال نمی‌کند، زیرا این موضوع مختص پیاده‌سازی چارچوب اجرای ناهمگام (مانند asyncio) است که شیء awaitable را مدیریت خواهد کرد.

اضافه شده در نسخه‌ی 3.5.

همچنین ملاحظه نمائید

PEP 492 برای اطلاعات بیشتر درباره‌ی اشیای awaitable.

3.4.2. اشیاء هم‌روال

اشیای هم‌روال، اشیای awaitable هستند. اجرای یک هم‌روال را می‌توان با فراخوانی __await__() و تکرار بر روی نتیجه کنترل کرد. هنگامی که هم‌روال اجرای خود را به پایان رساند و مقداری را برمی‌گرداند، پیمایش‌گر استثنای StopIteration را پرتاب می‌کند و ویژگی value آن استثنا، مقدار بازگشتی را در خود نگه می‌دارد. اگر هم‌روال استثنایی را پرتاب کند، پیمایش‌گر آن استثنا را منتشر می‌کند. هم‌روال‌ها نباید مستقیماً استثناهای StopIteration مدیریت‌نشده را پرتاب کنند.

هم‌روال‌ها همچنین متدهایی دارند که در زیر فهرست شده‌اند و مشابه متدهای تولیدگرها هستند (به متدهای تولیدگر-پیمایش‌گر مراجعه کنید). با این حال، برخلاف تولیدگرها، هم‌روال‌ها به‌طور مستقیم از پیمایش پشتیبانی نمی‌کنند.

هم‌روال‌ها به‌ترتیب نسبت به انواع مقادیر yield، send و return خود عام هستند.

تغییر یافته در نسخه‌ی 3.5.2: این یک RuntimeError است که بیش از یک‌بار روی یک هم‌روال await کنید.

coroutine.send(value)

اجرای هم‌روال را آغاز می‌کند یا آن را از سر می‌گیرد. اگر value برابر None باشد، این معادل پیش بردن پیمایش‌گری است که __await__() آن را برمی‌گرداند. اگر value برابر None نباشد، این متد، کار خود را به متد send() پیمایش‌گری که باعث تعلیق هم‌روال شده است، واگذار می‌کند. نتیجه (مقدار بازگشتی، StopIteration، یا استثنای دیگر) همان نتیجه‌ای است که هنگام پیمایش بر مقدار بازگشتی __await__() که در بالا توضیح داده شد، به دست می‌آید.

coroutine.throw(value)
coroutine.throw(type[, value[, traceback]])

استثنای مشخص‌شده را در هم‌روال پرتاب می‌کند. اگر پیمایش‌گری که باعث تعلیق هم‌روال شده است چنین متدی داشته باشد، این متد به متد throw() آن پیمایش‌گر واگذار می‌شود. در غیر این صورت، استثنا در نقطه تعلیق پرتاب می‌شود. نتیجه (مقدار بازگشتی، StopIteration، یا استثنای دیگر) همان نتیجه‌ای است که هنگام پیمایش روی مقدار بازگشتی __await__()، که در بالا توضیح داده شد، به دست می‌آید. اگر استثنا در هم‌روال گرفته نشود، به فراخواننده بازمی‌گردد.

تغییر یافته در نسخه‌ی 3.12: امضای دوم (type[, value[, traceback]]) منسوخ شده است و ممکن است در نسخه‌ای آینده از پایتون حذف شود.

coroutine.close()

باعث می‌شود هم‌روال خود را پاک‌سازی کند و خارج شود. اگر هم‌روال معلق باشد، این متد ابتدا به متد close() پیمایش‌گری که باعث تعلیق هم‌روال شده است ارجاع می‌دهد، اگر آن پیمایش‌گر چنین متدی داشته باشد. سپس GeneratorExit را در نقطه تعلیق پرتاب می‌کند و باعث می‌شود هم‌روال بلافاصله خود را پاک‌سازی کند. در نهایت، هم‌روال به‌عنوان پایان‌یافته علامت‌گذاری می‌شود، حتی اگر هرگز آغاز نشده باشد.

اشیای هم‌روال هنگامی که در آستانه نابودی هستند، به‌صورت خودکار با استفاده از فرایند بالا بسته می‌شوند.

3.4.3. پیمایش‌گرهای ناهمگام

یک پیمایش‌گر ناهمگام می‌تواند کد ناهمگام را در متد __anext__ خود فراخوانی کند.

پیمایش‌گرهای ناهمگام می‌توانند در یک دستور async for استفاده شوند.

خود کلاس object این متدها را فراهم نمی‌کند.

object.__aiter__(self)

باید یک شیء پیمایش‌گر ناهمگام را برگرداند.

object.__anext__(self)

باید یک شیء انتظارپذیر (awaitable) برگرداند که به مقدار بعدی پیمایش‌گر منجر می‌شود. باید هنگامی که پیمایش به پایان رسید، خطای StopAsyncIteration را پرتاب کند.

مثالی از یک شیء پیمایش‌پذیر ناهمگام:

class Reader:
    async def readline(self):
        ...

    def __aiter__(self):
        return self

    async def __anext__(self):
        val = await self.readline()
        if val == b'':
            raise StopAsyncIteration
        return val

اضافه شده در نسخه‌ی 3.5.

تغییر یافته در نسخه‌ی 3.7: پیش از پایتون 3.7، __aiter__() می‌توانست یک awaitable را برگرداند که به یک پیمایش‌گر ناهمگام حل می‌شد.

از پایتون 3.7 به بعد، __aiter__() باید یک شیء پیمایش‌گر ناهمگام را برگرداند. برگرداندن هر چیز دیگری منجر به خطای TypeError خواهد شد.

3.4.4. مدیرهای زمینه ناهمگام

یک مدیر زمینه ناهمگام، یک مدیر زمینه است که می‌تواند اجرا را در متدهای __aenter__ و __aexit__ خود معلق کند.

می‌توان از مدیرهای زمینه ناهمگام در یک دستور async with استفاده کرد.

خود کلاس object این متدها را فراهم نمی‌کند.

object.__aenter__(self)

از نظر معنایی مشابه __enter__() است، تنها تفاوت این است که باید یک awaitable را برگرداند.

object.__aexit__(self, exc_type, exc_value, traceback)

از نظر معنایی مشابه __exit__() است، با این تفاوت که باید یک شیء انتظارپذیر (awaitable) برگرداند.

نمونه‌ای از یک کلاس مدیر زمینه ناهمگام:

class AsyncContextManager:
    async def __aenter__(self):
        await log('entering context')

    async def __aexit__(self, exc_type, exc, tb):
        await log('exiting context')

اضافه شده در نسخه‌ی 3.5.

پانویس‌ها