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. ویژگیهای خاص فقطخواندنی¶
ویژگی |
معنی |
|---|---|
|
ارجاعی به اضافه شده در نسخهی 3.10. |
|
ارجاعی به |
|
یک شیء سلول دارای ویژگی |
3.2.8.1.2. ویژگیهای ویژه قابلنوشتن¶
بیشتر این ویژگیها نوع مقدار تخصیصدادهشده را بررسی میکنند:
ویژگی |
معنی |
|---|---|
|
رشتهی مستندسازی تابع، یا |
|
نام تابع. همچنین ببینید: |
|
نام کامل تابع. همچنین ببینید: اضافه شده در نسخهی 3.3. |
|
نام ماژولی که تابع در آن تعریف شده است، یا |
|
یک |
|
شیء کد که بدنهی تابع کامپایلشده را نشان میدهد. |
|
فضای نامی که از ویژگیهای دلخواه تابع پشتیبانی میکند. همچنین ببینید: |
|
یک تغییر یافته در نسخهی 3.14: حاشیهنویسیها اکنون بهصورت تنبل ارزیابی میشوند. PEP 649 را ببینید. |
|
annotate function برای این تابع، یا اضافه شده در نسخهی 3.14. |
|
یک |
|
یک اضافه شده در نسخهی 3.12. |
اشیای تابعی همچنین از دریافت و تنظیم ویژگیهای دلخواه پشتیبانی میکنند، که میتوان از آنها برای مثال برای اتصال فراداده به توابع استفاده کرد. برای دریافت و تنظیم چنین ویژگیهایی از سینتکس نقطهای معمول ویژگیها استفاده میشود.
پیادهسازی فعلی CPython فقط از ویژگیهای تابع در توابع تعریفشده توسط کاربر پشتیبانی میکند. ممکن است در آینده از ویژگیهای تابع در توابع توکار پشتیبانی شود.
اطلاعات بیشتری درباره تعریف یک تابع را میتوان از شیء کد آن (قابل دسترسی از طریق ویژگی __code__) بازیابی کرد.
3.2.8.2. متدهای نمونه¶
یک شیء متد نمونه، یک کلاس، یک نمونهی کلاس و هر شیء فراخوانیپذیر (معمولاً یک تابع تعریفشده توسط کاربر) را ترکیب میکند.
ویژگیهای خاص فقطخواندنی:
|
به شیء نمونه کلاس اشاره میکند که متد به آن متصل است |
|
به شیء تابع اصلی ارجاع میدهد |
|
مستندات متد (مشابه |
|
نام متد (همان |
|
نام ماژولی که متد در آن تعریف شده است، یا |
متدها همچنین از دسترسی (اما نه تنظیم) به ویژگیهای دلخواه تابع در شیء تابع زیربنایی پشتیبانی میکنند.
اشیای متد تعریفشده توسط کاربر ممکن است هنگام دریافت یک ویژگی از یک کلاس (شاید از طریق یک نمونه از آن کلاس) ایجاد شوند، در صورتی که آن ویژگی یک شیء تابع تعریفشده توسط کاربر یا یک شیء 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. ویژگیهای خاص¶
ویژگی |
معنی |
|---|---|
|
نام کلاس. همچنین ببینید: |
|
نام کامل کلاس. همچنین ببینید: |
|
نام ماژولی که کلاس در آن تعریف شده است. |
|
یک |
|
یک |
|
تنها کلاس پایه در زنجیره وراثت که مسئول چیدمان حافظه نمونهها است. این ویژگی در سطح C با |
|
رشتهی مستندسازی کلاس، یا |
|
دیکشنری حاوی حاشیهنویسیهای متغیر که در طول اجرای بدنه کلاس جمعآوری شدهاند. همچنین ببینید: برای بهترین روشهای کار با هشدار دسترسی مستقیم به ویژگی این ویژگی در برخی کلاسهای توکار وجود ندارد. در کلاسهای تعریفشده توسط کاربر بدون تغییر یافته در نسخهی 3.14: حاشیهنویسیها اکنون بهصورت تنبل ارزیابی میشوند. PEP 649 را ببینید. |
|
annotate function برای این کلاس، یا در صورتی که این کلاس annotation نداشته باشد، اضافه شده در نسخهی 3.14. |
|
یک اضافه شده در نسخهی 3.12. |
|
یک اضافه شده در نسخهی 3.13. |
|
شمارهی خط نخستِ تعریف کلاس، از جمله دکوراتورها. تنظیم ویژگی اضافه شده در نسخهی 3.13. |
|
|
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__¶
کلاسی که یک نمونهی کلاس به آن تعلق دارد.
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. ویژگیهای خاص فقطخواندنی¶
|
نام تابع |
|
نام کامل تابع اضافه شده در نسخهی 3.11. |
|
تعداد کل پارامترهای جایگاهی تابع (شامل پارامترهای فقط جایگاهی و پارامترهای دارای مقادیر پیشفرض) |
|
تعداد پارامترهای فقط جایگاهی تابع (از جمله آرگومانهای دارای مقادیر پیشفرض) |
|
تعداد پارامترهای فقط کلیدواژهای تابع (شامل آرگومانهای دارای مقادیر پیشفرض) |
|
تعداد متغیرهای محلی استفادهشده در تابع (شامل پارامترها) |
|
یک |
|
یک |
|
یک توجه: ارجاعها به نامهای سراسری و توکار گنجانده نشدهاند. |
|
رشتهای که نشاندهندهی دنبالهی دستورالعملهای بایتکد در تابع است |
|
|
|
یک |
|
نام پروندهای که کد از آن کامپایل شده است |
|
شمارهی اولین خط تابع |
|
رشتهای که نگاشت از آفستهای بایتکد به شمارههای خط را کدگذاری میکند. برای جزئیات، به کد منبع مفسر مراجعه کنید. منسوخ شده از نسخهی 3.12: این ویژگی از اشیای کد منسوخ شده است و ممکن است در پایتون 3.15 حذف شود. |
|
اندازهی پشتهی مورد نیاز شیء کد |
|
یک |
بیتهای پرچم زیر برای 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 با اندیسگذاری از ۰ در خط منبع دادهشده است.این اطلاعات جایگاهی ممکن است وجود نداشته باشد. فهرستی غیرجامع از مواردی که ممکن است این اتفاق بیفتد:
اجرای مفسر با
-Xno_debug_ranges.بارگذاری یک پرونده pyc که هنگام استفاده از
-Xno_debug_rangesکامپایل شده است.تاپلهای موقعیت متناظر با دستورالعملهای مصنوعی.
شمارههای خط و ستونی که به دلیل محدودیتهای خاص پیادهسازی نمیتوانند بازنمایی شوند.
هنگامی که این اتفاق میافتد، برخی یا همهی عناصر تاپل میتوانند
Noneباشند.اضافه شده در نسخهی 3.11.
توجه
این قابلیت نیازمند ذخیرهسازی موقعیتهای ستون در اشیای کد است که ممکن است منجر به افزایش جزئی مصرف دیسک پروندههای پایتون کامپایلشده یا مصرف حافظه مفسر شود. برای اجتناب از ذخیرهسازی اطلاعات اضافی و/یا غیرفعال کردن چاپ اطلاعات اضافی ردگیری پشته، میتوان از پرچم خط فرمان
-Xno_debug_rangesیا متغیر محیطیPYTHONNODEBUGRANGESاستفاده کرد.
- codeobject.co_lines()¶
یک پیمایشگر برمیگرداند که اطلاعاتی را دربارهی بازههای متوالی بایتکدs تولید میکند. هر آیتم تولیدشده یک
tupleبهصورت(start, end, lineno)است:start(یکint) آفست شروع محدودهی بایتکد را نشان میدهد (این آفست شامل خود مقدار است)end(یکint) آفست (غیرشامل) پایان محدودهی بایتکد را نشان میدهدlinenoیکintاست که شمارهی خط محدودهی بایتکد را نشان میدهد، یا اگر بایتکدهای محدودهی دادهشده شمارهی سطری نداشته باشند،Noneاست
آیتمهای تولیدشده ویژگیهای زیر را خواهند داشت:
اولین بازهی تولیدشده دارای
startبرابر با ۰ خواهد بود.بازههای
(start, end)غیرنزولی و متوالی خواهند بود. یعنی برای هر جفتtuples،startدومی برابر با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. ویژگیهای خاص فقطخواندنی¶
|
به فریم پشتهی قبلی اشاره میکند (به سمت فراخواننده)، یا اگر این پایینترین فریم پشته باشد، |
|
شیء کد در حال اجرا در این فریم. دسترسی به این ویژگی، یک رویداد حسابرسی |
|
نگاشتی که فریم برای جستوجوی متغیرهای محلی از آن استفاده میکند. اگر فریم به یک محدوده بهینهشده اشاره کند، ممکن است یک شیء پراکسی با نوشتنهمزمان (write-through) برگردانده شود. تغییر یافته در نسخهی 3.13: یک پراکسی برای محدودههای بهینهشده بازمیگرداند. |
|
دیکشنری استفادهشده توسط فریم برای جستجوی متغیرهای سراسری |
|
دیکشنری مورد استفاده فریم برای جستجوی نامهای توکار (ذاتی) |
|
«دستورالعمل دقیق» شیء فریم (این اندیسی در رشتهی بایتکد شیء کد است) |
|
شیء تولیدگر یا همروال که مالک این فریم است، یا اضافه شده در نسخهی 3.14. |
3.2.13.2.2. ویژگیهای ویژه قابلنوشتن¶
|
اگر |
|
این ویژگی را روی |
|
این ویژگی را روی |
|
شماره خط جاری فریم — نوشتن در آن از درون یک تابع ردگیری (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 برای تشکیل یک ردگیری پشته کامل، بر عهده ایجادکننده ردگیری پشته است.
ویژگیهای خاص فقطخواندنی:
|
به فریم اجرای سطح فعلی اشاره میکند. دسترسی به این ویژگی، یک رویداد حسابرسی |
|
شمارهی سطری که استثنا در آن رخ داده است را میدهد |
|
نشاندهندهی «دستور دقیق» است. |
شماره خط و آخرین دستور در ردگیری پشته ممکن است با شماره خطِ شیء فریم آن متفاوت باشد، اگر استثنا در یک دستور 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. سفارشیسازی دسترسی به ویژگیهای ماژول¶
همچنین میتوان از نامهای ویژه __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__ را فراخوانی میکند، مراحل سفارشیسازی اضافی زیر پس از ایجاد شیء کلاس اجرا میشوند:
متد
type.__new__همهی ویژگیهای موجود در فضای نام کلاس را که متد__set_name__()را تعریف میکنند، جمعآوری میکند؛آن متدهای
__set_name__با کلاسی که در حال تعریف است و نام اختصاصدادهشده به آن ویژگی خاص فراخوانی میشوند؛قلاب
__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. شبیهسازی اشیاء فراخوانیپذیر¶
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__()نباید استثنای دریافتی را بازپرتاب کنند؛ این مسئولیت فراخواننده است.
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.BufferABC برای نوعهای بافر.
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 نیست و این متد را ارائه نمیدهد.
اضافه شده در نسخهی 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.
پانویسها