ساختارهای شیء نوع¶
شاید یکی از مهمترین ساختارهای سیستم شیء پایتون، ساختاری باشد که یک نوع جدید را تعریف میکند: ساختار PyTypeObject. اشیاء نوع را میتوان با استفاده از هر یک از توابع PyObject_* یا PyType_* مدیریت کرد، اما چیز جالب زیادی برای بیشتر برنامههای پایتون ارائه نمیدهند. این اشیاء مبنای نحوه رفتار اشیاء هستند، بنابراین برای خود مفسر و برای هر ماژول توسعهای که نوعهای جدیدی را پیادهسازی میکند بسیار مهم هستند.
اشیاء نوع در مقایسه با اکثر نوعهای استاندارد نسبتاً بزرگ هستند. دلیل این اندازه آن است که هر شیء نوع تعداد زیادی مقدار را ذخیره میکند که عمدتاً اشارهگرهای تابع C هستند و هر یک بخش کوچکی از کارکرد نوع را پیادهسازی میکند. فیلدهای شیء نوع در این بخش به تفصیل بررسی میشوند. فیلدها به ترتیبی که در ساختار قرار دارند توصیف خواهند شد.
علاوه بر مرجع سریع زیر، بخش مثالها درکی سریع و فوری از معنا و کاربرد PyTypeObject فراهم میکند.
مرجع سریع¶
جایگاههای tp¶
جایگاه PyTypeObject [1] |
متدهای ویژه/ویژگیها |
اطلاعات [2] |
||||
|---|---|---|---|---|---|---|
O |
T |
D |
I |
|||
<R> |
const char * |
__name__ |
X |
X |
||
X |
X |
X |
||||
X |
X |
|||||
X |
X |
X |
||||
X |
X |
|||||
__getattribute__, __getattr__ |
G |
|||||
__setattr__, __delattr__ |
G |
|||||
% |
||||||
__repr__ |
X |
X |
X |
|||
% |
||||||
% |
||||||
% |
||||||
__hash__ |
X |
G |
||||
__call__ |
X |
X |
||||
__str__ |
X |
X |
||||
__getattribute__, __getattr__ |
X |
X |
G |
|||
__setattr__, __delattr__ |
X |
X |
G |
|||
% |
||||||
unsigned long |
X |
X |
? |
|||
const char * |
__doc__ |
X |
X |
|||
X |
G |
|||||
X |
G |
|||||
__lt__, __le__, __eq__, __ne__, __gt__, __ge__ |
X |
G |
||||
X |
? |
|||||
__iter__ |
X |
|||||
__next__ |
X |
|||||
|
X |
X |
||||
|
X |
|||||
|
X |
X |
||||
__base__ |
X |
|||||
|
__dict__ |
? |
||||
__get__ |
X |
|||||
__set__, __delete__ |
X |
|||||
X |
? |
|||||
__init__ |
X |
X |
X |
|||
X |
? |
? |
||||
__new__ |
X |
X |
? |
? |
||
X |
X |
? |
? |
|||
X |
X |
|||||
< |
|
__bases__ |
~ |
|||
< |
|
__mro__ |
~ |
|||
[ |
|
|||||
void * |
__subclasses__ |
|||||
|
||||||
( |
||||||
unsigned int |
||||||
__del__ |
X |
|||||
unsigned char |
||||||
زیرجایگاهها (sub-slots)¶
جایگاه |
متدهای ویژه |
|
|---|---|---|
__await__ |
||
__aiter__ |
||
__anext__ |
||
__add__ __radd__ |
||
__iadd__ |
||
__sub__ __rsub__ |
||
__isub__ |
||
__mul__ __rmul__ |
||
__imul__ |
||
__mod__ __rmod__ |
||
__imod__ |
||
__divmod__ __rdivmod__ |
||
__pow__ __rpow__ |
||
__ipow__ |
||
__neg__ |
||
__pos__ |
||
__abs__ |
||
__bool__ |
||
__invert__ |
||
__lshift__ __rlshift__ |
||
__ilshift__ |
||
__rshift__ __rrshift__ |
||
__irshift__ |
||
__and__ __rand__ |
||
__iand__ |
||
__xor__ __rxor__ |
||
__ixor__ |
||
__or__ __ror__ |
||
__ior__ |
||
__int__ |
||
void * |
||
__float__ |
||
__floordiv__ |
||
__ifloordiv__ |
||
__truediv__ |
||
__itruediv__ |
||
__index__ |
||
__matmul__ __rmatmul__ |
||
__imatmul__ |
||
__len__ |
||
__getitem__ |
||
__setitem__, __delitem__ |
||
__len__ |
||
__add__ |
||
__mul__ |
||
__getitem__ |
||
__setitem__ __delitem__ |
||
__contains__ |
||
__iadd__ |
||
__imul__ |
||
__buffer__ |
||
__release_buffer__ |
||
تعریفهای نوع جایگاه (slot typedefs)¶
typedef |
انواع پارامتر |
نوع بازگشتی |
|---|---|---|
|
||
|
void |
|
void * |
void |
|
int |
||
|
||
int |
||
|
|
|
PyObject *const char *
|
|
|
int |
||
|
||
int |
||
|
||
int |
||
|
Py_hash_t |
|
|
||
|
|
|
|
|
|
|
||
int |
||
void |
||
|
int |
|
PyObject * |
|
|
|
||
|
||
|
||
int |
||
int |
||
int |
برای جزئیات بیشتر، typedefهای نوع جایگاه را در ادامه ببینید.
تعریف PyTypeObject¶
تعریف ساختار PyTypeObject را میتوان در Include/cpython/object.h یافت. برای سهولت مراجعه، این بخش تعریف موجود در آنجا را تکرار میکند:
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
PyMethodDef *tp_methods;
PyMemberDef *tp_members;
PyGetSetDef *tp_getset;
// Strong reference on a heap type, borrowed reference on a static type
PyTypeObject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
Py_ssize_t tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache; /* no longer used */
void *tp_subclasses; /* for static builtin types this is an index */
PyObject *tp_weaklist; /* not used for static builtin types */
destructor tp_del;
/* Type attribute cache version tag. Added in version 2.6.
* If zero, the cache is invalid and must be initialized.
*/
unsigned int tp_version_tag;
destructor tp_finalize;
vectorcallfunc tp_vectorcall;
/* bitset of which type-watchers care about this type */
unsigned char tp_watched;
/* Number of tp_version_tag values used.
* Set to _Py_ATTR_CACHE_UNUSED if the attribute cache is
* disabled for this type (e.g. due to custom MRO entries).
* Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere).
*/
uint16_t tp_versions_used;
} PyTypeObject;
جایگاههای PyObject¶
ساختار شیء نوع، ساختار PyVarObject را گسترش میدهد. فیلد ob_size برای نوعهای پویا استفاده میشود (ایجادشده توسط type_new() که معمولاً از یک دستور کلاس فراخوانی میشود). توجه داشته باشید که PyType_Type (فرانوع) مقدار tp_itemsize را مقداردهی اولیه میکند، که این بدان معناست که نمونههای آن (یعنی اشیاء نوع) باید فیلد ob_size را داشته باشند.
شمارش ارجاع شیء نوع توسط ماکروی
PyObject_HEAD_INITبه1مقداردهی اولیه میشود. توجه داشته باشید که برای اشیای نوع تخصیصیافته بهصورت ایستا، نمونههای نوع (اشیایی کهob_typeآنها به خود نوع اشاره میکند) بهعنوان ارجاع شمرده نمیشوند. اما برای اشیای نوع تخصیصیافته بهصورت پویا، نمونهها بهعنوان ارجاع شمرده میشوند.ارثبری:
این فیلد توسط زیرنوعها به ارث برده نمیشود.
این، نوعِ نوع است؛ به عبارت دیگر، فرانوع (metatype) آن است. این فیلد با آرگومان ماکروی
PyObject_HEAD_INITمقداردهی اولیه میشود و مقدار آن معمولاً باید&PyType_Typeباشد. با این حال، برای ماژولهای توسعهای قابل بارگذاری پویا که باید در ویندوز (دستکم) قابل استفاده باشند، کامپایلر شکایت میکند که این یک مقداردهندهی اولیهی معتبر نیست. بنابراین، قرارداد بر این است کهNULLبه ماکرویPyObject_HEAD_INITداده شود و این فیلد بهطور صریح در ابتدای تابع مقداردهی اولیهی ماژول، پیش از انجام هر کار دیگری، مقداردهی اولیه شود. این کار معمولاً به این شکل انجام میشود:Foo_Type.ob_type = &PyType_Type;این کار باید پیش از ایجاد هر نمونهای از این نوع انجام شود.
PyType_Ready()بررسی میکند که آیاob_typeبرابرNULLاست یا خیر، و در این صورت، آن را به فیلدob_typeکلاس پایه مقداردهی اولیه میکند.PyType_Ready()در صورتی که این فیلد ناصفر باشد، آن را تغییر نمیدهد.ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
جایگاههای PyVarObject¶
برای اشیاء نوع با تخصیص ایستا، این باید به صفر مقداردهی اولیه شود. برای اشیاء نوع با تخصیص پویا، این فیلد معنای درونی خاصی دارد.
برای دسترسی به این فیلد باید از ماکروی
Py_SIZE()استفاده شود.ارثبری:
این فیلد توسط زیرنوعها به ارث برده نمیشود.
جایگاههای PyTypeObject¶
هر جایگاه بخشی دارد که وراثت را توصیف میکند. اگر ممکن است PyType_Ready() هنگامی که فیلد برابر NULL تنظیم شده باشد، مقداری تعیین کند، آنگاه بخشی نیز با عنوان «پیشفرض» وجود خواهد داشت. (توجه داشته باشید که بسیاری از فیلدهای تنظیمشده در PyBaseObject_Type و PyType_Type عملاً بهعنوان پیشفرض عمل میکنند.)
-
const char *PyTypeObject.tp_name¶
اشارهگر به رشتهی پایانیافته با تهی که نام نوع را در بر دارد. برای نوعهایی که بهصورت متغیرهای سراسری ماژول در دسترساند، این رشته باید شامل نام کامل ماژول، سپس یک نقطه و سپس نام نوع باشد؛ برای نوعهای توکار، باید فقط نام نوع باشد. اگر ماژول، زیرماژولی از یک بسته باشد، نام کامل بسته بخشی از نام کامل ماژول است. برای مثال، نوعی با نام
Tکه در ماژولMدر زیربستهیQدر بستهیPتعریفشده باشد، باید مقداردهندهی اولیهیtp_nameآن"P.Q.M.T"باشد.برای شیءهای نوعِ تخصیصیافته بهصورت پویا، این باید فقط نام نوع باشد و نام ماژول بهصورت صریح در دیکشنری نوع بهعنوان مقدار کلید
'__module__'ذخیره شود.برای شیءهای نوع تخصیصیافته بهصورت ایستا، فیلد tp_name باید حاوی یک نقطه باشد. همهچیز پیش از آخرین نقطه بهعنوان ویژگی
__module__و همهچیز پس از آخرین نقطه بهعنوان ویژگی__name__در دسترس قرار میگیرد.اگر نقطهای وجود نداشته باشد، کل فیلد
tp_nameبهعنوان ویژگی__name__در دسترس قرار میگیرد و ویژگی__module__تعریفنشده است (مگر آنکه بهطور صریح در دیکشنری تنظیم شده باشد، همانطور که در بالا توضیح داده شد). این بدان معناست که پیکلکردن نوع شما ناممکن خواهد بود. علاوه بر این، در مستندات ماژولهایی که با pydoc ایجاد میشوند فهرست نخواهد شد.این فیلد نباید
NULLباشد. این تنها فیلد الزامی درPyTypeObject()است (بهجز احتمالاًtp_itemsize).ارثبری:
این فیلد توسط زیرنوعها به ارث برده نمیشود.
-
Py_ssize_t PyTypeObject.tp_basicsize¶
-
Py_ssize_t PyTypeObject.tp_itemsize¶
این فیلدها محاسبهی اندازهی نمونههای نوع بر حسب بایت را ممکن میسازند.
دو گونه نوع وجود دارد: نوعهایی با نمونههای طول ثابت، فیلد
tp_itemsizeصفر دارند و نوعهایی با نمونههای طول متغیر، فیلدtp_itemsizeغیرصفر دارند. برای نوعی با نمونههای طول ثابت، همه نمونهها اندازه یکسانی دارند که درtp_basicsizeداده شده است. (میتوان با استفاده ازPyUnstable_Object_GC_NewWithExtraData()برای این قاعده استثنا قائل شد.)برای نوعی که نمونههای آن طول متغیر دارند، نمونهها باید دارای فیلد
ob_sizeباشند و اندازهی نمونه برابر است باtp_basicsizeبهاضافهی N برابرtp_itemsize، که در آن N «طول» شیء است.توابعی مانند
PyObject_NewVar()مقدار N را بهعنوان آرگومان میگیرند و آن را در فیلدob_sizeنمونه ذخیره میکنند. توجه داشته باشید که فیلدob_sizeممکن است بعداً برای منظورهای دیگری استفاده شود. برای مثال، نمونههایintبیتهایob_sizeرا به شیوهای که توسط پیادهسازی تعریف شده است استفاده میکنند؛ برای دسترسی به ذخیرهسازی زیرین و اندازهی آن باید ازPyLong_Export()استفاده کرد.توجه
برای دسترسی به فیلد
ob_sizeباید از ماکروهایPy_SIZE()وPy_SET_SIZE()استفاده کرد.همچنین، وجود یک فیلد
ob_sizeدر چیدمان نمونه به این معنا نیست که ساختار نمونه طول متغیر دارد. برای مثال، نوعlistنمونههایی با طول ثابت دارد، با این حال آن نمونهها فیلدob_sizeدارند. (مانندint، از خواندن مستقیمob_sizeفهرستها خودداری کنید. در عوضPyList_Size()را فراخوانی کنید.)tp_basicsizeشامل اندازهی مورد نیاز برای دادههایtp_baseنوع، بهعلاوهی هر دادهی اضافی مورد نیاز برای هر نمونه است.روش صحیح برای تنظیم
tp_basicsize، استفاده از عملگرsizeofروی ساختاری است که برای اعلان چیدمان نمونه به کار میرود. این ساختار باید ساختاری را که برای اعلان نوع پایه به کار میرود، در بر بگیرد. به عبارت دیگر،tp_basicsizeباید بزرگتر از یا برابر باtp_basicsizeنوع پایه باشد.از آنجا که هر نوع، زیرنوعی از
objectاست، این ساختار باید شاملPyObjectیاPyVarObjectباشد (بسته به اینکه آیاob_sizeباید در آن گنجانده شود یا نه). اینها معمولاً بهترتیب توسط ماکرویPyObject_HEADیاPyObject_VAR_HEADتعریف میشوند.اندازه پایه شامل اندازه سرآیند GC نیست، زیرا آن سرآیند بخشی از
PyObject_HEADنیست.برای مواردی که ساختار استفادهشده برای اعلان نوع پایه نامشخص است، به
PyType_Spec.basicsizeوPyType_FromMetaclass()مراجعه کنید.نکاتی دربارهی ترازبندی (alignment):
tp_basicsizeباید مضربی از_Alignof(PyObject)باشد. هنگام استفاده ازsizeofبر روی یکstructکهPyObject_HEADرا در بر میگیرد، همانطور که توصیه میشود، کامپایلر این موضوع را تضمین میکند. اگر از یکstructدر C استفاده نکنید یا از افزونههای کامپایلر مانند__attribute__((packed))استفاده کنید، این کار بر عهدهی شماست.اگر آیتمهای متغیر به ترازبندی خاصی نیاز داشته باشند،
tp_basicsizeوtp_itemsizeباید هر کدام مضربی از آن ترازبندی باشند. برای مثال، اگر بخش متغیرِ یک نوع،doubleذخیره کند، مسئولیت شماست که هر دو فیلد مضربی از_Alignof(double)باشند.
ارثبری:
این فیلدها بهطور جداگانه توسط زیرنوعها به ارث برده میشوند. (یعنی اگر فیلد روی صفر تنظیم شده باشد،
PyType_Ready()مقدار را از نوع پایه کپی میکند، که نشان میدهد نمونهها نیازی به فضای ذخیرهسازی اضافی ندارند.)اگر نوع پایه دارای
tp_itemsizeناصفر باشد، بهطور کلی ایمن نیست کهtp_itemsizeرا در یک زیرنوع به مقدار ناصفر متفاوتی تنظیم کنید (هرچند این امر به پیادهسازی نوع پایه بستگی دارد).
-
destructor PyTypeObject.tp_dealloc¶
The corresponding slot ID
Py_tp_deallocis part of the ABI پایدار.اشارهگری به تابع مخرب نمونه. امضای تابع به صورت زیر است:
void tp_dealloc(PyObject *self);
تابع مخرب باید تمام ارجاعهایی را که نمونه مالک آنهاست حذف کند (مثلاً
Py_CLEAR()را فراخوانی کند)، تمام بافرهای حافظهای را که در مالکیت نمونهاند آزاد کند و برای آزاد کردن خودِ شیء، تابعtp_freeنوع را فراخوانی کند.اگر ممکن است توابعی را فراخوانی کنید که نشانگر خطا را تنظیم کنند، باید از
PyErr_GetRaisedException()وPyErr_SetRaisedException()استفاده کنید تا مطمئن شوید نشانگر خطای از پیش موجود را از بین نمیبرید (آزادسازی ممکن است هنگام پردازش خطایی دیگر رخ داده باشد):static void foo_dealloc(foo_object *self) { PyObject *et, *ev, *etb; PyObject *exc = PyErr_GetRaisedException(); ... PyErr_SetRaisedException(exc); }
خودِ هندلر تخصیصزدایی (dealloc) نباید استثنایی پرتاب کند؛ اگر با مورد خطایی مواجه شود، باید
PyErr_FormatUnraisable()را فراخوانی کند تا استثنای غیرقابلپرتاب (unraisable) را گزارش (و پاک) کند.هیچ تضمینی وجود ندارد که یک شیء چه زمانی نابود میشود، مگر:
پایتون یک شیء را بلافاصله یا مدتی پس از حذف آخرین ارجاع به آن نابود میکند، مگر آنکه نهاییساز آن (
tp_finalize) متعاقباً شیء را احیا کند.یک شیء تا زمانی که در حال نهاییسازی خودکار (
tp_finalize) یا پاکسازی خودکار (tp_clear) است، نابود نخواهد شد.
سیپایتون در حال حاضر یک شیء را هنگامی که شمارش ارجاع جدید صفر است، بلافاصله از طریق
Py_DECREF()نابود میکند، اما این ممکن است در نسخهای در آینده تغییر کند.توصیه میشود که
PyObject_CallFinalizerFromDealloc()در ابتدایtp_deallocفراخوانی شود تا تضمین شود که شیء همیشه پیش از تخریب نهاییسازی میشود.اگر نوع از زبالهروبی پشتیبانی کند (پرچم
Py_TPFLAGS_HAVE_GCتنظیم شده باشد)، مخرب باید پیش از پاک کردن هر یک از فیلدهای عضو،PyObject_GC_UnTrack()را فراخوانی کند.مجاز است که
tp_clearرا ازtp_deallocفراخوانی کنید تا از تکرار کد کاسته شود و تضمین شود که شیء همیشه پیش از انهدام پاکسازی میشود. مراقب باشید که ممکن استtp_clearاز پیش فراخوانی شده باشد.اگر نوع در هیپ تخصیصیافته باشد (
Py_TPFLAGS_HEAPTYPE)، تخصیصگشا باید پس از فراخوانی تخصیصگشای نوع، ارجاع مالکانه به شیء نوع خود را (از طریقPy_DECREF()) آزاد کند. کد نمونه را در ادامه ببینید.:static void foo_dealloc(PyObject *op) { foo_object *self = (foo_object *) op; PyObject_GC_UnTrack(self); Py_CLEAR(self->ref); Py_TYPE(self)->tp_free(self); }
tp_deallocباید وضعیت استثنا را بدون تغییر بگذارد. اگر لازم باشد چیزی را فراخوانی کند که ممکن است استثنا ایجاد کند، وضعیت استثنا باید ابتدا پشتیبانگیری و بعداً بازگردانی شود (پس از گزارشگیری هرگونه استثنا باPyErr_WriteUnraisable()).مثال:
static void foo_dealloc(PyObject *self) { PyObject *exc = PyErr_GetRaisedException(); if (PyObject_CallFinalizerFromDealloc(self) < 0) { // self was resurrected. goto done; } PyTypeObject *tp = Py_TYPE(self); if (tp->tp_flags & Py_TPFLAGS_HAVE_GC) { PyObject_GC_UnTrack(self); } // Optional, but convenient to avoid code duplication. if (tp->tp_clear && tp->tp_clear(self) < 0) { PyErr_WriteUnraisable(self); } // Any additional destruction goes here. tp->tp_free(self); self = NULL; // In case PyErr_WriteUnraisable() is called below. if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_CLEAR(tp); } done: // Optional, if something was called that might have raised an // exception. if (PyErr_Occurred()) { PyErr_WriteUnraisable(self); } PyErr_SetRaisedException(exc); }
tp_deallocممکن است از هر نخ پایتون فراخوانی شود، نه فقط از نخی که شیء را ایجاد کرده است (اگر شیء بخشی از یک چرخه شمارش ارجاع شود، ممکن است آن چرخه توسط یک زبالهروبی روی هر نخ جمعآوری شود). این برای فراخوانیهای API پایتون مشکلی نیست، زیرا نخی کهtp_deallocروی آن فراخوانی میشود، دارای وضعیت نخ متصل است. با این حال، اگر شیءِ در حال نابود شدن به نوبه خود اشیایی از یک کتابخانه C دیگر را نابود کند، باید دقت کنید تا مطمئن شوید که نابود کردن آن اشیا روی نخی کهtp_deallocرا فراخوانی کرده است، هیچیک از فرضهای آن کتابخانه را نقض نخواهد کرد.ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
همچنین ملاحظه نمائید
چرخهی حیات شیء را برای جزئیات دربارهی نحوهی ارتباط این جایگاه با جایگاههای دیگر ببینید.
-
Py_ssize_t PyTypeObject.tp_vectorcall_offset¶
آفست اختیاری برای تابعی بهازای هر نمونه که فراخوانی شیء را با استفاده از پروتکل vectorcall پیادهسازی میکند؛ این پروتکل جایگزینی کارآمدتر برای
tp_callسادهتر است.این فیلد تنها زمانی استفاده میشود که پرچم
Py_TPFLAGS_HAVE_VECTORCALLتنظیم شده باشد. در این صورت، این فیلد باید یک عدد صحیح مثبت حاوی آفست اشارهگرvectorcallfuncدر نمونه باشد.اشارهگر vectorcallfunc ممکن است
NULLباشد، که در این صورت نمونه به گونهای رفتار میکند که گوییPy_TPFLAGS_HAVE_VECTORCALLتنظیم نشده است: فراخوانی نمونه بهtp_callبازمیگردد.هر کلاسی که
Py_TPFLAGS_HAVE_VECTORCALLرا تنظیم میکند، بایدtp_callرا نیز تنظیم کند و اطمینان حاصل کند که رفتار آن با تابع vectorcallfunc سازگار است. این کار را میتوان با تنظیم tp_call برابر باPyVectorcall_Call()انجام داد.تغییر یافته در نسخهی 3.8: پیش از نسخه 3.8، این جایگاه
tp_printنام داشت. در پایتون 2.x، از آن برای چاپ در یک پرونده استفاده میشد. در پایتون 3.0 تا 3.7، استفاده نمیشد.تغییر یافته در نسخهی 3.12: پیش از نسخه 3.12، توصیه نمیشد که نوعهای هیپِ تغییرپذیر پروتکل vectorcall را پیادهسازی کنند. هنگامی که کاربر
__call__را در کد پایتون تنظیم میکند، تنها tp_call بهروزرسانی میشود که احتمالاً آن را با تابع vectorcall ناسازگار میسازد. از نسخه 3.12 به بعد، تنظیم__call__بهینهسازی vectorcall را با پاک کردن پرچمPy_TPFLAGS_HAVE_VECTORCALLغیرفعال میکند.ارثبری:
این فیلد همیشه به ارث برده میشود. با این حال، پرچم
Py_TPFLAGS_HAVE_VECTORCALLهمیشه به ارث برده نمیشود. اگر این پرچم تنظیم نشده باشد، زیرکلاس از vectorcall استفاده نخواهد کرد، مگر اینکهPyVectorcall_Call()بهطور صریح فراخوانی شود.
-
getattrfunc PyTypeObject.tp_getattr¶
The corresponding slot ID
Py_tp_getattris part of the ABI پایدار.اشارهگر اختیاری به تابع get-attribute-string.
این فیلد منسوخ شده است. هنگامی که تعریف شود، باید به تابعی اشاره کند که مانند تابع
tp_getattroعمل میکند، اما بهجای شیء رشته پایتون، یک رشته C برای ارائهی نام ویژگی میگیرد.ارثبری:
گروه:
tp_getattr،tp_getattroاین فیلد به همراه
tp_getattroتوسط زیرنوعها به ارث میرسد: یک زیرنوع، هر دوtp_getattrوtp_getattroرا از نوع پایه خود به ارث میبرد، زمانی کهtp_getattrوtp_getattroزیرنوع هر دوNULLباشند.
-
setattrfunc PyTypeObject.tp_setattr¶
The corresponding slot ID
Py_tp_setattris part of the ABI پایدار.یک اشارهگر اختیاری به تابعِ تنظیم و حذف ویژگیها.
این فیلد منسوخ شده است. هنگامی که تعریف میشود، باید به تابعی اشاره کند که مانند تابع
tp_setattroعمل میکند، اما به جای شیء رشتهی پایتون، یک رشتهی C برای ارائهی نام ویژگی میپذیرد.ارثبری:
گروه:
tp_setattr،tp_setattroاین فیلد همراه با
tp_setattroتوسط زیرنوعها به ارث برده میشود: یک زیرنوع هر دوtp_setattrوtp_setattroرا از نوع پایهی خود به ارث میبرد وقتی کهtp_setattrوtp_setattroآن هر دوNULLباشند.
-
PyAsyncMethods *PyTypeObject.tp_as_async¶
اشارهگر به یک ساختار اضافی که فیلدهایی را در بر میگیرد که تنها به اشیایی مربوطاند که پروتکلهای awaitable و asynchronous iterator را در سطح C پیادهسازی میکنند. برای جزئیات به ساختارهای اشیای ناهمگام مراجعه کنید.
اضافه شده در نسخهی 3.5: قبلاً با نام
tp_compareوtp_reservedشناخته میشد.ارثبری:
فیلد
tp_as_asyncبه ارث نمیرسد، اما فیلدهای درون آن بهصورت جداگانه به ارث میرسند.
-
reprfunc PyTypeObject.tp_repr¶
The corresponding slot ID
Py_tp_repris part of the ABI پایدار.اشارهگر اختیاری به تابعی که تابع توکار
repr()را پیادهسازی میکند.امضا همانند
PyObject_Repr()است:PyObject *tp_repr(PyObject *self);
این تابع باید یک رشته یا یک شیء یونیکد را برگرداند. در حالت ایدهآل، این تابع باید رشتهای را برگرداند که وقتی به
eval()پاس داده شود، با فراهم بودن محیطی مناسب، شیئی با همان مقدار را بازگرداند. اگر این کار امکانپذیر نباشد، باید رشتهای را برگرداند که با'<'شروع میشود و به'>'ختم میشود و از روی آن میتوان هم نوع و هم مقدار شیء را استنباط کرد.ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
پیشفرض:
هنگامی که این فیلد تنظیم نشده باشد، رشتهای به شکل
<%s object at %p>برگردانده میشود که در آن%sبا نام نوع و%pبا نشانی حافظهی شیء جایگزین میشود.
-
PyNumberMethods *PyTypeObject.tp_as_number¶
اشارهگر به یک ساختار اضافی که فیلدهایی را در بر دارد که تنها برای اشیایی که پروتکل عددی را پیادهسازی میکنند مربوطاند. این فیلدها در ساختارهای شیء عدد مستند شدهاند.
ارثبری:
فیلد
tp_as_numberبه ارث برده نمیشود، اما فیلدهای درون آن بهصورت جداگانه به ارث برده میشوند.
-
PySequenceMethods *PyTypeObject.tp_as_sequence¶
اشارهگر به یک ساختار اضافی که فیلدهایی را در بر میگیرد که تنها به اشیائی مربوطاند که پروتکل دنباله را پیادهسازی میکنند. این فیلدها در ساختارهای اشیاء دنباله مستند شدهاند.
ارثبری:
فیلد
tp_as_sequenceبه ارث برده نمیشود، اما فیلدهای درون آن بهصورت جداگانه به ارث برده میشوند.
-
PyMappingMethods *PyTypeObject.tp_as_mapping¶
اشارهگر به ساختاری اضافی که فیلدهایش تنها به اشیایی مربوط است که پروتکل نگاشت را پیادهسازی میکنند. این فیلدها در ساختارهای شیء نگاشت مستند شدهاند.
ارثبری:
فیلد
tp_as_mappingبه ارث نمیرسد، اما فیلدهای درون آن بهصورت جداگانه به ارث میرسند.
-
hashfunc PyTypeObject.tp_hash¶
The corresponding slot ID
Py_tp_hashis part of the ABI پایدار.یک اشارهگر اختیاری به تابعی که تابع توکار
hash()را پیادهسازی میکند.امضا همانند
PyObject_Hash()است:Py_hash_t tp_hash(PyObject *);
مقدار
-1نباید بهعنوان یک مقدار بازگشتی عادی برگردانده شود؛ هنگامی که در حین محاسبهی مقدار هش خطایی رخ میدهد، تابع باید یک استثنا تنظیم کرده و-1را برگرداند.وقتی این فیلد تنظیم نشده باشد (و
tp_richcompareنیز تنظیم نشده باشد)، تلاش برای گرفتن هش شیء باعث ایجاد استثنایTypeErrorمیشود. این همانند تنظیم آن بهPyObject_HashNotImplemented()است.این فیلد را میتوان بهطور صریح روی
PyObject_HashNotImplemented()تنظیم کرد تا از ارثبری متد هش از نوع والد جلوگیری شود. این بهعنوان معادل__hash__ = Noneدر سطح پایتون تفسیر میشود و باعث میشودisinstance(o, collections.Hashable)بهدرستیFalseرا برگرداند. توجه داشته باشید که عکس این موضوع نیز صادق است — تنظیم__hash__ = Noneروی یک کلاس در سطح پایتون باعث میشود جایگاهtp_hashرویPyObject_HashNotImplemented()تنظیم شود.ارثبری:
گروه:
tp_hash،tp_richcompareاین فیلد به همراه
tp_richcompareتوسط زیرنوعها به ارث برده میشود: یک زیرنوع هر دوtp_richcompareوtp_hashرا به ارث میبرد، زمانی کهtp_richcompareوtp_hashزیرنوع هر دوNULLباشند.پیشفرض:
PyBaseObject_TypeازPyObject_GenericHash()استفاده میکند.
-
ternaryfunc PyTypeObject.tp_call¶
The corresponding slot ID
Py_tp_callis part of the ABI پایدار.اشارهگر اختیاری به تابعی که فراخوانی شیء را پیادهسازی میکند. اگر شیء فراخوانیپذیر نباشد، این اشارهگر باید
NULLباشد. امضای این تابع همانندPyObject_Call()است:PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwargs);
ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
-
reprfunc PyTypeObject.tp_str¶
The corresponding slot ID
Py_tp_stris part of the ABI پایدار.یک اشارهگر اختیاری به تابعی که عملیات توکار
str()را پیادهسازی میکند. (توجه داشته باشید کهstrاکنون یک نوع است وstr()سازندهی آن نوع را فراخوانی میکند. این سازنده برای انجام کار اصلیPyObject_Str()را فراخوانی میکند وPyObject_Str()این هندلر را فراخوانی خواهد کرد.)امضا همانند
PyObject_Str()است:PyObject *tp_str(PyObject *self);
این تابع باید یک رشته یا یک شیء یونیکد را برگرداند. این باید نمایش رشتهای «دوستانه» از شیء باشد، زیرا این نمایشی است که، از جمله موارد دیگر، توسط تابع
print()استفاده خواهد شد.ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
پیشفرض:
هنگامی که این فیلد تنظیمنشده باشد،
PyObject_Repr()برای برگرداندن یک نمایش رشتهای فراخوانی میشود.
-
getattrofunc PyTypeObject.tp_getattro¶
The corresponding slot ID
Py_tp_getattrois part of the ABI پایدار.اشارهگر اختیاری به تابع دریافت ویژگی.
امضا همانند
PyObject_GetAttr()است:PyObject *tp_getattro(PyObject *self, PyObject *attr);
معمولاً مناسب است که این فیلد را روی
PyObject_GenericGetAttr()تنظیم کنید که روش معمولِ جستجوی ویژگیهای شیء را پیادهسازی میکند.ارثبری:
گروه:
tp_getattr،tp_getattroاین فیلد همراه با
tp_getattrتوسط زیرنوعها به ارث برده میشود: زیرنوع زمانی هر دوtp_getattrوtp_getattroرا از نوع پایهی خود به ارث میبرد که هر دوtp_getattrوtp_getattroآنNULLباشند.پیشفرض:
PyBaseObject_TypeازPyObject_GenericGetAttr()استفاده میکند.
-
setattrofunc PyTypeObject.tp_setattro¶
The corresponding slot ID
Py_tp_setattrois part of the ABI پایدار.یک اشارهگر اختیاری به تابعِ تنظیم و حذف ویژگیها.
امضا همان امضای
PyObject_SetAttr()است:int tp_setattro(PyObject *self, PyObject *attr, PyObject *value);
علاوه بر این، باید از تنظیم value به
NULLبرای حذف یک ویژگی پشتیبانی شود. معمولاً سودمند است که این فیلد را بهPyObject_GenericSetAttr()تنظیم کنید که روش معمول تنظیم ویژگیهای شیء را پیادهسازی میکند.ارثبری:
گروه:
tp_setattr،tp_setattroاین فیلد به همراه
tp_setattrتوسط زیرنوعها به ارث برده میشود: زیرنوعی کهtp_setattrوtp_setattroآن هر دوNULLهستند، هر دوtp_setattrوtp_setattroرا از نوع پایه خود به ارث میبرد.پیشفرض:
PyBaseObject_TypeازPyObject_GenericSetAttr()استفاده میکند.
-
PyBufferProcs *PyTypeObject.tp_as_buffer¶
اشارهگر به یک ساختار اضافی که فیلدهای آن تنها برای اشیایی که رابط بافر را پیادهسازی میکنند مربوط است. این فیلدها در ساختارهای شیء بافر مستند شدهاند.
ارثبری:
فیلد
tp_as_bufferبه ارث برده نمیشود، اما فیلدهای درون آن بهطور جداگانه به ارث برده میشوند.
-
unsigned long PyTypeObject.tp_flags¶
این فیلد یک نقاب بیتی از پرچمهای گوناگون است. برخی پرچمها معناشناسی متفاوتی را برای موقعیتهای خاص نشان میدهند؛ برخی دیگر برای نشان دادن این موضوع به کار میروند که فیلدهای خاصی در شیء نوع (یا در ساختارهای توسعهای که از طریق
tp_as_number،tp_as_sequence،tp_as_mappingوtp_as_bufferبه آنها ارجاع میشود) که بهطور تاریخی همیشه وجود نداشتهاند، معتبر هستند؛ اگر چنین بیت پرچمی صفر باشد، نباید به فیلدهای نوعی که این بیت از آنها نگهبانی میکند دسترسی پیدا کرد و باید در عوض، آنها را دارای مقدار صفر یاNULLدر نظر گرفت.ارثبری:
وراثت این فیلد پیچیده است. بیشتر بیتهای پرچم بهصورت جداگانه به ارث میرسند، یعنی اگر بیت پرچمی در نوع پایه تنظیمشده باشد، زیرنوع این بیت پرچم را به ارث میبرد. بیتهای پرچم مربوط به ساختارهای توسعهای، در صورتی که ساختار توسعهای به ارث برسد، بهطور اکید به ارث میرسند؛ یعنی مقدار بیت پرچم در نوع پایه به همراه اشارهگری به ساختار توسعهای، در زیرنوع کپی میشود. بیت پرچم
Py_TPFLAGS_HAVE_GCهمراه با فیلدهایtp_traverseوtp_clearبه ارث میرسد، یعنی بیت پرچمPy_TPFLAGS_HAVE_GCدر صورتی به ارث میرسد که در زیرنوع صفر باشد و فیلدهایtp_traverseوtp_clearدر زیرنوع موجود باشند و مقدارNULLداشته باشند.پیشفرض:
PyBaseObject_TypeازPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPEاستفاده میکند.نقابهای بیتی:
نقابهای بیتی زیر در حال حاضر تعریف شدهاند؛ این نقابها را میتوان با استفاده از عملگر
|با یکدیگر OR کرد تا مقدار فیلدtp_flagsرا تشکیل دهند. ماکرویPyType_HasFeature()یک نوع و یک مقدار پرچم، یعنی tp و f، میگیرد و بررسی میکند که آیاtp->tp_flags & fناصفر است یا خیر.-
Py_TPFLAGS_HEAPTYPE¶
این بیت زمانی تنظیم میشود که خودِ شیء نوع روی هیپ تخصیص یابد؛ برای مثال، نوعهایی که بهصورت پویا با استفاده از
PyType_FromSpec()ایجاد میشوند. در این حالت، فیلدob_typeنمونههای آن بهعنوان ارجاعی به نوع در نظر گرفته میشود و شیء نوع هنگام ایجاد شدن یک نمونهی جدید INCREF میشود و هنگام نابود شدن نمونه DECREF میشود (این مورد برای نمونههای زیرنوعها اعمال نمیشود؛ فقط نوعی که ob_type نمونه به آن ارجاع میدهد INCREF یا DECREF میشود). نوعهای هیپ همچنین باید زبالهروبی را پشتیبانی کنند، زیرا میتوانند با شیء ماژول خود چرخهی ارجاع تشکیل دهند.ارثبری:
???
-
Py_TPFLAGS_BASETYPE¶
- قسمتی از ABI پایدار.
این بیت زمانی تنظیم میشود که بتوان از این نوع بهعنوان نوع پایهی نوع دیگری استفاده کرد. اگر این بیت پاک باشد، نمیتوان از این نوع زیرنوعی ساخت (مشابه کلاس «final» در جاوا).
ارثبری:
???
-
Py_TPFLAGS_READY¶
این بیت زمانی تنظیم میشود که شیء نوع بهطور کامل توسط
PyType_Ready()مقداردهی اولیه شده باشد.ارثبری:
???
-
Py_TPFLAGS_READYING¶
این بیت هنگامی تنظیم میشود که
PyType_Ready()در حال مقداردهی اولیهی شیء نوع است.ارثبری:
???
-
Py_TPFLAGS_HAVE_GC¶
- قسمتی از ABI پایدار.
این بیت زمانی تنظیم میشود که شیء از زبالهروبی پشتیبانی کند. اگر این بیت تنظیم شده باشد، حافظهی نمونههای جدید (نگاه کنید به
tp_alloc) باید با استفاده ازPyObject_GC_NewیاPyType_GenericAlloc()تخصیص داده شود و (نگاه کنید بهtp_free) با استفاده ازPyObject_GC_Del()آزاد شود. اطلاعات بیشتر در بخش پشتیبانی از زبالهروبی چرخهای.ارثبری:
گروه:
Py_TPFLAGS_HAVE_GC،tp_traverse،tp_clearبیت پرچم
Py_TPFLAGS_HAVE_GCبه همراه فیلدهایtp_traverseوtp_clearبه ارث برده میشود؛ یعنی اگر بیت پرچمPy_TPFLAGS_HAVE_GCدر زیرنوع صفر باشد و فیلدهایtp_traverseوtp_clearدر زیرنوع وجود داشته باشند و مقدارNULLداشته باشند.
-
Py_TPFLAGS_DEFAULT¶
- قسمتی از ABI پایدار.
این نقاب بیتی تمام بیتهایی را در بر میگیرد که به وجود فیلدهای معین در شیء نوع و ساختارهای توسعهای آن مربوط میشوند. در حال حاضر، شامل بیتهای زیر است:
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION.ارثبری:
???
-
Py_TPFLAGS_METHOD_DESCRIPTOR¶
- قسمتی از ABI پایدار از نسخهی 3.8.
این بیت نشان میدهد که اشیاء مانند متدهای غیرمقید رفتار میکنند.
اگر این پرچم برای
type(meth)تنظیمشده باشد، آنگاه:عبارت
meth.__get__(obj, cls)(*args, **kwds)(وقتیobjبرابر None نیست) باید معادلmeth(obj, *args, **kwds)باشد.meth.__get__(None, cls)(*args, **kwds)باید معادلmeth(*args, **kwds)باشد.
این پرچم بهینهسازیای را برای فراخوانیهای متداول متد مانند
obj.meth()فعال میکند: از ایجاد یک شیء موقت «متد مقید» برایobj.methجلوگیری میکند.اضافه شده در نسخهی 3.8.
ارثبری:
این پرچم هرگز توسط نوعهایی که پرچم
Py_TPFLAGS_IMMUTABLETYPEروی آنها تنظیمنشده است، به ارث برده نمیشود. برای نوعهای توسعهای، این پرچم هر زمان کهtp_descr_getبه ارث برده شود، به ارث برده میشود.
-
Py_TPFLAGS_MANAGED_DICT¶
این بیت نشان میدهد که نمونههای کلاس دارای ویژگی
__dict__هستند و فضای دیکشنری توسط ماشین مجازی مدیریت میشود.اگر این پرچم تنظیم شده باشد،
Py_TPFLAGS_HAVE_GCنیز باید تنظیم شود.تابع پیمایش نوع باید
PyObject_VisitManagedDict()را فراخوانی کند و تابع پاکسازی آن بایدPyObject_ClearManagedDict()را فراخوانی کند.اضافه شده در نسخهی 3.12.
ارثبری:
این پرچم به ارث برده میشود، مگر آنکه فیلد
tp_dictoffsetدر یک ابرکلاس تنظیم شده باشد.
-
Py_TPFLAGS_MANAGED_WEAKREF¶
این بیت نشان میدهد که نمونههای کلاس باید قابل ارجاع ضعیف باشند.
اضافه شده در نسخهی 3.12.
ارثبری:
این پرچم به ارث برده میشود مگر اینکه فیلد
tp_weaklistoffsetدر یک ابرکلاس تنظیم شده باشد.
-
Py_TPFLAGS_ITEMS_AT_END¶
- قسمتی از ABI پایدار از نسخهی 3.12.
فقط با نوعهای دارای اندازه متغیر قابل استفاده است؛ یعنی نوعهایی که
tp_itemsizeغیر صفر دارند.نشان میدهد که بخش با اندازهی متغیرِ نمونهای از این نوع، در انتهای ناحیهی حافظهی نمونه و با آفست
Py_TYPE(obj)->tp_basicsizeقرار دارد (که ممکن است در هر زیرکلاس متفاوت باشد).هنگام تنظیم این پرچم، مطمئن شوید که همهی ابرکلاسها یا از این چیدمان حافظه استفاده میکنند یا اندازهی متغیر ندارند. پایتون این مورد را بررسی نمیکند.
اضافه شده در نسخهی 3.12.
ارثبری:
این پرچم به ارث برده میشود.
-
Py_TPFLAGS_LONG_SUBCLASS¶
-
Py_TPFLAGS_LIST_SUBCLASS¶
-
Py_TPFLAGS_TUPLE_SUBCLASS¶
-
Py_TPFLAGS_BYTES_SUBCLASS¶
-
Py_TPFLAGS_UNICODE_SUBCLASS¶
-
Py_TPFLAGS_DICT_SUBCLASS¶
-
Py_TPFLAGS_BASE_EXC_SUBCLASS¶
-
Py_TPFLAGS_TYPE_SUBCLASS¶
توابعی مانند
PyLong_Check()با یکی از این پرچمهاPyType_FastSubclass()را فراخوانی میکنند تا بهسرعت تعیین کنند که آیا یک نوع، زیرکلاس یک نوع توکار است یا نه؛ چنین بررسیهای خاصی سریعتر از یک بررسی عام مانندPyObject_IsInstance()هستند. نوعهای سفارشی که از نوعهای توکار ارثبری میکنند بایدtp_flagsخود را بهدرستی تنظیم کنند، وگرنه کدی که با چنین نوعهایی تعامل دارد، بسته به اینکه چه نوع بررسیای استفاده میشود، رفتار متفاوتی خواهد داشت.
-
Py_TPFLAGS_HAVE_FINALIZE¶
این بیت زمانی تنظیم میشود که جایگاه
tp_finalizeدر ساختار نوع موجود باشد.اضافه شده در نسخهی 3.4.
منسوخ شده از نسخهی 3.8: این پرچم دیگر ضروری نیست، زیرا مفسر فرض میکند که جایگاه
tp_finalizeهمیشه در ساختار نوع وجود دارد.
-
Py_TPFLAGS_HAVE_VECTORCALL¶
- قسمتی از ABI پایدار از نسخهی 3.12.
این بیت زمانی تنظیم میشود که کلاس پروتکل vectorcall را پیادهسازی کند. برای جزئیات به
tp_vectorcall_offsetمراجعه کنید.ارثبری:
این بیت در صورتی به ارث میرسد که
tp_callنیز به ارث برسد.اضافه شده در نسخهی 3.8: بهعنوان
_Py_TPFLAGS_HAVE_VECTORCALLتغییر یافته در نسخهی 3.9: به نام فعلی تغییر نام یافت، بدون زیرخط ابتدایی. نام آزمایشی قدیمی soft deprecated است.
تغییر یافته در نسخهی 3.12: این پرچم اکنون هنگامی که متد
__call__()کلاس مجدداً انتساب داده شود، از کلاس حذف میشود.این پرچم اکنون میتواند توسط کلاسهای تغییرپذیر به ارث برده شود.
-
Py_TPFLAGS_IMMUTABLETYPE¶
این بیت برای اشیاء نوعِ تغییرناپذیر تنظیم میشود: ویژگیهای نوع را نمیتوان تنظیم یا حذف کرد.
PyType_Ready()این پرچم را بهطور خودکار به انواع ایستا اعمال میکند.ارثبری:
این پرچم به ارث برده نمیشود.
اضافه شده در نسخهی 3.10.
-
Py_TPFLAGS_DISALLOW_INSTANTIATION¶
ایجاد نمونه از این نوع را ممنوع کنید:
tp_newرا برابر NULL قرار دهید و کلید__new__را در دیکشنری نوع ایجاد نکنید.پرچم باید پیش از ایجاد نوع تنظیم شود، نه پس از آن. برای مثال، باید پیش از فراخوانی
PyType_Ready()روی نوع تنظیم شود.اگر
tp_baseبرابر NULL یا&PyBaseObject_Typeباشد وtp_newبرابر NULL باشد، این پرچم بهطور خودکار بر روی نوعهای ایستا تنظیم میشود.ارثبری:
این پرچم به ارث برده نمیشود. با این حال، زیرکلاسها قابل نمونهسازی نخواهند بود مگر آنکه یک
tp_newغیر NULL ارائه کنند (که این کار تنها از طریق API زبان C امکانپذیر است).توجه
برای اینکه نمونهسازی مستقیم از یک کلاس ممنوع باشد اما نمونهسازی از زیرکلاسهای آن مجاز باشد (مثلاً برای یک کلاس پایه انتزاعی)، از این پرچم استفاده نکنید. در عوض، کاری کنید که
tp_newتنها برای زیرکلاسها موفق شود.اضافه شده در نسخهی 3.10.
-
Py_TPFLAGS_MAPPING¶
این بیت نشان میدهد که نمونههای کلاس، زمانی که بهعنوان موضوع بلوک
matchاستفاده میشوند، میتوانند با الگوهای نگاشت تطبیق یابند. این بیت هنگام ثبت یا زیرکلاسسازیcollections.abc.Mappingبهطور خودکار تنظیم میشود و هنگام ثبتcollections.abc.Sequenceاز تنظیم خارج میشود.توجه
Py_TPFLAGS_MAPPINGوPy_TPFLAGS_SEQUENCEانحصاری متقابل هستند؛ فعالسازی هر دو پرچم بهطور همزمان خطا است.ارثبری:
این پرچم به نوعهایی که از پیش
Py_TPFLAGS_SEQUENCEرا تنظیم نکردهاند، به ارث میرسد.همچنین ملاحظه نمائید
PEP 634 -- تطبیق الگوی ساختاری: مشخصات
اضافه شده در نسخهی 3.10.
-
Py_TPFLAGS_SEQUENCE¶
این بیت نشان میدهد که نمونههای کلاس ممکن است هنگامی که بهعنوان موضوع یک بلوک
matchاستفاده میشوند، با الگوهای دنباله تطبیق یابند. این بیت بهطور خودکار هنگام ثبت کردن یا زیرکلاسسازیcollections.abc.Sequenceتنظیم میشود و هنگام ثبت کردنcollections.abc.Mappingپاک میشود.توجه
Py_TPFLAGS_MAPPINGوPy_TPFLAGS_SEQUENCEانحصاری متقابل هستند؛ فعالسازی هر دو پرچم بهطور همزمان خطا است.ارثبری:
این پرچم توسط نوعهایی که از قبل
Py_TPFLAGS_MAPPINGرا تنظیم نکردهاند، به ارث میرسد.همچنین ملاحظه نمائید
PEP 634 -- تطبیق الگوی ساختاری: مشخصات
اضافه شده در نسخهی 3.10.
-
Py_TPFLAGS_VALID_VERSION_TAG¶
داخلی است. این پرچم را تنظیم یا از تنظیم خارج نکنید. برای نشان دادن اینکه کلاسی تغییر کرده است،
PyType_Modified()را فراخوانی کنیدهشدار
این پرچم در پروندههای سرآیند وجود دارد، اما استفاده نمیشود. این پرچم در نسخهای آینده از سیپایتون حذف خواهد شد
-
Py_TPFLAGS_HAVE_VERSION_TAG¶
این ماکرو هیچ کاری انجام نمیدهد. در گذشته، این نشان میداد که فیلد
tp_version_tagموجود و مقداردهی اولیه شده بود.منسوخسازی نرم <Soft deprecated> از نسخهی 3.13.
-
Py_TPFLAGS_INLINE_VALUES¶
این بیت نشان میدهد که نمونههای این نوع، آرایهی «مقادیر درونخطی» (inline values) — شامل ویژگیهای شیء — خواهند داشت که مستقیماً پس از انتهای شیء قرار میگیرد.
این امر نیازمند آن است که
Py_TPFLAGS_HAVE_GCتنظیم شده باشد.ارثبری:
این پرچم به ارث برده نمیشود.
اضافه شده در نسخهی 3.13.
-
Py_TPFLAGS_IS_ABSTRACT¶
این بیت نشان میدهد که این یک نوع انتزاعی است و بنابراین نمیتوان از آن نمونهسازی کرد.
ارثبری:
این پرچم به ارث برده نمیشود.
همچنین ملاحظه نمائید
-
Py_TPFLAGS_HAVE_STACKLESS_EXTENSION¶
داخلی. این پرچم را تنظیم یا از تنظیم خارج نکنید. در گذشته، این پرچم برای استفاده در Stackless Python رزروشده بود.
هشدار
این پرچم در پروندههای سرآیند وجود دارد، اما استفاده نمیشود. ممکن است در نسخههای آیندهی سیپایتون حذف شود.
-
Py_TPFLAGS_HEAPTYPE¶
-
const char *PyTypeObject.tp_doc¶
The corresponding slot ID
Py_tp_docis part of the ABI پایدار.یک اشارهگر اختیاری به رشتهی C پایانیافته با تهی که رشتهی مستند این شیء نوع را ارائه میدهد. این رشتهی مستند بهصورت ویژگی
__doc__روی نوع و نمونههای آن نوع در دسترس قرار میگیرد.ارثبری:
این فیلد توسط زیرنوعها به ارث برده نمیشود.
-
traverseproc PyTypeObject.tp_traverse¶
The corresponding slot ID
Py_tp_traverseis part of the ABI پایدار.اشارهگر اختیاری به تابع پیمایش برای زبالهروب. این تنها زمانی استفاده میشود که بیت پرچم
Py_TPFLAGS_HAVE_GCتنظیم شده باشد. امضا به این صورت است:int tp_traverse(PyObject *self, visitproc visit, void *arg);
اطلاعات بیشتری دربارهی طرحوارهی زبالهروبی پایتون را میتوانید در بخش پشتیبانی از زبالهروبی چرخهای بیابید.
اشارهگر
tp_traverseتوسط زبالهروب برای تشخیص چرخههای ارجاع استفاده میشود. یک پیادهسازی معمول از تابعtp_traverseبهسادگیPy_VISIT()را روی هر یک از اعضای نمونه که شیءهای پایتونی هستند و نمونه مالک آنهاست، فراخوانی میکند. برای مثال، این تابعlocal_traverse()از ماژول توسعهای_threadاست:static int local_traverse(PyObject *op, visitproc visit, void *arg) { localobject *self = (localobject *) op; Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dict); return 0; }
توجه داشته باشید که
Py_VISIT()تنها بر روی اعضایی فراخوانی میشود که میتوانند در چرخههای ارجاع شرکت کنند. اگرچه عضوself->keyنیز وجود دارد، اما این عضو تنها میتواندNULLیا یک رشتهی پایتون باشد و بنابراین نمیتواند بخشی از یک چرخهی ارجاع باشد.از سوی دیگر، حتی اگر بدانید که یک عضو هرگز نمیتواند بخشی از یک چرخه باشد، ممکن است به عنوان کمکی برای اشکالزدایی، به هر حال بخواهید آن را بازدید کنید تا تابع
get_referents()ماژولgcآن را در بر بگیرد.نوعهای هیپ (
Py_TPFLAGS_HEAPTYPE) باید نوع خود را با کد زیر بازدید کنند:Py_VISIT(Py_TYPE(self));
این تنها از پایتون 3.9 به بعد مورد نیاز است. برای پشتیبانی از پایتون 3.8 و نسخههای قدیمیتر، این سطر باید شرطی باشد:
#if PY_VERSION_HEX >= 0x03090000 Py_VISIT(Py_TYPE(self)); #endif
اگر بیت
Py_TPFLAGS_MANAGED_DICTدر فیلدtp_flagsتنظیم شده باشد، تابع پیمایش بایدPyObject_VisitManagedDict()را به این شکل فراخوانی کند:PyObject_VisitManagedDict((PyObject*)self, visit, arg);
هشدار
هنگام پیادهسازی
tp_traverse، فقط اعضایی که نمونه مالک آنهاست (با داشتن ارجاعهای قوی به آنها) باید بازدید شوند. برای مثال، اگر یک شیء از طریق جایگاهtp_weaklistاز ارجاعهای ضعیف پشتیبانی کند، اشارهگری که فهرست پیوندی را پشتیبانی میکند (چیزی که tp_weaklist به آن اشاره میکند) نباید بازدید شود، زیرا نمونه بهطور مستقیم مالک ارجاعهای ضعیف به خود نیست (فهرست ارجاعهای ضعیف وجود دارد تا از سازوکار ارجاع ضعیف پشتیبانی کند، اما نمونه ارجاع قوی به عناصر درون آن ندارد، زیرا اجازه داده میشود آنها حتی اگر نمونه هنوز زنده باشد حذف شوند).هشدار
تابع پیمایش نباید هیچ اثر جانبی داشته باشد. این تابع نباید شمارش ارجاع هیچ شیء پایتونی را تغییر دهد و نه هیچ شیء پایتونی را ایجاد یا نابود کند.
توجه داشته باشید که
Py_VISIT()نیازمند آن است که پارامترهای visit و arg درlocal_traverse()دقیقاً همین نامها را داشته باشند؛ آنها را با هر نامی نامگذاری نکنید.نمونههای نوعهای تخصیصیافته در هیپ ارجاعی به نوع خود نگه میدارند. بنابراین تابع پیمایش آنها باید یا
Py_TYPE(self)را بازدید کند، یا این مسئولیت را با فراخوانیtp_traverseیک نوع تخصیصیافته در هیپ دیگر (مانند یک ابرکلاس تخصیصیافته در هیپ) واگذار کند. اگر چنین نکنند، ممکن است شیء نوع زبالهروبی نشود.توجه
تابع
tp_traverseرا میتوان از هر نخی فراخوانی کرد.تغییر یافته در نسخهی 3.9: انتظار میرود که نوعهای تخصیصیافته در هیپ،
Py_TYPE(self)را درtp_traverseبازدید کنند. در نسخههای پیشین پایتون، به دلیل باگ 40217، انجام این کار ممکن است در زیرکلاسها به فروپاشی منجر شود.ارثبری:
گروه:
Py_TPFLAGS_HAVE_GC،tp_traverse،tp_clearاین فیلد به همراه
tp_clearو بیت پرچمPy_TPFLAGS_HAVE_GCتوسط زیرنوعها به ارث برده میشود: بیت پرچم،tp_traverseوtp_clearهمگی در صورتی از نوع پایه به ارث برده میشوند که هر سه در زیرنوع صفر باشند.
-
inquiry PyTypeObject.tp_clear¶
The corresponding slot ID
Py_tp_clearis part of the ABI پایدار.اشارهگر اختیاری به تابع پاکسازی. امضا به این صورت است:
int tp_clear(PyObject *);
هدف از این تابع، شکستن چرخههای ارجاعی است که یک cyclic isolate ایجاد میکنند تا اشیاء بتوانند بهطور ایمن نابود شوند. شیء پاکسازیشده شیئی است که بهطور جزئی نابود شده است؛ این شیء موظف نیست ناوردهای طراحیای را که در استفادهی عادی برقرارند رعایت کند.
tp_clearنیازی به حذف ارجاعات به اشیایی ندارد که نمیتوانند در چرخههای ارجاع شرکت کنند، مانند رشتههای پایتون یا اعداد صحیح پایتون. با این حال، ممکن است پاککردن همهی ارجاعات و نوشتن تابعtp_deallocنوع بهگونهای کهtp_clearرا فراخوانی کند، برای جلوگیری از تکرار کد مناسب باشد. (مراقب باشید که ممکن استtp_clearقبلاً فراخوانی شده باشد. فراخوانی توابع همتوان مانندPy_CLEAR()را ترجیح دهید.)هرگونه پاکسازی غیرساده باید بهجای
tp_clearدرtp_finalizeانجام شود.توجه
اگر
tp_clearنتواند یک چرخه ارجاع را بشکند، ممکن است اشیاء درون cyclic isolate بهطور نامحدود غیرقابل جمعآوری باقی بمانند («نشت»).gc.garbageرا ببینید.توجه
ارجاعشوندهها (referents) — مستقیم و غیرمستقیم — ممکن است از پیش پاکسازی شده باشند؛ تضمینی نیست که در وضعیتی سازگار باشند.
توجه
تابع
tp_clearرا میتوان از هر نخی فراخوانی کرد.توجه
تضمین نمیشود که یک شیء پیش از فراخوانی مخرب آن (
tp_dealloc) بهطور خودکار پاکسازی شود.این تابع به روشهای زیر با مخرب (
tp_dealloc) تفاوت دارد:هدف از پاکسازی یک شیء، حذف ارجاعها به اشیاء دیگری است که ممکن است در چرخه ارجاع شرکت کنند. از سوی دیگر، هدف مخرب ابرمجموعهای از آن است: مخرب باید همه منابعی را که در اختیار دارد آزاد کند، از جمله ارجاعها به اشیائی که نمیتوانند در چرخه ارجاع شرکت کنند (مانند اعداد صحیح) و همچنین حافظهی خودِ شیء (با فراخوانی
tp_free).وقتی
tp_clearفراخوانی میشود، ممکن است اشیاء دیگر همچنان ارجاعهایی به شیءِ در حال پاکشدن داشته باشند. به همین دلیل،tp_clearنباید حافظهی خودِ شیء را آزاد کند (tp_free). از سوی دیگر، مخرب تنها زمانی فراخوانی میشود که هیچ ارجاعی (قوی) وجود نداشته باشد، و از این رو، باید خودِ شیء را با آزاد کردن آن بهطور ایمن نابود کند.tp_clearممکن است هرگز بهطور خودکار فراخوانی نشود. از سوی دیگر، مخرب یک شیء، مدتی پس از دسترسناپذیر شدن شیء بهطور خودکار فراخوانی میشود (یعنی، یا هیچ ارجاعی به شیء وجود ندارد یا شیء عضوی از یک cyclic isolate است).
هیچ تضمینی دربارهی اینکه پایتون چه زمانی، آیا اصلاً، یا هر چند وقت یکبار یک شیء را بهطور خودکار پاک میکند ارائه نمیشود، مگر در موارد زیر:
پایتون بهطور خودکار شیئی را پاک نمیکند که دسترسیپذیر باشد؛ یعنی ارجاعی به آن وجود داشته باشد و عضوی از cyclic isolate نباشد.
اگر یک شیء بهطور خودکار نهاییسازی نشده باشد، پایتون آن را بهطور خودکار پاک نمیکند (به
tp_finalizeمراجعه کنید). (اگر نهاییساز شیء را احیا کرده باشد، ممکن است شیء پیش از پاک شدن، دوباره بهطور خودکار نهاییسازی شود یا نشود.)اگر شیئی عضوی از یک cyclic isolate باشد، پایتون در صورتی که عضوی از cyclic isolate هنوز بهطور خودکار نهاییسازی نشده باشد، آن را بهطور خودکار پاک نمیکند (
tp_finalize).پایتون تا پس از بازگشت هرگونه فراخوانی خودکار تابع
tp_clearیک شیء، آن را نابود نمیکند. این تضمین میکند که عمل شکستن چرخه ارجاع، اشارهگرselfرا در حالی کهtp_clearهنوز در حال اجراست، نامعتبر نکند.پایتون بهطور خودکار
tp_clearرا چندین بار بهطور همزمان فراخوانی نمیکند.
سیپایتون در حال حاضر اشیاء را تنها زمانی بهطور خودکار پاکسازی میکند که برای شکستن چرخههای ارجاع در یک cyclic isolate نیاز باشد، اما نسخههای آینده ممکن است اشیاء را بهطور منظم پیش از تخریبشان پاکسازی کنند.
در مجموع، همهی توابع
tp_clearدر سیستم باید با هم تمام چرخههای ارجاع را بشکنند. این موضوع ظریف است، و در صورت وجود هرگونه شک، یک تابعtp_clearارائه دهید. برای مثال، نوع تاپل تابعtp_clearرا پیادهسازی نمیکند، زیرا میتوان اثبات کرد که هیچ چرخهی ارجاعی نمیتواند بهطور کامل از تاپلها تشکیل شود. بنابراین توابعtp_clearانواع دیگر مسئول شکستن هر چرخهای هستند که شامل یک تاپل باشد. این موضوع در نگاه اول آشکار نیست، و بهندرت دلیل خوبی برای اجتناب از پیادهسازیtp_clearوجود دارد.پیادهسازیهای
tp_clearباید ارجاعهای نمونه به آنهایی از اعضایش که ممکن است اشیاء پایتون باشند را رها کنند و اشارهگرهایش به آن اعضا را برابرNULLقرار دهند، همانند مثال زیر:static int local_clear(PyObject *op) { localobject *self = (localobject *) op; Py_CLEAR(self->key); Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dict); return 0; }
باید از ماکروی
Py_CLEAR()استفاده کرد، زیرا پاکسازی ارجاعها امری ظریف است: ارجاع به شیء درونگرفته نباید (از طریقPy_DECREF()) آزاد شود، مگر پس از آنکه اشارهگر به شیء درونگرفته برابرNULLقرار گرفته باشد. دلیل این امر آن است که آزاد کردن ارجاع ممکن است باعث شود شیء درونگرفته به زباله تبدیل شود و زنجیرهای از فعالیت بازیافت را فعال کند که ممکن است شامل فراخوانی کد دلخواه پایتون باشد (به دلیل نهاییسازها یا کالبکهای weakref مرتبط با شیء درونگرفته). اگر چنین کدی بتواند دوباره به self ارجاع کند، مهم است که اشارهگر به شیء درونگرفته در آن لحظه برابرNULLباشد، تا self بداند که شیء درونگرفته دیگر قابل استفاده نیست. ماکرویPy_CLEAR()عملیاتها را به ترتیبی ایمن انجام میدهد.اگر بیت
Py_TPFLAGS_MANAGED_DICTدر فیلدtp_flagsتنظیم شده باشد، تابع پاکسازی بایدPyObject_ClearManagedDict()را به این شکل فراخوانی کند:PyObject_ClearManagedDict((PyObject*)self);
اطلاعات بیشتری دربارهی طرحوارهی زبالهروبی پایتون را میتوانید در بخش پشتیبانی از زبالهروبی چرخهای بیابید.
ارثبری:
گروه:
Py_TPFLAGS_HAVE_GC،tp_traverse،tp_clearاین فیلد به همراه
tp_traverseو بیت پرچمPy_TPFLAGS_HAVE_GCتوسط زیرنوعها به ارث برده میشود: اگر بیت پرچم،tp_traverseوtp_clearدر زیرنوع همگی صفر باشند، از نوع پایه به ارث برده میشوند.همچنین ملاحظه نمائید
چرخهی حیات شیء را برای جزئیات دربارهی نحوهی ارتباط این جایگاه با جایگاههای دیگر ببینید.
-
richcmpfunc PyTypeObject.tp_richcompare¶
The corresponding slot ID
Py_tp_richcompareis part of the ABI پایدار.یک اشارهگر اختیاری به تابع مقایسهی غنی (rich comparison)، که امضای آن به صورت زیر است:
PyObject *tp_richcompare(PyObject *self, PyObject *other, int op);
تضمین میشود که پارامتر اول، نمونهای از نوعی باشد که توسط
PyTypeObjectتعریف شده است.تابع باید نتیجهی مقایسه را برگرداند (معمولاً
Py_TrueیاPy_False). اگر مقایسه تعریفنشده باشد، بایدPy_NotImplementedرا برگرداند، و اگر خطای دیگری رخ داده باشد، بایدNULLبرگرداند و یک وضعیت استثنا را تنظیم کند.ثابتهای زیر برای استفاده بهعنوان آرگومان سومِ
tp_richcompareوPyObject_RichCompare()تعریف شدهاند:ثابت
مقایسه
-
Py_LT¶
<-
Py_LE¶
<=-
Py_EQ¶
==-
Py_NE¶
!=-
Py_GT¶
>-
Py_GE¶
>=ماکروی زیر برای آسانسازی نوشتن توابع مقایسهی غنی (rich comparison) تعریفشده است:
-
Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, op)¶
بسته به نتیجهی مقایسه،
Py_TrueیاPy_Falseرا از تابع برگردانید. VAL_A و VAL_B باید با عملگرهای مقایسهی C قابل مرتبسازی باشند (برای مثال، ممکن است اعداد صحیح یا ممیز شناور در C باشند). آرگومان سوم، عملیات درخواستی را مشخص میکند، همانگونه که برایPyObject_RichCompare()است.مقدار بازگشتی یک ارجاع قوی جدید است.
در صورت خطا، یک استثنا تنظیم میکند و
NULLرا از تابع برمیگرداند.اضافه شده در نسخهی 3.7.
ارثبری:
گروه:
tp_hash،tp_richcompareاین فیلد به همراه
tp_hashتوسط زیرنوعها به ارث برده میشود: زیرنوع زمانیtp_richcompareوtp_hashرا به ارث میبرد که هر دوtp_richcompareوtp_hashآنNULLباشند.پیشفرض:
PyBaseObject_Typeیک پیادهسازی ازtp_richcompareفراهم میکند که ممکن است به ارث برده شود. با این حال، اگر تنهاtp_hashتعریف شده باشد، حتی تابع بهارثرسیده هم استفاده نمیشود و نمونههای این نوع نمیتوانند در هیچ مقایسهای شرکت کنند.-
Py_LT¶
-
Py_ssize_t PyTypeObject.tp_weaklistoffset¶
هرچند این فیلد همچنان پشتیبانی میشود، تا جای ممکن باید به جای آن از
Py_TPFLAGS_MANAGED_WEAKREFاستفاده شود.اگر نمونههای این نوع قابل ارجاع ضعیف باشند، این فیلد بزرگتر از صفر است و آفست سر فهرست ارجاعهای ضعیف در ساختار نمونه را در بر میگیرد (با نادیده گرفتن سرآیند GC، در صورت وجود)؛ این آفست توسط
PyObject_ClearWeakRefs()و توابعPyWeakref_*استفاده میشود. ساختار نمونه باید شامل یک فیلد از نوع PyObject* باشد که باNULLمقداردهی اولیه میشود.این فیلد را با
tp_weaklistاشتباه نگیرید؛ آن، سر فهرست ارجاعهای ضعیف به خودِ شیء نوع است.تنظیم کردن هم بیت
Py_TPFLAGS_MANAGED_WEAKREFو همtp_weaklistoffsetخطا است.ارثبری:
این فیلد توسط زیرنوعها به ارث برده میشود، اما به قواعد فهرستشده در پایین مراجعه کنید. یک زیرنوع میتواند این آفست را بازنویسی کند؛ این بدان معناست که زیرنوع از سر فهرست ارجاعهای ضعیف متفاوتی نسبت به نوع پایه استفاده میکند. از آنجا که سر فهرست همیشه از طریق
tp_weaklistoffsetیافت میشود، این نباید مشکلی ایجاد کند.پیشفرض:
اگر بیت
Py_TPFLAGS_MANAGED_WEAKREFدر فیلدtp_flagsتنظیم شده باشد، آنگاهtp_weaklistoffsetبه یک مقدار منفی تنظیم خواهد شد تا نشان دهد که استفاده از این فیلد ناامن است.
-
getiterfunc PyTypeObject.tp_iter¶
The corresponding slot ID
Py_tp_iteris part of the ABI پایدار.یک اشارهگر اختیاری به تابعی که یک iterator برای شیء برمیگرداند. حضور آن معمولاً نشان میدهد که نمونههای این نوع iterable هستند (هرچند دنبالهها ممکن است بدون این تابع پیمایشپذیر باشند).
این تابع همان امضای
PyObject_GetIter()را دارد:PyObject *tp_iter(PyObject *self);
ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
-
iternextfunc PyTypeObject.tp_iternext¶
The corresponding slot ID
Py_tp_iternextis part of the ABI پایدار.اشارهگر اختیاری به تابعی که آیتم بعدی در یک پیمایشگر را برمیگرداند. امضا به این صورت است:
PyObject *tp_iternext(PyObject *self);
When the iterator is exhausted, the
tp_iternextfunction must returnNULL; aStopIterationexception may or may not be set. When another error occurs, it must returnNULLtoo. The presence oftp_iternextsignals that the instances of this type are iterators.نوعهای پیمایشگر باید تابع
tp_iterرا نیز تعریف کنند، و این تابع باید خودِ نمونهی پیمایشگر را برگرداند (نه یک نمونهی پیمایشگر جدید).این تابع همان امضای
PyIter_Next()را دارد.ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
-
struct PyMethodDef *PyTypeObject.tp_methods¶
The corresponding slot ID
Py_tp_methodsis part of the ABI پایدار.یک اشارهگر اختیاری به آرایهی ایستای پایانیافته با
NULLاز ساختارهایPyMethodDefکه متدهای معمولی این نوع را اعلام میکند.برای هر ورودی در آرایه، ورودیای به دیکشنری نوع اضافه میشود (به
tp_dictدر ادامه ببینید) که حاوی یک توصیفگر متد است.ارثبری:
این فیلد توسط زیرنوعها به ارث برده نمیشود (متدها از طریق سازوکاری متفاوت به ارث برده میشوند).
-
struct PyMemberDef *PyTypeObject.tp_members¶
The corresponding slot ID
Py_tp_membersis part of the ABI پایدار.یک اشارهگر اختیاری به آرایهی ایستای مختوم به
NULLاز ساختارهایPyMemberDef، که اعضای دادهی عادی (فیلدها یا جایگاهها) از نمونههای این نوع را اعلان میکند.برای هر ورودی در آرایه، ورودیای به دیکشنری نوع افزوده میشود (به
tp_dictدر ادامه مراجعه کنید) که حاوی یک توصیفگر عضو است.ارثبری:
این فیلد به زیرنوعها به ارث نمیرسد (اعضا از طریق سازوکاری متفاوت به ارث میرسند).
-
struct PyGetSetDef *PyTypeObject.tp_getset¶
The corresponding slot ID
Py_tp_getsetis part of the ABI پایدار.یک اشارهگر اختیاری به یک آرایهی ایستای پایانیافته با
NULLاز ساختارهایPyGetSetDefکه ویژگیهای محاسبهشدهی نمونههای این نوع را اعلان میکند.برای هر ورودی در آرایه، یک ورودی به دیکشنری نوع اضافه میشود (به
tp_dictدر ادامه مراجعه کنید) که شامل یک توصیفگر getset است.ارثبری:
این فیلد به زیرنوعها به ارث نمیرسد (ویژگیهای محاسبهشده از طریق سازوکاری متفاوت به ارث میرسند).
-
PyTypeObject *PyTypeObject.tp_base¶
The corresponding slot ID
Py_tp_baseis part of the ABI پایدار.اشارهگری اختیاری به یک نوع پایه که ویژگیهای نوع از آن به ارث میرسند. در این سطح، تنها ارثبری تکی پشتیبانی میشود؛ ارثبری چندگانه نیازمند ایجاد یک شیء نوع بهصورت پویا با فراخوانی فرانوع است.
توجه
مقداردهی اولیه جایگاه از قواعد مقداردهی اولیه متغیرهای سراسری پیروی میکند. C99 الزام میکند که مقداردهندههای اولیه «ثابتهای آدرس» باشند. نشانگرهای تابع (function designator) مانند
PyType_GenericNew()که بهطور ضمنی به اشارهگر تبدیل میشوند، ثابتهای آدرس معتبر در C99 هستند.با این حال، الزامی نیست که عملگر یکعملوندی '&' اعمالشده بر متغیری غیرایستا مانند
PyBaseObject_Typeثابت آدرس (address constant) تولید کند. کامپایلرها ممکن است از این پشتیبانی کنند (gcc پشتیبانی میکند)، اما MSVC پشتیبانی نمیکند. هر دو کامپایلر در این رفتار خاص کاملاً منطبق با استاندارد هستند.در نتیجه،
tp_baseباید در تابع init ماژول توسعهای تنظیم شود.ارثبری:
این فیلد به زیرنوعها به ارث نمیرسد (بدیهی است).
پیشفرض:
مقدار پیشفرض این فیلد
&PyBaseObject_Typeاست (که برای برنامهنویسان پایتون بهعنوان نوعobjectشناخته میشود).
-
PyObject *PyTypeObject.tp_dict¶
دیکشنری نوع توسط
PyType_Ready()در اینجا ذخیره میشود.این فیلد بهطور معمول باید پیش از فراخوانی PyType_Ready به
NULLمقداردهی اولیه شود؛ همچنین میتواند به یک دیکشنری حاوی ویژگیهای اولیه برای نوع مقداردهی اولیه شود. پس از آنکهPyType_Ready()نوع را مقداردهی اولیه کرد، ویژگیهای اضافی برای نوع تنها در صورتی میتوانند به این دیکشنری افزوده شوند که با عملیاتهای سربارگذاریشده (مانند__add__()) تناظر نداشته باشند. پس از پایان مقداردهی اولیه نوع، این فیلد باید فقطخواندنی در نظر گرفته شود.برخی نوعها ممکن است دیکشنری خود را در این جایگاه ذخیره نکنند. برای بازیابی دیکشنری یک نوع دلخواه، از
PyType_GetDict()استفاده کنید.تغییر یافته در نسخهی 3.12: جزئیات داخلی: برای نوعهای توکار ایستا، این همیشه
NULLاست. در عوض، دیکشنری چنین نوعهایی درPyInterpreterStateذخیره میشود. برای دریافت دیکشنری یک نوع دلخواه ازPyType_GetDict()استفاده کنید.ارثبری:
این فیلد توسط زیرنوعها به ارث برده نمیشود (هرچند ویژگیهای تعریفشده در آن از طریق سازوکاری متفاوت به ارث برده میشوند).
پیشفرض:
اگر این فیلد
NULLباشد،PyType_Ready()یک دیکشنری جدید به آن انتساب میدهد.هشدار
استفاده از
PyDict_SetItem()بر رویtp_dictیا تغییر دادن آن به روشهای دیگر با C-API دیکشنری ایمن نیست.
-
descrgetfunc PyTypeObject.tp_descr_get¶
The corresponding slot ID
Py_tp_descr_getis part of the ABI پایدار.اشارهگری اختیاری به تابع «دریافت توصیفگر» (descriptor get).
امضای تابع به این صورت است:
PyObject * tp_descr_get(PyObject *self, PyObject *obj, PyObject *type);
ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
-
descrsetfunc PyTypeObject.tp_descr_set¶
The corresponding slot ID
Py_tp_descr_setis part of the ABI پایدار.اشارهگر اختیاری به تابعی برای تنظیم و حذف مقدار یک توصیفگر.
امضای تابع به این صورت است:
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
آرگومان value برای حذف مقدار، بر روی
NULLتنظیم میشود.ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
-
Py_ssize_t PyTypeObject.tp_dictoffset¶
با اینکه این فیلد هنوز پشتیبانی میشود، در صورت امکان باید به جای آن از
Py_TPFLAGS_MANAGED_DICTاستفاده شود.اگر نمونههای این نوع دیکشنری حاوی متغیرهای نمونه داشته باشند، این فیلد ناصفر است و آفست دیکشنری متغیرهای نمونه در نمونههای نوع را در بر میگیرد؛ این آفست توسط
PyObject_GenericGetAttr()استفاده میشود.این فیلد را با
tp_dictاشتباه نگیرید؛ آن، دیکشنریِ مربوط به ویژگیهای خودِ شیء نوع است.این مقدار، آفست دیکشنری را از ابتدای ساختار نمونه مشخص میکند.
tp_dictoffsetباید فقطنوشتنی در نظر گرفته شود. برای بهدستآوردن اشارهگر به دیکشنری،PyObject_GenericGetDict()را فراخوانی کنید. فراخوانیPyObject_GenericGetDict()ممکن است نیاز به تخصیص حافظه برای دیکشنری داشته باشد، بنابراین ممکن است هنگام دسترسی به یک ویژگی روی شیء، فراخوانیPyObject_GetAttr()کارآمدتر باشد.تنظیم هر دو بیت
Py_TPFLAGS_MANAGED_DICTوtp_dictoffsetخطا است.ارثبری:
این فیلد توسط زیرنوعها به ارث برده میشود. زیرنوع نباید این آفست را بازنویسی کند؛ انجام این کار میتواند ناامن باشد، اگر کد C تلاش کند به دیکشنری در آفست قبلی دسترسی پیدا کند. برای پشتیبانی صحیح از ارثبری، از
Py_TPFLAGS_MANAGED_DICTاستفاده کنید.پیشفرض:
این جایگاه مقدار پیشفرضی ندارد. برای نوعهای ایستا، اگر فیلد
NULLباشد، برای نمونهها هیچ__dict__ایجاد نمیشود.اگر بیت
Py_TPFLAGS_MANAGED_DICTدر فیلدtp_flagsتنظیم شده باشد، آنگاهtp_dictoffsetبرابر-1تنظیم خواهد شد تا نشان دهد که استفاده از این فیلد ناامن است.
-
initproc PyTypeObject.tp_init¶
The corresponding slot ID
Py_tp_initis part of the ABI پایدار.اشارهگری اختیاری به تابع مقداردهی اولیهی نمونه.
این تابع معادل متد
__init__()کلاسها است. مانند__init__()، میتوان نمونهای را بدون فراخوانی__init__()ایجاد کرد، و میتوان نمونهای را با فراخوانی دوباره متد__init__()آن مقداردهی مجدد کرد.امضای تابع به این صورت است:
int tp_init(PyObject *self, PyObject *args, PyObject *kwds);
آرگومان self نمونهای است که باید مقداردهی اولیه شود؛ آرگومانهای args و kwds آرگومانهای جایگاهی و کلیدواژهای فراخوانی
__init__()را بازنمایی میکنند.تابع
tp_init، در صورتی کهNULLنباشد، هنگامی فراخوانی میشود که نمونهای بهطور معمول با فراخوانی نوع آن ایجاد شود، پس از آنکه تابعtp_newآن نوع، نمونهای از آن نوع را برگردانده باشد. اگر تابعtp_newنمونهای از نوع دیگری را برگرداند که زیرنوع نوع اصلی نیست، هیچ تابعtp_initفراخوانی نمیشود؛ اگرtp_newنمونهای از یک زیرنوع از نوع اصلی را برگرداند،tp_initآن زیرنوع فراخوانی میشود.در صورت موفقیت
0و در صورت خطا-1را برمیگرداند و استثنایی تنظیم میکند.ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
پیشفرض:
برای نوعهای ایستا این فیلد مقدار پیشفرض ندارد.
-
allocfunc PyTypeObject.tp_alloc¶
The corresponding slot ID
Py_tp_allocis part of the ABI پایدار.اشارهگر اختیاری به یک تابع تخصیص نمونه.
امضای تابع به این صورت است:
PyObject *tp_alloc(PyTypeObject *self, Py_ssize_t nitems);
ارثبری:
زیرنوعهای ایستا این جایگاه را به ارث میبرند که در صورت ارثبری از
object،PyType_GenericAlloc()خواهد بود.زیرنوعهای هیپ این جایگاه را به ارث نمیبرند.
پیشفرض:
برای زیرنوعهای هیپ، این فیلد همیشه روی
PyType_GenericAlloc()تنظیم میشود.برای زیرنوعهای ایستا، این جایگاه به ارث میرسد (بالا را ببینید).
-
newfunc PyTypeObject.tp_new¶
The corresponding slot ID
Py_tp_newis part of the ABI پایدار.اشارهگر اختیاری به یک تابع ایجاد نمونه.
امضای تابع به این صورت است:
PyObject *tp_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
آرگومان subtype نوع شیئی است که در حال ایجاد شدن است؛ آرگومانهای args و kwds آرگومانهای جایگاهی و کلیدواژهای فراخوانی آن نوع را نشان میدهند. توجه داشته باشید که subtype لازم نیست با نوعی که تابع
tp_newآن فراخوانی میشود برابر باشد؛ میتواند زیرنوعی از آن نوع باشد (اما نه نوعی نامرتبط).تابع
tp_newباید برای تخصیص فضای شیء،subtype->tp_alloc(subtype, nitems)را فراخوانی کند و سپس تنها به اندازهای که کاملاً ضروری است، مقداردهی اولیهی بیشتری انجام دهد. مقداردهی اولیهای که میتوان آن را با اطمینان نادیده گرفت یا تکرار کرد، باید در هندلرtp_initقرار گیرد. یک قاعده سرانگشتی خوب این است که برای نوعهای تغییرناپذیر، تمام مقداردهی اولیه باید درtp_newانجام شود، در حالی که برای نوعهای تغییرپذیر، بیشترِ مقداردهی اولیه باید بهtp_initموکول شود.برای جلوگیری از ایجاد نمونههای این نوع در پایتون، پرچم
Py_TPFLAGS_DISALLOW_INSTANTIATIONرا تنظیم کنید.ارثبری:
این فیلد توسط زیرنوعها به ارث برده میشود، بهجز اینکه نوعهای ایستا که
tp_baseآنهاNULLیا&PyBaseObject_Typeاست، این فیلد را به ارث نمیبرند.پیشفرض:
برای نوعهای ایستا این فیلد مقدار پیشفرضی ندارد. این بدان معناست که اگر جایگاه بهصورت
NULLتعریف شود، نمیتوان نوع را برای ایجاد نمونههای جدید فراخوانی کرد؛ احتمالاً راه دیگری برای ایجاد نمونهها وجود دارد، مانند یک تابع کارخانهای.
-
freefunc PyTypeObject.tp_free¶
The corresponding slot ID
Py_tp_freeis part of the ABI پایدار.اشارهگری اختیاری به تابع تخصیصگشایی نمونه. امضای آن چنین است:
void tp_free(void *self);
این تابع باید حافظهی تخصیصیافته توسط
tp_allocرا آزاد کند.ارثبری:
زیرنوعهای ایستا این جایگاه را به ارث میبرند؛ این جایگاه در صورتی که از
objectبه ارث برده شود،PyObject_Free()خواهد بود. استثنا: اگر نوع از زبالهروبی پشتیبانی کند (یعنی پرچمPy_TPFLAGS_HAVE_GCدرtp_flagsتنظیم شده باشد) و قرار باشدPyObject_Free()را به ارث ببرد، آنگاه این جایگاه به ارث برده نمیشود، بلکه پیشفرض آنPyObject_GC_Del()است.زیرنوعهای هیپ این جایگاه را به ارث نمیبرند.
پیشفرض:
برای زیرنوعهای هیپ، این جایگاه بهطور پیشفرض به یک آزادساز حافظه مناسب برای مطابقت با
PyType_GenericAlloc()و مقدار پرچمPy_TPFLAGS_HAVE_GCتنظیم میشود.برای زیرنوعهای ایستا، این جایگاه به ارث میرسد (بالا را ببینید).
-
inquiry PyTypeObject.tp_is_gc¶
The corresponding slot ID
Py_tp_is_gcis part of the ABI پایدار.اشارهگر اختیاری به تابعی که توسط زبالهروب فراخوانی میشود.
زبالهروب نیاز دارد بداند که آیا یک شیء خاص قابل جمعآوری است یا خیر. در حالت عادی، نگاه کردن به فیلد
tp_flagsنوع شیء و بررسی بیت پرچمPy_TPFLAGS_HAVE_GCکافی است. اما برخی نوعها ترکیبی از نمونههای تخصیصیافته بهصورت ایستا و پویا دارند و نمونههای تخصیصیافته بهصورت ایستا قابل جمعآوری نیستند. چنین نوعهایی باید این تابع را تعریف کنند؛ این تابع باید برای یک نمونهی قابل جمعآوری1و برای یک نمونهی غیرقابل جمعآوری0بازگرداند. امضا به این صورت است:int tp_is_gc(PyObject *self);
(تنها نمونه از این مورد، خودِ نوعها هستند. فراکلاس،
PyType_Type، این تابع را برای تمایز بین نوعهای تخصیصیافته بهصورت ایستا و نوعهای تخصیصیافته بهصورت پویا تعریف میکند.)ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
پیشفرض:
این جایگاه مقدار پیشفرض ندارد. اگر این فیلد
NULLباشد،Py_TPFLAGS_HAVE_GCبهعنوان معادل عملکردی استفاده میشود.
-
PyObject *PyTypeObject.tp_bases¶
The corresponding slot ID
Py_tp_basesis part of the ABI پایدار.تاپل نوعهای پایه.
این فیلد باید روی
NULLتنظیم شود و بهعنوان فقطخواندنی در نظر گرفته شود. پایتون آن را زمانی که نوعمقداردهی اولیهشود، پر میکند.برای کلاسهای ایجادشده بهصورت پویا، میتوان بهجای آرگومان bases در
PyType_FromSpecWithBases()ازجایگاهPy_tp_basesاستفاده کرد. شکل آرگومان ترجیح داده میشود.هشدار
وراثت چندگانه برای نوعهای تعریفشده بهصورت ایستا بهخوبی کار نمیکند. اگر
tp_basesرا روی یک تاپل تنظیم کنید، پایتون خطایی ایجاد نمیکند، اما برخی جایگاهها فقط از اولین پایه به ارث برده میشوند.ارثبری:
این فیلد به ارث برده نمیشود.
-
PyObject *PyTypeObject.tp_mro¶
تاپلی حاوی مجموعهی گسترشیافتهی نوعهای پایه به ترتیب حل متد، که با خودِ نوع آغاز میشود و با
objectپایان مییابد.این فیلد باید روی
NULLتنظیم شود و بهعنوان فقطخواندنی در نظر گرفته شود. پایتون آن را زمانی که نوعمقداردهی اولیهشود، پر میکند.ارثبری:
این فیلد به ارث برده نمیشود؛ توسط
PyType_Ready()از نو محاسبه میشود.
-
PyObject *PyTypeObject.tp_cache¶
استفاده نمیشود. فقط برای استفاده داخلی است.
ارثبری:
این فیلد به ارث برده نمیشود.
-
void *PyTypeObject.tp_subclasses¶
مجموعهای از زیرکلاسها. فقط برای استفاده داخلی. ممکن است اشارهگر نامعتبر باشد.
برای بهدستآوردن فهرستی از زیرکلاسها، متد پایتونی
__subclasses__()را فراخوانی کنید.تغییر یافته در نسخهی 3.12: برای برخی از نوعها، این فیلد شامل یک PyObject* معتبر نیست. نوع این فیلد به void* تغییر یافت تا این موضوع را نشان دهد.
ارثبری:
این فیلد به ارث برده نمیشود.
-
PyObject *PyTypeObject.tp_weaklist¶
سر فهرست ارجاعهای ضعیف، برای ارجاعهای ضعیف به این شیء نوع. به ارث برده نمیشود. فقط برای استفادهی داخلی.
تغییر یافته در نسخهی 3.12: جزئیات داخلی: برای نوعهای توکار ایستا، این همیشه
NULLاست، حتی اگر ارجاعهای ضعیف اضافه شوند. در عوض، ارجاعهای ضعیف هر یک رویPyInterpreterStateذخیره میشوند. برای پرهیز از این تمایز، از C-API عمومی یا ماکرو داخلی_PyObject_GET_WEAKREFS_LISTPTR()استفاده کنید.ارثبری:
این فیلد به ارث برده نمیشود.
-
destructor PyTypeObject.tp_del¶
The corresponding slot ID
Py_tp_delis part of the ABI پایدار.این فیلد منسوخ شده است. بهجای آن از
tp_finalizeاستفاده کنید.
-
unsigned int PyTypeObject.tp_version_tag¶
برای اندیسگذاری در نهانگاه متد استفاده میشود. فقط برای استفاده داخلی.
ارثبری:
این فیلد به ارث برده نمیشود.
-
destructor PyTypeObject.tp_finalize¶
The corresponding slot ID
Py_tp_finalizeis part of the ABI پایدار از نسخهی 3.5.یک اشارهگر اختیاری به تابع نهاییسازی نمونه. این، پیادهسازی C متد ویژهی
__del__()است. امضای آن به این صورت است:void tp_finalize(PyObject *self);
هدف اصلی نهاییسازی، انجام هر پاکسازی غیربدیهی است که باید پیش از نابود شدن شیء انجام شود، در حالی که شیء و هر شیء دیگری که مستقیماً یا غیرمستقیم به آنها ارجاع میدهد، همچنان در وضعیت سازگار هستند. نهاییساز مجاز است کد دلخواه پایتون را اجرا کند.
پیش از آنکه پایتون یک شیء را بهطور خودکار نهاییسازی کند، ممکن است برخی از ارجاعشوندههای (referents) مستقیم یا غیرمستقیم آن شیء، خودشان بهطور خودکار نهاییسازی شده باشند. با این حال، هیچیک از ارجاعشوندهها هنوز بهطور خودکار پاکسازی (
tp_clear) نشدهاند.ممکن است سایر اشیای نهایینشده همچنان در حال استفاده از یک شیء نهاییشده باشند، بنابراین نهاییساز باید شیء را در وضعیتی سالم باقی بگذارد (مثلاً، ناورداها همچنان برقرار باشند).
توجه
پس از آنکه پایتون بهطور خودکار یک شیء را نهاییسازی میکند، ممکن است پایتون پاکسازی خودکار (
tp_clear) آن شیء و ارجاعشدههایش (مستقیم و غیرمستقیم) را آغاز کند. تضمینی نیست که اشیای پاکسازیشده در وضعیتی سازگار باشند؛ یک شیء نهاییسازیشده باید بتواند ارجاعشدههای پاکسازیشده را تحمل کند.توجه
تضمین نمیشود که یک شیء پیش از فراخوانی مخرب آن (
tp_dealloc) بهطور خودکار نهاییسازی شده باشد. توصیه میشودPyObject_CallFinalizerFromDealloc()را در ابتدایtp_deallocفراخوانی کنید تا تضمین شود که شیء همیشه پیش از تخریب نهاییسازی میشود.توجه
تابع
tp_finalizeرا میتوان از هر نخی فراخوانی کرد، هرچند قفل مفسر سراسری در اختیار گرفته خواهد شد.توجه
تابع
tp_finalizeمیتواند در طول خاموشی، پس از حذف برخی از متغیرهای سراسری فراخوانی شود. برای جزئیات، مستندات متد__del__()را ببینید.وقتی پایتون یک شیء را نهاییسازی میکند، مانند الگوریتم زیر رفتار میکند:
پایتون ممکن است شیء را بهعنوان نهاییشده علامتگذاری کند. در حال حاضر، پایتون همیشه اشیایی را که نوع آنها از زبالهروبی پشتیبانی میکند (یعنی پرچم
Py_TPFLAGS_HAVE_GCدرtp_flagsتنظیم شده است) علامتگذاری میکند و هرگز اشیایی از انواع دیگر را علامتگذاری نمیکند؛ این ممکن است در نسخهای در آینده تغییر کند.اگر شیء بهعنوان نهاییسازیشده نشانهگذاری نشده باشد و تابع نهاییساز
tp_finalizeآن غیرNULLباشد، تابع نهاییساز فراخوانی میشود.اگر تابع نهاییساز فراخوانی شده باشد و نهاییساز شیء را دسترسپذیر کرده باشد (یعنی ارجاعی به شیء وجود داشته باشد و شیء عضوی از cyclic isolate نباشد)، آنگاه گفته میشود که نهاییساز شیء را احیا کرده است. مشخص نشده است که آیا نهاییساز میتواند با افزودن ارجاع جدیدی به شیء که آن را دسترسپذیر نمیکند، شیء را نیز احیا کند، یعنی شیء (هنوز) عضوی از یک ایزوله چرخهای است.
اگر نهاییساز شیء را احیا کرده باشد، نابودی در انتظار شیء لغو میشود و نشانهی نهاییشده شیء در صورت وجود ممکن است حذف شود. در حال حاضر، پایتون هرگز نشانهی نهاییشده را حذف نمیکند؛ این ممکن است در نسخههای آینده تغییر کند.
نهاییسازی خودکار به هر نهاییسازیای اشاره دارد که توسط پایتون انجام میشود، بهجز از طریق فراخوانی
PyObject_CallFinalizer()یاPyObject_CallFinalizerFromDealloc(). هیچ تضمینی ارائه نمیشود که یک شیء چه زمانی، آیا اصلاً، یا هر چند وقت یکبار بهطور خودکار نهاییسازی میشود، مگر:پایتون در صورتی که شیئی در دسترس باشد — یعنی ارجاعی به آن وجود داشته باشد و عضوی از یک cyclic isolate نباشد — آن را بهطور خودکار نهاییسازی نمیکند.
پایتون بهطور خودکار یک شیء را نهاییسازی نمیکند اگر نهاییسازی آن، آن شیء را بهعنوان نهاییشده علامتگذاری نکند. در حال حاضر، این مورد بر اشیائی اعمال میشود که نوع آنها از زبالهروبی پشتیبانی نمیکند؛ یعنی پرچم
Py_TPFLAGS_HAVE_GCتنظیم نشده است. اینگونه اشیاء همچنان میتوانند با فراخوانیPyObject_CallFinalizer()یاPyObject_CallFinalizerFromDealloc()بهصورت دستی نهاییسازی شوند.پایتون بهطور خودکار هیچ دو عضو از یک cyclic isolate را بهطور همزمان نهاییسازی نمیکند.
پایتون پس از پاکسازی خودکار (
tp_clear) یک شیء، آن شیء را بهطور خودکار نهایی نمیکند.اگر یک شیء عضوی از یک مجموعه چرخهای مجزا باشد، پایتون پس از پاکسازی خودکار هر عضو دیگر (به
tp_clearمراجعه کنید)، آن را بهطور خودکار نهاییسازی نخواهد کرد.پایتون پیش از آنکه بهطور خودکار هر یک از آنها را پاکسازی کند (رجوع کنید به
tp_clear)، بهطور خودکار هر عضو از یک cyclic isolate را نهایی میکند.اگر پایتون بخواهد یک شیء را بهطور خودکار پاکسازی کند (
tp_clear)، ابتدا شیء را بهطور خودکار نهاییسازی خواهد کرد.
پایتون در حال حاضر تنها اشیایی را بهطور خودکار نهاییسازی میکند که عضوی از یک cyclic isolate باشند، اما نسخههای آینده ممکن است اشیاء را بهطور منظم پیش از تخریبشان نهاییسازی کنند.
برای نهاییسازی دستی یک شیء، این تابع را مستقیماً فراخوانی نکنید؛ به جای آن
PyObject_CallFinalizer()یاPyObject_CallFinalizerFromDealloc()را فراخوانی کنید.tp_finalizeباید وضعیت فعلی استثنا را بدون تغییر بگذارد. روش توصیهشده برای نوشتن یک نهاییساز غیربدیهی این است که در ابتدا با فراخوانیPyErr_GetRaisedException()از استثنا پشتیبانگیری کنید و در پایان با فراخوانیPyErr_SetRaisedException()استثنا را بازگردانی کنید. اگر در میانهی نهاییساز استثنایی رخ دهد، آن را باPyErr_WriteUnraisable()یاPyErr_FormatUnraisable()گزارش داده و پاک کنید. برای مثال:static void foo_finalize(PyObject *self) { // Save the current exception, if any. PyObject *exc = PyErr_GetRaisedException(); // ... if (do_something_that_might_raise() != success_indicator) { PyErr_WriteUnraisable(self); goto done; } done: // Restore the saved exception. This silently discards any exception // raised above, so be sure to call PyErr_WriteUnraisable first if // necessary. PyErr_SetRaisedException(exc); }
ارثبری:
این فیلد به زیرنوعها به ارث میرسد.
اضافه شده در نسخهی 3.4.
تغییر یافته در نسخهی 3.8: پیش از نسخه 3.8 برای استفاده از این فیلد، لازم بود که بیت پرچم
Py_TPFLAGS_HAVE_FINALIZEتنظیم شود. این کار دیگر لازم نیست.همچنین ملاحظه نمائید
PEP 442: «نهاییسازی امن شیء»
چرخهی حیات شیء را برای جزئیات دربارهی نحوهی ارتباط این جایگاه با جایگاههای دیگر ببینید.
-
vectorcallfunc PyTypeObject.tp_vectorcall¶
The corresponding slot ID
Py_tp_vectorcallis part of the ABI پایدار از نسخهی 3.14.یک تابع vectorcall برای استفاده در فراخوانیهای این شیء نوع (به جای نمونهها). به عبارت دیگر،
tp_vectorcallمیتواند برای بهینهسازیtype.__call__استفاده شود که بهطور معمول نمونهی جدیدی از نوع را برمیگرداند.مانند هر تابع vectorcall، اگر
tp_vectorcallبرابرNULLباشد، بهجای آن از پروتکل tp_call (Py_TYPE(type)->tp_call) استفاده میشود.توجه
پروتکل vectorcall ایجاب میکند که تابع vectorcall همان رفتار
tp_callمتناظر را داشته باشد. این بدان معناست کهtype->tp_vectorcallباید با رفتارPy_TYPE(type)->tp_callمطابقت داشته باشد.بهطور خاص، اگر نوع از فراکلاس پیشفرض استفاده کند،
type->tp_vectorcallباید همانند PyType_Type->tp_call رفتار کند، که:type->tp_newرا فرامیخواند،اگر نتیجه زیرکلاسی از type باشد،
type->tp_initرا روی نتیجهیtp_newفراخوانی میکند ونتیجهی
tp_newرا برمیگرداند.
معمولاً
tp_vectorcallبازنویسی میشود تا این فرایند برایtp_newوtp_initخاص بهینهسازی شود. هنگام انجام این کار برای نوعهایی که کاربران میتوانند از آنها زیرکلاس بسازند، توجه داشته باشید که هر دوی آنها میتوانند بازنویسی شوند (با استفاده از__new__()و__init__()، بهترتیب).ارثبری:
این فیلد هرگز به ارث برده نمیشود.
اضافه شده در نسخهی 3.9: (این فیلد از نسخه 3.8 وجود دارد، اما تنها از نسخه 3.9 استفاده میشود)
-
unsigned char PyTypeObject.tp_watched¶
داخلی. استفاده نکنید.
اضافه شده در نسخهی 3.12.
نوعهای ایستا¶
بهطور سنتی، نوعهای تعریفشده در کد C ایستا هستند؛ یعنی یک ساختار ایستای PyTypeObject مستقیماً در کد تعریف میشود و با استفاده از PyType_Ready() مقداردهی اولیه میشود.
این امر منجر به نوعهایی میشود که نسبت به نوعهای تعریفشده در پایتون محدود هستند:
نوعهای ایستا به یک کلاس پایه محدود هستند، یعنی نمیتوانند از وراثت چندگانه استفاده کنند.
شیءهای نوع ایستا (اما نه لزوماً نمونههای آنها) تغییرناپذیر هستند. افزودن یا تغییر دادن ویژگیهای شیء نوع از پایتون امکانپذیر نیست.
اشیاء نوع ایستا بین زیرمفسرها به اشتراک گذاشته میشوند، بنابراین نباید شامل هیچ وضعیت مختص زیرمفسر باشند.
همچنین، از آنجا که PyTypeObject تنها بهعنوان یک ساختار مات بخشی از API محدود است، هر ماژول توسعهای که از نوعهای ایستا استفاده میکند، باید برای یک نسخهی فرعی مشخص از پایتون کامپایل شود.
نوعهای هیپ¶
جایگزینی برای نوعهای ایستا، نوعهای تخصیصیافته در هیپ یا بهاختصار نوعهای هیپ است که تطابق نزدیکی با کلاسهای ایجادشده توسط دستور class پایتون دارند. پرچم Py_TPFLAGS_HEAPTYPE در نوعهای هیپ تنظیمشده است.
این کار با پر کردن ساختار PyType_Spec و فراخوانی PyType_FromSpec()، PyType_FromSpecWithBases()، PyType_FromModuleAndSpec() یا PyType_FromMetaclass() انجام میشود.
ساختارهای شیء عدد¶
-
type PyNumberMethods¶
این ساختار اشارهگرهایی به توابعی را در خود نگه میدارد که یک شیء برای پیادهسازی پروتکل عددی از آنها استفاده میکند. هر تابع توسط تابعی با نام مشابه که در بخش پروتکل عدد مستند شده است، استفاده میشود.
این تعریف ساختار است:
typedef struct { binaryfunc nb_add; binaryfunc nb_subtract; binaryfunc nb_multiply; binaryfunc nb_remainder; binaryfunc nb_divmod; ternaryfunc nb_power; unaryfunc nb_negative; unaryfunc nb_positive; unaryfunc nb_absolute; inquiry nb_bool; unaryfunc nb_invert; binaryfunc nb_lshift; binaryfunc nb_rshift; binaryfunc nb_and; binaryfunc nb_xor; binaryfunc nb_or; unaryfunc nb_int; void *nb_reserved; unaryfunc nb_float; binaryfunc nb_inplace_add; binaryfunc nb_inplace_subtract; binaryfunc nb_inplace_multiply; binaryfunc nb_inplace_remainder; ternaryfunc nb_inplace_power; binaryfunc nb_inplace_lshift; binaryfunc nb_inplace_rshift; binaryfunc nb_inplace_and; binaryfunc nb_inplace_xor; binaryfunc nb_inplace_or; binaryfunc nb_floor_divide; binaryfunc nb_true_divide; binaryfunc nb_inplace_floor_divide; binaryfunc nb_inplace_true_divide; unaryfunc nb_index; binaryfunc nb_matrix_multiply; binaryfunc nb_inplace_matrix_multiply; } PyNumberMethods;
توجه
توابع دوعملوندی و سهعملوندی باید نوع همهی عملوندهای خود را بررسی کنند و تبدیلهای لازم را پیادهسازی کنند (حداقل یکی از عملوندها نمونهای از نوع تعریفشده است). اگر عملیات برای عملوندهای دادهشده تعریفنشده باشد، توابع دوعملوندی و سهعملوندی باید
Py_NotImplementedرا برگردانند و اگر خطای دیگری رخ داده باشد، بایدNULLرا برگردانند و یک استثنا تنظیم کنند.توجه
فیلد
nb_reservedباید همیشهNULLباشد. این فیلد پیشترnb_longنامیده میشد و در پایتون 3.0.1 تغییر نام یافت.
-
binaryfunc PyNumberMethods.nb_add¶
The corresponding slot ID
Py_nb_addis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_subtract¶
The corresponding slot ID
Py_nb_subtractis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_multiply¶
The corresponding slot ID
Py_nb_multiplyis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_remainder¶
The corresponding slot ID
Py_nb_remainderis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_divmod¶
The corresponding slot ID
Py_nb_divmodis part of the ABI پایدار.
-
ternaryfunc PyNumberMethods.nb_power¶
The corresponding slot ID
Py_nb_poweris part of the ABI پایدار.
-
unaryfunc PyNumberMethods.nb_negative¶
The corresponding slot ID
Py_nb_negativeis part of the ABI پایدار.
-
unaryfunc PyNumberMethods.nb_positive¶
The corresponding slot ID
Py_nb_positiveis part of the ABI پایدار.
-
unaryfunc PyNumberMethods.nb_absolute¶
The corresponding slot ID
Py_nb_absoluteis part of the ABI پایدار.
-
inquiry PyNumberMethods.nb_bool¶
The corresponding slot ID
Py_nb_boolis part of the ABI پایدار.
-
unaryfunc PyNumberMethods.nb_invert¶
The corresponding slot ID
Py_nb_invertis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_lshift¶
The corresponding slot ID
Py_nb_lshiftis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_rshift¶
The corresponding slot ID
Py_nb_rshiftis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_and¶
The corresponding slot ID
Py_nb_andis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_xor¶
The corresponding slot ID
Py_nb_xoris part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_or¶
The corresponding slot ID
Py_nb_oris part of the ABI پایدار.
-
unaryfunc PyNumberMethods.nb_int¶
The corresponding slot ID
Py_nb_intis part of the ABI پایدار.
-
void *PyNumberMethods.nb_reserved¶
-
unaryfunc PyNumberMethods.nb_float¶
The corresponding slot ID
Py_nb_floatis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_add¶
The corresponding slot ID
Py_nb_inplace_addis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_subtract¶
The corresponding slot ID
Py_nb_inplace_subtractis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_multiply¶
The corresponding slot ID
Py_nb_inplace_multiplyis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_remainder¶
The corresponding slot ID
Py_nb_inplace_remainderis part of the ABI پایدار.
-
ternaryfunc PyNumberMethods.nb_inplace_power¶
The corresponding slot ID
Py_nb_inplace_poweris part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_lshift¶
The corresponding slot ID
Py_nb_inplace_lshiftis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_rshift¶
The corresponding slot ID
Py_nb_inplace_rshiftis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_and¶
The corresponding slot ID
Py_nb_inplace_andis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_xor¶
The corresponding slot ID
Py_nb_inplace_xoris part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_or¶
The corresponding slot ID
Py_nb_inplace_oris part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_floor_divide¶
The corresponding slot ID
Py_nb_floor_divideis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_true_divide¶
The corresponding slot ID
Py_nb_true_divideis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_floor_divide¶
The corresponding slot ID
Py_nb_inplace_floor_divideis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_inplace_true_divide¶
The corresponding slot ID
Py_nb_inplace_true_divideis part of the ABI پایدار.
-
unaryfunc PyNumberMethods.nb_index¶
The corresponding slot ID
Py_nb_indexis part of the ABI پایدار.
-
binaryfunc PyNumberMethods.nb_matrix_multiply¶
The corresponding slot ID
Py_nb_matrix_multiplyis part of the ABI پایدار از نسخهی 3.5.
-
binaryfunc PyNumberMethods.nb_inplace_matrix_multiply¶
The corresponding slot ID
Py_nb_inplace_matrix_multiplyis part of the ABI پایدار از نسخهی 3.5.
ساختارهای شیء نگاشت¶
-
type PyMappingMethods¶
این ساختار اشارهگرهایی به توابعی را نگه میدارد که یک شیء از آنها برای پیادهسازی پروتکل نگاشت استفاده میکند. این ساختار سه عضو دارد:
-
lenfunc PyMappingMethods.mp_length¶
The corresponding slot ID
Py_mp_lengthis part of the ABI پایدار.این تابع توسط
PyMapping_Size()وPyObject_Size()استفاده میشود و همان امضا را دارد. اگر شیء طول تعریفشدهای نداشته باشد، این جایگاه میتواند بهNULLتنظیم شود.
-
binaryfunc PyMappingMethods.mp_subscript¶
The corresponding slot ID
Py_mp_subscriptis part of the ABI پایدار.این تابع توسط
PyObject_GetItem()وPySequence_GetSlice()استفاده میشود و امضای مشابهی باPyObject_GetItem()دارد. این جایگاه باید پر شود تا تابعPyMapping_Check()مقدار1را برگرداند، در غیر این صورت میتواندNULLباشد.
-
objobjargproc PyMappingMethods.mp_ass_subscript¶
The corresponding slot ID
Py_mp_ass_subscriptis part of the ABI پایدار.این تابع توسط
PyObject_SetItem()،PyObject_DelItem()،PySequence_SetSlice()وPySequence_DelSlice()استفاده میشود. این تابع امضایی مشابهPyObject_SetItem()دارد، اما v را میتوان برای حذف یک آیتم نیز برابرNULLقرار داد. اگر این جایگاهNULLباشد، شیء از انتساب و حذف آیتم پشتیبانی نمیکند.
ساختارهای اشیاء دنباله¶
-
type PySequenceMethods¶
این ساختار اشارهگرهایی به توابعی را نگه میدارد که یک شیء برای پیادهسازی پروتکل دنباله از آنها استفاده میکند.
-
lenfunc PySequenceMethods.sq_length¶
The corresponding slot ID
Py_sq_lengthis part of the ABI پایدار.این تابع توسط
PySequence_Size()وPyObject_Size()استفاده میشود و امضای یکسانی دارد. همچنین برای مدیریت اندیسهای منفی از طریق جایگاههایsq_itemوsq_ass_itemاز آن استفاده میشود.
-
binaryfunc PySequenceMethods.sq_concat¶
The corresponding slot ID
Py_sq_concatis part of the ABI پایدار.این تابع توسط
PySequence_Concat()استفاده میشود و امضای یکسانی دارد. همچنین پس از تلاش برای انجام جمع عددی از طریق جایگاهnb_add، توسط عملگر+نیز استفاده میشود.
-
ssizeargfunc PySequenceMethods.sq_repeat¶
The corresponding slot ID
Py_sq_repeatis part of the ABI پایدار.این تابع توسط
PySequence_Repeat()استفاده میشود و امضای یکسانی دارد. عملگر*نیز پس از تلاش برای ضرب عددی از طریق جایگاهnb_multiplyاز این تابع استفاده میکند.
-
ssizeargfunc PySequenceMethods.sq_item¶
The corresponding slot ID
Py_sq_itemis part of the ABI پایدار.این تابع توسط
PySequence_GetItem()استفاده میشود و امضای یکسانی دارد. این تابع همچنین توسطPyObject_GetItem()استفاده میشود، پس از تلاش برای زیرنویسی از طریق جایگاهmp_subscript. این جایگاه باید پرشده باشد تا تابعPySequence_Check()مقدار1را برگرداند؛ در غیر این صورت میتواندNULLباشد.اندیسهای منفی به صورت زیر مدیریت میشوند: اگر جایگاه
sq_lengthپر شده باشد، فراخوانی میشود و از طول دنباله برای محاسبهی اندیس مثبتی که بهsq_itemارسال میشود، استفاده میشود. اگرsq_lengthبرابرNULLباشد، اندیس بدون تغییر به تابع ارسال میشود.
-
ssizeobjargproc PySequenceMethods.sq_ass_item¶
The corresponding slot ID
Py_sq_ass_itemis part of the ABI پایدار.این تابع توسط
PySequence_SetItem()استفاده میشود و همان امضا را دارد. این تابع همچنین پس از تلاش برای انجام انتساب و حذف آیتم از طریق جایگاهmp_ass_subscript، توسطPyObject_SetItem()وPyObject_DelItem()استفاده میشود. اگر شیء از انتساب و حذف آیتم پشتیبانی نکند، میتوان این جایگاه راNULLگذاشت.
-
objobjproc PySequenceMethods.sq_contains¶
The corresponding slot ID
Py_sq_containsis part of the ABI پایدار.این تابع ممکن است توسط
PySequence_Contains()استفاده شود و همان امضا را دارد. میتوان این جایگاه راNULLگذاشت؛ در این صورتPySequence_Contains()صرفاً دنباله را پیمایش میکند تا زمانی که مورد منطبقی بیابد.
-
binaryfunc PySequenceMethods.sq_inplace_concat¶
The corresponding slot ID
Py_sq_inplace_concatis part of the ABI پایدار.این تابع توسط
PySequence_InPlaceConcat()استفاده میشود و امضای یکسانی با آن دارد. این تابع باید عملوند اول خود را تغییر دهد و آن را برگرداند. این جایگاه میتواندNULLباقی بماند؛ در این صورتPySequence_InPlaceConcat()بهPySequence_Concat()بازمیگردد. این جایگاه همچنین توسط انتساب افزودهی+=استفاده میشود، پس از تلاش برای انجام جمع درجای عددی از طریق جایگاهnb_inplace_add.
-
ssizeargfunc PySequenceMethods.sq_inplace_repeat¶
The corresponding slot ID
Py_sq_inplace_repeatis part of the ABI پایدار.این تابع توسط
PySequence_InPlaceRepeat()استفاده میشود و امضای یکسانی دارد. باید عملوند اول خود را تغییر دهد و آن را بازگرداند. این جایگاه را میتوانNULLگذاشت؛ در این صورتPySequence_InPlaceRepeat()بهPySequence_Repeat()بازمیگردد. این جایگاه همچنین توسط عملگر انتساب افزوده*=استفاده میشود، پس از تلاش برای ضرب عددی درجا از طریق جایگاهnb_inplace_multiply.
ساختارهای شیء بافر¶
-
type PyBufferProcs¶
این ساختار اشارهگرهایی به توابع مورد نیاز پروتکل بافر را نگه میدارد. این پروتکل تعریف میکند که یک شیء اکسپورتکننده چگونه میتواند دادههای داخلی خود را در دسترس اشیاء مصرفکننده قرار دهد.
-
getbufferproc PyBufferProcs.bf_getbuffer¶
The corresponding slot ID
Py_bf_getbufferis part of the ABI پایدار از نسخهی 3.11.امضای این تابع به این صورت است:
int (PyObject *exporter, Py_buffer *view, int flags);
درخواستی به exporter برای پر کردن view مطابق با flags را مدیریت میکند. بهجز مورد (۳)، پیادهسازی این تابع باید این گامها را بردارد:
بررسی کنید که آیا درخواست قابل برآوردن است یا خیر. در غیر این صورت، استثنای
BufferErrorرا ایجاد کنید،view->objرا برابرNULLقرار دهید و-1را برگردانید.فیلدهای درخواستی را پر کنید.
شمارندهی داخلی تعداد اکسپورت را افزایش میدهد.
مقدار
view->objرا برابر exporter قرار دهید وview->objرا افزایش دهید.0را برمیگرداند.
نخایمنی:
در free-threaded build، پیادهسازیها باید اطمینان حاصل کنند:
افزایش شمارندهی اکسپورت (export) در گام (۳) اتمیک است.
دادههای بافر زیرین برای طول عمر همهی اکسپورتها (export) معتبر و در مکان حافظهای پایدار باقی میمانند.
برای اشیایی که از تغییر اندازه یا تخصیص مجدد پشتیبانی میکنند (مانند
bytearray)، شمارنده اکسپورت پیش از انجام چنین عملیاتهایی بهصورت اتمیک بررسی میشود و در صورت وجود اکسپورتها،BufferErrorایجاد میشود.فراخوانی همزمان این تابع از چندین نخ ایمن است.
همچنین برای تضمینهای ایمنی نخ در سطح پایتون برای اشیاء
memoryview، به Thread safety for memoryview objects مراجعه کنید.اگر اکسپورتکننده (exporter) بخشی از زنجیره یا درختی از تأمینکنندگان بافر باشد، میتوان از دو طرحوارهی اصلی استفاده کرد:
اکسپورت کردن مجدد: هر عضو درخت بهعنوان شیء اکسپورتکننده عمل میکند و
view->objرا برابر یک ارجاع جدید به خود قرار میدهد.هدایت مجدد: درخواست بافر به شیء ریشهی درخت هدایت مجدد میشود. در اینجا،
view->objارجاعی جدید به شیء ریشه خواهد بود.
فیلدهای جداگانهی view در بخش ساختار بافر توصیف شدهاند و قواعدی که اکسپورتکننده باید بر اساس آنها به درخواستهای خاص واکنش نشان دهد، در بخش انواع درخواست بافر آمده است.
تمام حافظهای که در ساختار
Py_bufferبه آن اشاره میشود متعلق به اکسپورتکننده است و باید تا زمانی که هیچ مصرفکنندهای باقی نمانده باشد معتبر بماند.format،shape،strides،suboffsetsوinternalبرای مصرفکننده فقطخواندنی هستند.PyBuffer_FillInfo()راهی آسان برای در معرض قرار دادن یک بافر بایت ساده فراهم میکند، در حالی که با همهی انواع درخواست بهدرستی برخورد میکند.PyObject_GetBuffer()رابط مصرفکنندهای است که این تابع را دربر میگیرد.
-
releasebufferproc PyBufferProcs.bf_releasebuffer¶
The corresponding slot ID
Py_bf_releasebufferis part of the ABI پایدار از نسخهی 3.11.امضای این تابع به این صورت است:
void (PyObject *exporter, Py_buffer *view);
درخواست آزاد کردن منابع بافر را مدیریت میکند. اگر هیچ منبعی نیاز به آزاد شدن نداشته باشد،
PyBufferProcs.bf_releasebufferمیتواندNULLباشد. در غیر این صورت، یک پیادهسازی استاندارد از این تابع گامهای اختیاری زیر را برمیدارد:شمارنده داخلی تعداد اکسپورتهارا را کاهش دهید.
اگر شمارنده
0باشد، تمام حافظهی مرتبط با view را آزاد کنید.
نخایمنی:
کاهش شمارندهی اکسپورت در گام (۱) باید اتمیک باشد.
پاکسازی منابع هنگامی که شمارنده به صفر میرسد باید بهصورت اتمیک انجام شود، زیرا آزادسازی نهایی ممکن است با آزادسازیهای همزمان از سوی نخهای دیگر رقابت کند و تخصیصزدایی باید تنها یکبار رخ دهد.
اکسپورتکننده باید از فیلد
internalبرای پیگیری منابع مخصوص بافر استفاده کند. تضمین میشود که این فیلد ثابت باقی بماند، در حالی که مصرفکننده میتواند رونوشتی از بافر اصلی را بهعنوان آرگومان view ارسال کند.این تابع به هیچ وجه نباید
view->objرا کاهش دهد، زیرا این کار بهطور خودکار درPyBuffer_Release()انجام میشود (این طرح برای شکستن چرخههای ارجاع مفید است).PyBuffer_Release()رابطی برای مصرفکننده است که این تابع را پوشش میدهد.
ساختارهای اشیای ناهمگام¶
اضافه شده در نسخهی 3.5.
-
type PyAsyncMethods¶
این ساختار اشارهگرهایی به توابع مورد نیاز برای پیادهسازی اشیاء انتظارپذیر و پیمایشگر ناهمگام را در خود نگه میدارد.
این تعریف ساختار است:
typedef struct { unaryfunc am_await; unaryfunc am_aiter; unaryfunc am_anext; sendfunc am_send; } PyAsyncMethods;
-
unaryfunc PyAsyncMethods.am_await¶
The corresponding slot ID
Py_am_awaitis part of the ABI پایدار از نسخهی 3.5.امضای این تابع به این صورت است:
PyObject *am_await(PyObject *self);
شیء بازگرداندهشده باید یک پیمایشگر باشد؛ یعنی
PyIter_Check()باید برای آن1برگرداند.اگر یک شیء awaitable نباشد، این جایگاه میتواند روی
NULLتنظیم شود.
-
unaryfunc PyAsyncMethods.am_aiter¶
The corresponding slot ID
Py_am_aiteris part of the ABI پایدار از نسخهی 3.5.امضای این تابع به این صورت است:
PyObject *am_aiter(PyObject *self);
باید یک شیء asynchronous iterator برگرداند. برای جزئیات به
__anext__()مراجعه کنید.اگر شیئی پروتکل پیمایش ناهمگام را پیادهسازی نکرده باشد، این جایگاه میتواند برابر
NULLقرار داده شود.
-
unaryfunc PyAsyncMethods.am_anext¶
The corresponding slot ID
Py_am_anextis part of the ABI پایدار از نسخهی 3.5.امضای این تابع به این صورت است:
PyObject *am_anext(PyObject *self);
باید یک شیء انتظارپذیر برگرداند. برای جزئیات به
__anext__()مراجعه کنید. این جایگاه میتواند بهNULLتنظیم شود.
-
sendfunc PyAsyncMethods.am_send¶
The corresponding slot ID
Py_am_sendis part of the ABI پایدار از نسخهی 3.10.امضای این تابع به این صورت است:
PySendResult am_send(PyObject *self, PyObject *arg, PyObject **result);
برای جزئیات به
PyIter_Send()مراجعه کنید. این جایگاه میتواند بهNULLتنظیم شود.اضافه شده در نسخهی 3.10.
typedefهای نوع جایگاه¶
-
typedef PyObject *(*allocfunc)(PyTypeObject *cls, Py_ssize_t nitems)¶
- قسمتی از ABI پایدار.
هدف این تابع، جداسازی تخصیص حافظه از مقداردهی اولیه حافظه است. این تابع باید اشارهگری به بلوکی از حافظه با طول مناسب برای نمونه، همترازشده بهدرستی و مقداردهیشده به صفر برگرداند، اما بهطوریکه
ob_refcntروی1وob_typeروی آرگومان نوع تنظیم شده باشد. اگرtp_itemsizeنوع غیرصفر باشد، فیلدob_sizeشیء باید به nitems مقداردهی اولیه شود و طول بلوک حافظه تخصیصیافته بایدtp_basicsize + nitems*tp_itemsizeباشد که به سمت بالا به مضربی ازsizeof(void*)گرد شده است؛ در غیر این صورت، nitems استفاده نمیشود و طول بلوک بایدtp_basicsizeباشد.این تابع نباید هیچ مقداردهی اولیهی دیگری روی نمونه انجام دهد، حتی تخصیص حافظهی اضافی؛ این کار باید توسط
tp_newانجام شود.
-
typedef void (*destructor)(PyObject*)¶
- قسمتی از ABI پایدار.
-
typedef PyObject *(*newfunc)(PyTypeObject*, PyObject*, PyObject*)¶
- قسمتی از ABI پایدار.
به
tp_newمراجعه کنید.
-
typedef int (*initproc)(PyObject*, PyObject*, PyObject*)¶
- قسمتی از ABI پایدار.
به
tp_initمراجعه کنید.
-
typedef PyObject *(*reprfunc)(PyObject*)¶
- قسمتی از ABI پایدار.
به
tp_reprمراجعه کنید.
-
typedef PyObject *(*getattrfunc)(PyObject *self, char *attr)¶
- قسمتی از ABI پایدار.
مقدار ویژگی نامبردهشده را برای شیء برمیگرداند.
-
typedef int (*setattrfunc)(PyObject *self, char *attr, PyObject *value)¶
- قسمتی از ABI پایدار.
مقدار ویژگی نامبرده را برای شیء تنظیم میکند. آرگومان مقدار برای حذف ویژگی روی
NULLتنظیم میشود.
-
typedef PyObject *(*getattrofunc)(PyObject *self, PyObject *attr)¶
- قسمتی از ABI پایدار.
مقدار ویژگی نامبردهشده را برای شیء برمیگرداند.
به
tp_getattroمراجعه کنید.
-
typedef int (*setattrofunc)(PyObject *self, PyObject *attr, PyObject *value)¶
- قسمتی از ABI پایدار.
مقدار ویژگی نامبرده را برای شیء تنظیم میکند. آرگومان مقدار برای حذف ویژگی روی
NULLتنظیم میشود.به
tp_setattroمراجعه کنید.
-
typedef PyObject *(*descrgetfunc)(PyObject*, PyObject*, PyObject*)¶
- قسمتی از ABI پایدار.
tp_descr_getرا ببینید.
-
typedef int (*descrsetfunc)(PyObject*, PyObject*, PyObject*)¶
- قسمتی از ABI پایدار.
tp_descr_setرا ببینید.
-
typedef Py_hash_t (*hashfunc)(PyObject*)¶
- قسمتی از ABI پایدار.
به
tp_hashمراجعه کنید.
-
typedef PyObject *(*richcmpfunc)(PyObject*, PyObject*, int)¶
- قسمتی از ABI پایدار.
به
tp_richcompareمراجعه کنید.
-
typedef PyObject *(*getiterfunc)(PyObject*)¶
- قسمتی از ABI پایدار.
به
tp_iterمراجعه کنید.
-
typedef PyObject *(*iternextfunc)(PyObject*)¶
- قسمتی از ABI پایدار.
به
tp_iternextمراجعه کنید.
-
typedef Py_ssize_t (*lenfunc)(PyObject*)¶
- قسمتی از ABI پایدار.
-
typedef int (*getbufferproc)(PyObject*, Py_buffer*, int)¶
- قسمتی از ABI پایدار از نسخهی 3.12.
-
typedef void (*releasebufferproc)(PyObject*, Py_buffer*)¶
- قسمتی از ABI پایدار از نسخهی 3.12.
-
typedef PyObject *(*unaryfunc)(PyObject*)¶
- قسمتی از ABI پایدار.
-
typedef PyObject *(*binaryfunc)(PyObject*, PyObject*)¶
- قسمتی از ABI پایدار.
-
typedef PyObject *(*ssizeargfunc)(PyObject*, Py_ssize_t)¶
- قسمتی از ABI پایدار.
-
typedef int (*ssizeobjargproc)(PyObject*, Py_ssize_t, PyObject*)¶
- قسمتی از ABI پایدار.
-
typedef int (*objobjproc)(PyObject*, PyObject*)¶
- قسمتی از ABI پایدار.
-
typedef int (*objobjargproc)(PyObject*, PyObject*, PyObject*)¶
- قسمتی از ABI پایدار.
مثالها¶
در ادامه، نمونههای سادهای از تعریف نوعها در پایتون آمده است. این نمونهها شامل کاربردهای رایجی هستند که ممکن است با آنها مواجه شوید. برخی از آنها موارد گوشهای پیچیده را نشان میدهند. برای مثالهای بیشتر، اطلاعات کاربردی و یک آموزش، به تعریف نوعهای توسعهای: آموزش و تعریف نوعهای توسعهای: موضوعات گوناگون مراجعه کنید.
یک نوع ایستای پایه:
typedef struct {
PyObject_HEAD
const char *data;
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject),
.tp_doc = PyDoc_STR("My objects"),
.tp_new = myobj_new,
.tp_dealloc = (destructor)myobj_dealloc,
.tp_repr = (reprfunc)myobj_repr,
};
ممکن است کد قدیمیتری نیز بیابید (بهویژه در کدبیس سیپایتون) که از مقداردهنده اولیهی پرحرفتری استفاده میکند:
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"mymod.MyObject", /* tp_name */
sizeof(MyObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)myobj_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)myobj_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
0, /* tp_flags */
PyDoc_STR("My objects"), /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
myobj_new, /* tp_new */
};
نوعی که از ارجاعهای ضعیف، دیکشنریهای نمونه و هش کردن پشتیبانی میکند:
typedef struct {
PyObject_HEAD
const char *data;
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject),
.tp_doc = PyDoc_STR("My objects"),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
Py_TPFLAGS_MANAGED_WEAKREF,
.tp_new = myobj_new,
.tp_traverse = (traverseproc)myobj_traverse,
.tp_clear = (inquiry)myobj_clear,
.tp_alloc = PyType_GenericNew,
.tp_dealloc = (destructor)myobj_dealloc,
.tp_repr = (reprfunc)myobj_repr,
.tp_hash = (hashfunc)myobj_hash,
.tp_richcompare = PyBaseObject_Type.tp_richcompare,
};
زیرکلاسی از str که نمیتوان از آن زیرکلاس گرفت و نمیتوان آن را برای ایجاد نمونه فراخوانی کرد (مثلاً از یک تابع کارخانهای جداگانه استفاده میکند) با استفاده از پرچم Py_TPFLAGS_DISALLOW_INSTANTIATION:
typedef struct {
PyUnicodeObject raw;
char *extra;
} MyStr;
static PyTypeObject MyStr_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyStr",
.tp_basicsize = sizeof(MyStr),
.tp_base = NULL, // set to &PyUnicode_Type in module init
.tp_doc = PyDoc_STR("my custom str"),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.tp_repr = (reprfunc)myobj_repr,
};
سادهترین نوع ایستا با نمونههای با طول ثابت:
typedef struct {
PyObject_HEAD
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
};
سادهترین نوع ایستا با نمونههای با طول متغیر:
typedef struct {
PyObject_VAR_HEAD
const char *data[1];
} MyObject;
static PyTypeObject MyObject_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "mymod.MyObject",
.tp_basicsize = sizeof(MyObject) - sizeof(char *),
.tp_itemsize = sizeof(char *),
};