ساختارهای شیء نوع

شاید یکی از مهم‌ترین ساختارهای سیستم شیء پایتون، ساختاری باشد که یک نوع جدید را تعریف می‌کند: ساختار PyTypeObject. اشیاء نوع را می‌توان با استفاده از هر یک از توابع PyObject_* یا PyType_* مدیریت کرد، اما چیز جالب زیادی برای بیشتر برنامه‌های پایتون ارائه نمی‌دهند. این اشیاء مبنای نحوه رفتار اشیاء هستند، بنابراین برای خود مفسر و برای هر ماژول توسعه‌ای که نوع‌های جدیدی را پیاده‌سازی می‌کند بسیار مهم هستند.

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

علاوه بر مرجع سریع زیر، بخش مثال‌ها درکی سریع و فوری از معنا و کاربرد PyTypeObject فراهم می‌کند.

مرجع سریع

جایگاه‌های tp

جایگاه PyTypeObject [1]

نوع

متدهای ویژه/ویژگی‌ها

اطلاعات [2]

O

T

D

I

<R> tp_name

const char *

__name__

X

X

tp_basicsize

Py_ssize_t

X

X

X

tp_itemsize

Py_ssize_t

X

X

tp_dealloc

destructor

X

X

X

tp_vectorcall_offset

Py_ssize_t

X

X

(tp_getattr)

getattrfunc

__getattribute__, __getattr__

G

(tp_setattr)

setattrfunc

__setattr__, __delattr__

G

tp_as_async

PyAsyncMethods *

زیرجایگاه‌ها (sub-slots)

%

tp_repr

reprfunc

__repr__

X

X

X

tp_as_number

PyNumberMethods *

زیرجایگاه‌ها (sub-slots)

%

tp_as_sequence

PySequenceMethods *

زیرجایگاه‌ها (sub-slots)

%

tp_as_mapping

PyMappingMethods *

زیرجایگاه‌ها (sub-slots)

%

tp_hash

hashfunc

__hash__

X

G

tp_call

ternaryfunc

__call__

X

X

tp_str

reprfunc

__str__

X

X

tp_getattro

getattrofunc

__getattribute__, __getattr__

X

X

G

tp_setattro

setattrofunc

__setattr__, __delattr__

X

X

G

tp_as_buffer

PyBufferProcs *

زیرجایگاه‌ها (sub-slots)

%

tp_flags

unsigned long

X

X

?

tp_doc

const char *

__doc__

X

X

tp_traverse

traverseproc

X

G

tp_clear

inquiry

X

G

tp_richcompare

richcmpfunc

__lt__, __le__, __eq__, __ne__, __gt__, __ge__

X

G

(tp_weaklistoffset)

Py_ssize_t

X

?

tp_iter

getiterfunc

__iter__

X

tp_iternext

iternextfunc

__next__

X

tp_methods

PyMethodDef []

X

X

tp_members

PyMemberDef []

X

tp_getset

PyGetSetDef []

X

X

tp_base

PyTypeObject *

__base__

X

tp_dict

PyObject *

__dict__

?

tp_descr_get

descrgetfunc

__get__

X

tp_descr_set

descrsetfunc

__set__, __delete__

X

(tp_dictoffset)

Py_ssize_t

X

?

tp_init

initproc

__init__

X

X

X

tp_alloc

allocfunc

X

?

?

tp_new

newfunc

__new__

X

X

?

?

tp_free

freefunc

X

X

?

?

tp_is_gc

inquiry

X

X

<tp_bases>

PyObject *

__bases__

~

<tp_mro>

PyObject *

__mro__

~

[tp_cache]

PyObject *

[tp_subclasses]

void *

__subclasses__

[tp_weaklist]

PyObject *

(tp_del)

destructor

[tp_version_tag]

unsigned int

tp_finalize

destructor

__del__

X

tp_vectorcall

vectorcallfunc

[tp_watched]

unsigned char

زیرجایگاه‌ها (sub-slots)

جایگاه

نوع

متد‌های ویژه

am_await

unaryfunc

__await__

am_aiter

unaryfunc

__aiter__

am_anext

unaryfunc

__anext__

am_send

sendfunc

nb_add

binaryfunc

__add__ __radd__

nb_inplace_add

binaryfunc

__iadd__

nb_subtract

binaryfunc

__sub__ __rsub__

nb_inplace_subtract

binaryfunc

__isub__

nb_multiply

binaryfunc

__mul__ __rmul__

nb_inplace_multiply

binaryfunc

__imul__

nb_remainder

binaryfunc

__mod__ __rmod__

nb_inplace_remainder

binaryfunc

__imod__

nb_divmod

binaryfunc

__divmod__ __rdivmod__

nb_power

ternaryfunc

__pow__ __rpow__

nb_inplace_power

ternaryfunc

__ipow__

nb_negative

unaryfunc

__neg__

nb_positive

unaryfunc

__pos__

nb_absolute

unaryfunc

__abs__

nb_bool

inquiry

__bool__

nb_invert

unaryfunc

__invert__

nb_lshift

binaryfunc

__lshift__ __rlshift__

nb_inplace_lshift

binaryfunc

__ilshift__

nb_rshift

binaryfunc

__rshift__ __rrshift__

nb_inplace_rshift

binaryfunc

__irshift__

nb_and

binaryfunc

__and__ __rand__

nb_inplace_and

binaryfunc

__iand__

nb_xor

binaryfunc

__xor__ __rxor__

nb_inplace_xor

binaryfunc

__ixor__

nb_or

binaryfunc

__or__ __ror__

nb_inplace_or

binaryfunc

__ior__

nb_int

unaryfunc

__int__

nb_reserved

void *

nb_float

unaryfunc

__float__

nb_floor_divide

binaryfunc

__floordiv__

nb_inplace_floor_divide

binaryfunc

__ifloordiv__

nb_true_divide

binaryfunc

__truediv__

nb_inplace_true_divide

binaryfunc

__itruediv__

nb_index

unaryfunc

__index__

nb_matrix_multiply

binaryfunc

__matmul__ __rmatmul__

nb_inplace_matrix_multiply

binaryfunc

__imatmul__

mp_length

lenfunc

__len__

mp_subscript

binaryfunc

__getitem__

mp_ass_subscript

objobjargproc

__setitem__, __delitem__

sq_length

lenfunc

__len__

sq_concat

binaryfunc

__add__

sq_repeat

ssizeargfunc

__mul__

sq_item

ssizeargfunc

__getitem__

sq_ass_item

ssizeobjargproc

__setitem__ __delitem__

sq_contains

objobjproc

__contains__

sq_inplace_concat

binaryfunc

__iadd__

sq_inplace_repeat

ssizeargfunc

__imul__

bf_getbuffer

getbufferproc()

__buffer__

bf_releasebuffer

releasebufferproc()

__release_buffer__

تعریف‌های نوع جایگاه (slot typedefs)

typedef

انواع پارامتر

نوع بازگشتی

allocfunc

PyObject *

destructor

PyObject *

void

freefunc

void *

void

traverseproc

void *

int

newfunc

PyObject *

initproc

int

reprfunc

PyObject *

PyObject *

getattrfunc

const char *

PyObject *

setattrfunc

const char *

int

getattrofunc

PyObject *

setattrofunc

int

descrgetfunc

PyObject *

descrsetfunc

int

hashfunc

PyObject *

Py_hash_t

richcmpfunc

int

PyObject *

getiterfunc

PyObject *

PyObject *

iternextfunc

PyObject *

PyObject *

lenfunc

PyObject *

Py_ssize_t

getbufferproc

int

releasebufferproc

void

inquiry

PyObject *

int

unaryfunc

PyObject *

binaryfunc

PyObject *

ternaryfunc

PyObject *

ssizeargfunc

PyObject *

ssizeobjargproc

int

objobjproc

int

objobjargproc

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.ob_refcnt

شمارش ارجاع شیء نوع توسط ماکروی PyObject_HEAD_INIT به 1 مقداردهی اولیه می‌شود. توجه داشته باشید که برای اشیای نوع تخصیص‌یافته به‌صورت ایستا، نمونه‌های نوع (اشیایی که ob_type آن‌ها به خود نوع اشاره می‌کند) به‌عنوان ارجاع شمرده نمی‌شوند. اما برای اشیای نوع تخصیص‌یافته به‌صورت پویا، نمونه‌ها به‌عنوان ارجاع شمرده می‌شوند.

ارث‌بری:

این فیلد توسط زیرنوع‌ها به ارث برده نمی‌شود.

PyObject.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

PyVarObject.ob_size

برای اشیاء نوع با تخصیص ایستا، این باید به صفر مقداردهی اولیه شود. برای اشیاء نوع با تخصیص پویا، این فیلد معنای درونی خاصی دارد.

برای دسترسی به این فیلد باید از ماکروی 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_dealloc is 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_getattr is 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_setattr is 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_repr is 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_hash is 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_call is 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_str is 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_getattro is 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_setattro is 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 موجود و مقداردهی اولیه شده بود.

Py_TPFLAGS_INLINE_VALUES

این بیت نشان می‌دهد که نمونه‌های این نوع، آرایه‌ی «مقادیر درون‌خطی» (inline values) — شامل ویژگی‌های شیء — خواهند داشت که مستقیماً پس از انتهای شیء قرار می‌گیرد.

این امر نیازمند آن است که Py_TPFLAGS_HAVE_GC تنظیم شده باشد.

ارث‌بری:

این پرچم به ارث برده نمی‌شود.

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

Py_TPFLAGS_IS_ABSTRACT

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

ارث‌بری:

این پرچم به ارث برده نمی‌شود.

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

abc

Py_TPFLAGS_HAVE_STACKLESS_EXTENSION

داخلی. این پرچم را تنظیم یا از تنظیم خارج نکنید. در گذشته، این پرچم برای استفاده در Stackless Python رزروشده بود.

هشدار

این پرچم در پرونده‌های سرآیند وجود دارد، اما استفاده نمی‌شود. ممکن است در نسخه‌های آینده‌ی سی‌پایتون حذف شود.

const char *PyTypeObject.tp_doc

The corresponding slot ID Py_tp_doc is part of the ABI پایدار.

یک اشاره‌گر اختیاری به رشته‌ی C پایان‌یافته با تهی که رشته‌ی مستند این شیء نوع را ارائه می‌دهد. این رشته‌ی مستند به‌صورت ویژگی __doc__ روی نوع و نمونه‌های آن نوع در دسترس قرار می‌گیرد.

ارث‌بری:

این فیلد توسط زیرنوع‌ها به ارث برده نمی‌شود.

traverseproc PyTypeObject.tp_traverse

The corresponding slot ID Py_tp_traverse is 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_clear is 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_richcompare is 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_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_iter is part of the ABI پایدار.

یک اشاره‌گر اختیاری به تابعی که یک iterator برای شیء برمی‌گرداند. حضور آن معمولاً نشان می‌دهد که نمونه‌های این نوع iterable هستند (هرچند دنباله‌ها ممکن است بدون این تابع پیمایش‌پذیر باشند).

این تابع همان امضای PyObject_GetIter() را دارد:

PyObject *tp_iter(PyObject *self);

ارث‌بری:

این فیلد به زیرنوع‌ها به ارث می‌رسد.

iternextfunc PyTypeObject.tp_iternext

The corresponding slot ID Py_tp_iternext is part of the ABI پایدار.

اشاره‌گر اختیاری به تابعی که آیتم بعدی در یک پیمایش‌گر را برمی‌گرداند. امضا به این صورت است:

PyObject *tp_iternext(PyObject *self);

When the iterator is exhausted, the tp_iternext function must return NULL; a StopIteration exception may or may not be set. When another error occurs, it must return NULL too. The presence of tp_iternext signals that the instances of this type are iterators.

نوع‌های پیمایش‌گر باید تابع tp_iter را نیز تعریف کنند، و این تابع باید خودِ نمونه‌ی پیمایش‌گر را برگرداند (نه یک نمونه‌ی پیمایش‌گر جدید).

این تابع همان امضای PyIter_Next() را دارد.

ارث‌بری:

این فیلد به زیرنوع‌ها به ارث می‌رسد.

struct PyMethodDef *PyTypeObject.tp_methods

The corresponding slot ID Py_tp_methods is part of the ABI پایدار.

یک اشاره‌گر اختیاری به آرایه‌ی ایستای پایان‌یافته با NULL از ساختارهای PyMethodDef که متدهای معمولی این نوع را اعلام می‌کند.

برای هر ورودی در آرایه، ورودی‌ای به دیکشنری نوع اضافه می‌شود (به tp_dict در ادامه ببینید) که حاوی یک توصیف‌گر متد است.

ارث‌بری:

این فیلد توسط زیرنوع‌ها به ارث برده نمی‌شود (متدها از طریق سازوکاری متفاوت به ارث برده می‌شوند).

struct PyMemberDef *PyTypeObject.tp_members

The corresponding slot ID Py_tp_members is part of the ABI پایدار.

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

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

ارث‌بری:

این فیلد به زیرنوع‌ها به ارث نمی‌رسد (اعضا از طریق سازوکاری متفاوت به ارث می‌رسند).

struct PyGetSetDef *PyTypeObject.tp_getset

The corresponding slot ID Py_tp_getset is part of the ABI پایدار.

یک اشاره‌گر اختیاری به یک آرایه‌ی ایستای پایان‌یافته با NULL از ساختارهای PyGetSetDef که ویژگی‌های محاسبه‌شده‌ی نمونه‌های این نوع را اعلان می‌کند.

برای هر ورودی در آرایه، یک ورودی به دیکشنری نوع اضافه می‌شود (به tp_dict در ادامه مراجعه کنید) که شامل یک توصیف‌گر getset است.

ارث‌بری:

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

PyTypeObject *PyTypeObject.tp_base

The corresponding slot ID Py_tp_base is 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_get is 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_set is 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_init is 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_alloc is 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_new is 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_free is 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_gc is 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_bases is 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_del is part of the ABI پایدار.

این فیلد منسوخ شده است. به‌جای آن از tp_finalize استفاده کنید.

unsigned int PyTypeObject.tp_version_tag

برای اندیس‌گذاری در نهانگاه متد استفاده می‌شود. فقط برای استفاده داخلی.

ارث‌بری:

این فیلد به ارث برده نمی‌شود.

destructor PyTypeObject.tp_finalize

The corresponding slot ID Py_tp_finalize is 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__() را ببینید.

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

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

  2. اگر شیء به‌عنوان نهایی‌سازی‌شده نشانه‌گذاری نشده باشد و تابع نهایی‌ساز tp_finalize آن غیر NULL باشد، تابع نهایی‌ساز فراخوانی می‌شود.

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

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

نهایی‌سازی خودکار به هر نهایی‌سازی‌ای اشاره دارد که توسط پایتون انجام می‌شود، به‌جز از طریق فراخوانی 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 تنظیم شود. این کار دیگر لازم نیست.

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

vectorcallfunc PyTypeObject.tp_vectorcall

The corresponding slot ID Py_tp_vectorcall is 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_add is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_subtract

The corresponding slot ID Py_nb_subtract is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_multiply

The corresponding slot ID Py_nb_multiply is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_remainder

The corresponding slot ID Py_nb_remainder is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_divmod

The corresponding slot ID Py_nb_divmod is part of the ABI پایدار.

ternaryfunc PyNumberMethods.nb_power

The corresponding slot ID Py_nb_power is part of the ABI پایدار.

unaryfunc PyNumberMethods.nb_negative

The corresponding slot ID Py_nb_negative is part of the ABI پایدار.

unaryfunc PyNumberMethods.nb_positive

The corresponding slot ID Py_nb_positive is part of the ABI پایدار.

unaryfunc PyNumberMethods.nb_absolute

The corresponding slot ID Py_nb_absolute is part of the ABI پایدار.

inquiry PyNumberMethods.nb_bool

The corresponding slot ID Py_nb_bool is part of the ABI پایدار.

unaryfunc PyNumberMethods.nb_invert

The corresponding slot ID Py_nb_invert is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_lshift

The corresponding slot ID Py_nb_lshift is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_rshift

The corresponding slot ID Py_nb_rshift is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_and

The corresponding slot ID Py_nb_and is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_xor

The corresponding slot ID Py_nb_xor is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_or

The corresponding slot ID Py_nb_or is part of the ABI پایدار.

unaryfunc PyNumberMethods.nb_int

The corresponding slot ID Py_nb_int is part of the ABI پایدار.

void *PyNumberMethods.nb_reserved
unaryfunc PyNumberMethods.nb_float

The corresponding slot ID Py_nb_float is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_add

The corresponding slot ID Py_nb_inplace_add is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_subtract

The corresponding slot ID Py_nb_inplace_subtract is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_multiply

The corresponding slot ID Py_nb_inplace_multiply is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_remainder

The corresponding slot ID Py_nb_inplace_remainder is part of the ABI پایدار.

ternaryfunc PyNumberMethods.nb_inplace_power

The corresponding slot ID Py_nb_inplace_power is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_lshift

The corresponding slot ID Py_nb_inplace_lshift is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_rshift

The corresponding slot ID Py_nb_inplace_rshift is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_and

The corresponding slot ID Py_nb_inplace_and is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_xor

The corresponding slot ID Py_nb_inplace_xor is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_or

The corresponding slot ID Py_nb_inplace_or is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_floor_divide

The corresponding slot ID Py_nb_floor_divide is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_true_divide

The corresponding slot ID Py_nb_true_divide is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_floor_divide

The corresponding slot ID Py_nb_inplace_floor_divide is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_inplace_true_divide

The corresponding slot ID Py_nb_inplace_true_divide is part of the ABI پایدار.

unaryfunc PyNumberMethods.nb_index

The corresponding slot ID Py_nb_index is part of the ABI پایدار.

binaryfunc PyNumberMethods.nb_matrix_multiply

The corresponding slot ID Py_nb_matrix_multiply is part of the ABI پایدار از نسخه‌ی 3.5.

binaryfunc PyNumberMethods.nb_inplace_matrix_multiply

The corresponding slot ID Py_nb_inplace_matrix_multiply is part of the ABI پایدار از نسخه‌ی 3.5.

ساختارهای شیء نگاشت

type PyMappingMethods

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

lenfunc PyMappingMethods.mp_length

The corresponding slot ID Py_mp_length is part of the ABI پایدار.

این تابع توسط PyMapping_Size() و PyObject_Size() استفاده می‌شود و همان امضا را دارد. اگر شیء طول تعریف‌شده‌ای نداشته باشد، این جایگاه می‌تواند به NULL تنظیم شود.

binaryfunc PyMappingMethods.mp_subscript

The corresponding slot ID Py_mp_subscript is 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_subscript is 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_length is part of the ABI پایدار.

این تابع توسط PySequence_Size() و PyObject_Size() استفاده می‌شود و امضای یکسانی دارد. همچنین برای مدیریت اندیس‌های منفی از طریق جایگاه‌های sq_item و sq_ass_item از آن استفاده می‌شود.

binaryfunc PySequenceMethods.sq_concat

The corresponding slot ID Py_sq_concat is part of the ABI پایدار.

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

ssizeargfunc PySequenceMethods.sq_repeat

The corresponding slot ID Py_sq_repeat is part of the ABI پایدار.

این تابع توسط PySequence_Repeat() استفاده می‌شود و امضای یکسانی دارد. عملگر * نیز پس از تلاش برای ضرب عددی از طریق جایگاه nb_multiply از این تابع استفاده می‌کند.

ssizeargfunc PySequenceMethods.sq_item

The corresponding slot ID Py_sq_item is 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_item is part of the ABI پایدار.

این تابع توسط PySequence_SetItem() استفاده می‌شود و همان امضا را دارد. این تابع همچنین پس از تلاش برای انجام انتساب و حذف آیتم از طریق جایگاه mp_ass_subscript، توسط PyObject_SetItem() و PyObject_DelItem() استفاده می‌شود. اگر شیء از انتساب و حذف آیتم پشتیبانی نکند، می‌توان این جایگاه را NULL گذاشت.

objobjproc PySequenceMethods.sq_contains

The corresponding slot ID Py_sq_contains is part of the ABI پایدار.

این تابع ممکن است توسط PySequence_Contains() استفاده شود و همان امضا را دارد. می‌توان این جایگاه را NULL گذاشت؛ در این صورت PySequence_Contains() صرفاً دنباله را پیمایش می‌کند تا زمانی که مورد منطبقی بیابد.

binaryfunc PySequenceMethods.sq_inplace_concat

The corresponding slot ID Py_sq_inplace_concat is 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_repeat is 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_getbuffer is part of the ABI پایدار از نسخه‌ی 3.11.

امضای این تابع به این صورت است:

int (PyObject *exporter, Py_buffer *view, int flags);

درخواستی به exporter برای پر کردن view مطابق با flags را مدیریت می‌کند. به‌جز مورد (۳)، پیاده‌سازی این تابع باید این گام‌ها را بردارد:

  1. بررسی کنید که آیا درخواست قابل برآوردن است یا خیر. در غیر این صورت، استثنای BufferError را ایجاد کنید، view->obj را برابر NULL قرار دهید و -1 را برگردانید.

  2. فیلد‌های درخواستی را پر کنید.

  3. شمارنده‌ی داخلی تعداد اکسپورت را افزایش می‌دهد.

  4. مقدار view->obj را برابر exporter قرار دهید و view->obj را افزایش دهید.

  5. 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_releasebuffer is part of the ABI پایدار از نسخه‌ی 3.11.

امضای این تابع به این صورت است:

void (PyObject *exporter, Py_buffer *view);

درخواست آزاد کردن منابع بافر را مدیریت می‌کند. اگر هیچ منبعی نیاز به آزاد شدن نداشته باشد، PyBufferProcs.bf_releasebuffer می‌تواند NULL باشد. در غیر این صورت، یک پیاده‌سازی استاندارد از این تابع گام‌های اختیاری زیر را برمی‌دارد:

  1. شمارنده داخلی تعداد اکسپورت‌هارا را کاهش دهید.

  2. اگر شمارنده 0 باشد، تمام حافظه‌ی مرتبط با view را آزاد کنید.

نخ‌ایمنی:

در free-threaded build:

  • کاهش شمارنده‌ی اکسپورت در گام (۱) باید اتمیک باشد.

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

اکسپورتکننده باید از فیلد 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_await is 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_aiter is 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_anext is part of the ABI پایدار از نسخه‌ی 3.5.

امضای این تابع به این صورت است:

PyObject *am_anext(PyObject *self);

باید یک شیء انتظارپذیر برگرداند. برای جزئیات به __anext__() مراجعه کنید. این جایگاه می‌تواند به NULL تنظیم شود.

sendfunc PyAsyncMethods.am_send

The corresponding slot ID Py_am_send is 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 void (*freefunc)(void*)

به tp_free مراجعه کنید.

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 PySendResult (*sendfunc)(PyObject*, PyObject*, PyObject**)

به am_send مراجعه کنید.

typedef PyObject *(*ternaryfunc)(PyObject*, 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 *),
};