قسمتی از ABI پایدار.تابع پیمایش برای یک شیء جمعآوریشده در زبالهجمعکن، که توسط زبالهجمعکن برای تشخیص چرخههای ارجاع استفاده میشود. پیادهسازیها باید تابع visit را برای هر شیء که مستقیماً توسط self دربرگرفته شده است فراخوانی کنند، به طوری که پارامترهای ارسالی به visit شامل شیء محصورشده و مقدار arg ارسالشده به هندلر باشند. تابع visit نباید با یک آرگومان شیء NULL فراخوانی شود. اگر visit یک مقدار غیرصفر برگرداند، آن مقدار باید بلافاصله بازگردانده شود.
یک تابع tp_traverse معمولی، ماکروی کمکی Py_VISIT() را روی هر یک از اعضای نمونه فراخوانی میکند که از اشیای پایتون متعلق به نمونه هستند. برای نمونه، این یک تابع پیمایش (کمی قدیمیشده) برای کلاس threading.local است:
static int
local_traverse(PyObject *op, visitproc visit, void *arg)
{
localobject *self = (localobject *) op;
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->args);
Py_VISIT(self->kw);
Py_VISIT(self->dict);
return 0;
}
نکته
تابع Py_VISIT() ایجاب میکند که پارامترهای visit و arg در تابع local_traverse() دارای این نامهای مشخص باشند؛ آنها را با هر نام دلخواهی نامگذاری نکنید.
نمونههای انواع تخصیصیافته در هیپ ارجاعی به نوع خود را نگهداری میکنند. بنابراین تابع پیمایش آنها باید نوع را بازدید کند:
بهعنوان جایگزین، نوع ممکن است با فراخوانی tp_traverse از یک سوپرکلاس تخصیصیافته در هیپ (یا یک نوع تخصیصیافتهی دیگر در هیپ، در صورت لزوم)، این مسئولیت را واگذار کند. اگر این کار را نکنند، ممکن است شیء نوع زبالهروبی نشود.
اگر بیت Py_TPFLAGS_MANAGED_DICT در فیلد tp_flags تنظیم شده باشد، تابع پیمایش باید تابع PyObject_VisitManagedDict() را به این شکل فراخوانی کند:
int err = PyObject_VisitManagedDict((PyObject*)self, visit, arg);
if (err) {
return err;
}
فقط اعضایی که نمونه آنها را دارد (با داشتن ارجاعهای قوی به آنها) باید بازدید شوند. برای نمونه، اگر یک شیء از طریق جایگاه tp_weaklist از ارجاعهای ضعیف پشتیبانی کند، اشارهگری که از فهرست پیوندی پشتیبانی میکند (چیزی که tp_weaklist به آن اشاره میکند) نباید بازدید شود، زیرا نمونه مستقیماً مالک ارجاعهای ضعیف به خودش نیست.
تابع پیمایش محدودیتی دارد:
هشدار
تابع پیمایش نباید هیچ اثر جانبی داشته باشد. پیادهسازیها نباید شمارههای ارجاع هیچیک از اشیای پایتون را تغییر دهند و همچنین نباید هیچ شیء پایتونی را، به صورت مستقیم یا غیرمستقیم، ایجاد یا نابود کنند.
این یعنی بیشتر توابع C API پایتون ممکن است استفاده نشوند، زیرا میتوانند یک استثنای جدید ایجاد کنند، یک ارجاع جدید به یک شیء نتیجه را برگردانند، یا منطق داخلی داشته باشند که از عوارض جانبی استفاده میکند. همچنین، مگر اینکه طور دیگری مستند شده باشد، توابعی که عوارض جانبی ندارند ممکن است در نسخههای آینده بدون هشدار پیدا کردن عوارض جانبی را شروع کنند.
برای فهرستی از توابع امن، به بخش جداگانه در ادامه مراجعه کنید.
If an error occurs during traversal, ignore it and return 0.
If tp_traverse fails to visit some strong references, garbage reference
cycles involving the skipped references will not be reliably broken,
but correctness won't be affected.
For example, if traversal requires a lock that cannot be acquired promptly,
skip the traversal.
The garbage collector will visit your object again in a future pass.
نکته
فراخوانی Py_VISIT() را میتوان برای آن دسته از اعضایی که ثابت شده نمیتوانند در چرخههای ارجاع شرکت کنند، رد کرد. در نمونهی local_traverse در بالا، یک عضو self->key نیز وجود دارد، اما این عضو فقط میتواند NULL یا یک رشتهی پایتون باشد و بنابراین نمیتواند بخشی از یک چرخه ارجاع باشد.
از سوی دیگر، حتی اگر میدانید که یک عضو هرگز نمیتواند بخشی از یک چرخه باشد، به عنوان یک ابزار کمکی برای اشکالزدایی ممکن است بخواهید به هر حال آن را بازدید کنید تا تابع get_referents() در ماژول gc آن را در بر بگیرد.
نکته
تابع tp_traverse را میتوان از هر نخی فراخوانی کرد.
زبالهروبی یک عملیات «متوقفکنندهی دنیا» است: حتی در پیادهسازیهای دارای نخبندی آزاد، هنگامی که کنترلکنندههای tp_traverse اجرا میشوند، فقط یک حالت نخ متصل است.
تغییر یافته در نسخهی 3.9: انتظار میرود انواع تخصیصیافته در هیپ، Py_TYPE(self) را در tp_traverse بازدید کنند. در نسخههای قبلی پایتون، به دلیل bug 40217، انجام این کار ممکن است منجر به فروپاشی در زیرکلاسها شود.