reprlib --- پیاده‌سازی جایگزین repr()

کد منبع: Lib/reprlib.py


ماژول reprlib وسیله‌ای برای تولید بازنمایی‌های شیء با محدودیت روی اندازه‌ی رشته‌های حاصل فراهم می‌کند. این امکان در اشکال‌زدای پایتون استفاده می‌شود و ممکن است در زمینه‌های دیگر نیز مفید باشد.

این ماژول یک کلاس، یک نمونه و یک تابع را فراهم می‌کند:

class reprlib.Repr(*, maxlevel=6, maxtuple=6, maxlist=6, maxarray=5, maxdict=4, maxset=6, maxfrozenset=6, maxdeque=6, maxstring=30, maxlong=40, maxother=30, fillvalue='...', indent=None)

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

می‌توان از آرگومان‌های کلیدواژه‌ای سازنده به‌عنوان میان‌بری برای تنظیم ویژگی‌های نمونه‌ی Repr استفاده کرد. این بدان معناست که مقداردهی اولیه‌ی زیر:

aRepr = reprlib.Repr(maxlevel=3)

معادل است با:

aRepr = reprlib.Repr()
aRepr.maxlevel = 3

برای اطلاعات بیشتر درباره ویژگی‌های Repr، بخش Repr Objects را ببینید.

تغییر یافته در نسخه‌ی 3.12: امکان تنظیم ویژگی‌ها از طریق آرگومان‌های کلیدواژه‌ای را فراهم می‌کند.

reprlib.aRepr

این نمونه‌ای از Repr است که برای فراهم کردن تابع repr() که در زیر توضیح داده شده است، استفاده می‌شود. تغییر ویژگی‌های این شیء بر محدودیت‌های اندازه‌ای که repr() و اشکال‌زدای پایتون از آن‌ها استفاده می‌کنند، تأثیر خواهد گذاشت.

reprlib.repr(obj)

این متد repr() از aRepr است. این متد رشته‌ای مشابه رشته‌ی برگردانده‌شده توسط تابع توکار هم‌نام برمی‌گرداند، اما با محدودیت‌هایی در بیشتر اندازه‌ها.

علاوه بر ابزارهای محدودکننده‌ی اندازه، این ماژول همچنین یک دکوراتور برای تشخیص فراخوانی‌های بازگشتی به __repr__() و جایگزین کردن یک رشته‌ی جای‌نگهدار به‌جای آن ارائه می‌دهد.

@reprlib.recursive_repr(fillvalue='...')

دکوراتوری برای متدهای __repr__() جهت تشخیص فراخوانی‌های بازگشتی در همان نخ. اگر فراخوانی بازگشتی انجام شود، fillvalue برگردانده می‌شود، در غیر این صورت، فراخوانی معمول __repr__() انجام می‌شود. برای مثال:

>>> from reprlib import recursive_repr
>>> class MyList(list):
...     @recursive_repr()
...     def __repr__(self):
...         return '<' + '|'.join(map(repr, self)) + '>'
...
>>> m = MyList('abc')
>>> m.append(m)
>>> m.append('x')
>>> print(m)
<'a'|'b'|'c'|...|'x'>

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

اشیای Repr

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

Repr.fillvalue

این رشته برای ارجاعات بازگشتی نمایش داده می‌شود. مقدار پیش‌فرض آن ... است.

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

Repr.maxlevel

محدودیت عمق در ایجاد بازنمایی‌های بازگشتی. مقدار پیش‌فرض 6 است.

Repr.maxdict
Repr.maxlist
Repr.maxtuple
Repr.maxset
Repr.maxfrozenset
Repr.maxdeque
Repr.maxarray

محدودیت‌های تعداد آیتم‌های بازنمایی‌شده برای نوع شیء نام‌برده‌شده. مقدار پیش‌فرض برای maxdict برابر 4، برای maxarray برابر 5 و برای سایر موارد برابر 6 است.

Repr.maxlong

حداکثر تعداد نویسه‌ها در بازنمایی یک عدد صحیح. ارقام از میانه حذف می‌شوند. مقدار پیش‌فرض 40 است.

Repr.maxstring

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

Repr.maxother

این محدودیت برای کنترل اندازه‌ی انواع شیءهایی به کار می‌رود که هیچ متد قالب‌بندی مشخصی برای آن‌ها در شیء Repr در دسترس نیست. این محدودیت به شیوه‌ای مشابه maxstring اعمال می‌شود. مقدار پیش‌فرض 20 است.

Repr.indent

اگر این ویژگی روی None تنظیم شده باشد (پیش‌فرض)، خروجی بدون شکست خط یا تورفتگی قالب‌بندی می‌شود، مانند repr() استاندارد. برای مثال:

>>> example = [
...     1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham']
>>> import reprlib
>>> aRepr = reprlib.Repr()
>>> print(aRepr.repr(example))
[1, 'spam', {'a': 2, 'b': 'spam eggs', 'c': {3: 4.5, 6: []}}, 'ham']

اگر indent روی یک رشته تنظیم شود، هر سطح بازگشت در خط خودش قرار می‌گیرد و با آن رشته تورفتگی داده می‌شود:

>>> aRepr.indent = '-->'
>>> print(aRepr.repr(example))
[
-->1,
-->'spam',
-->{
-->-->'a': 2,
-->-->'b': 'spam eggs',
-->-->'c': {
-->-->-->3: 4.5,
-->-->-->6: [],
-->-->},
-->},
-->'ham',
]

اگر indent را به یک مقدار عدد صحیح مثبت تنظیم کنید، به‌گونه‌ای رفتار می‌کند که گویی به رشته‌ای با آن تعداد فاصله تنظیم شده باشد:

>>> aRepr.indent = 4
>>> print(aRepr.repr(example))
[
    1,
    'spam',
    {
        'a': 2,
        'b': 'spam eggs',
        'c': {
            3: 4.5,
            6: [],
        },
    },
    'ham',
]

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

Repr.repr(obj)

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

Repr.repr1(obj, level)

پیاده‌سازی بازگشتی که توسط repr() استفاده می‌شود. این پیاده‌سازی از نوع obj برای تعیین متد قالب‌بندی مناسب جهت فراخوانی استفاده می‌کند و obj و level را به آن منتقل می‌کند. متدهای مخصوص نوع باید برای انجام قالب‌بندی بازگشتی، repr1() را فراخوانی کنند و در فراخوانی بازگشتی، level - 1 را به‌عنوان مقدار level استفاده کنند.

Repr.repr_TYPE(obj, level)

متدهای قالب‌بندی برای انواع خاص به‌صورت متدهایی با نامی مبتنی بر نام نوع پیاده‌سازی شده‌اند. در نام متد، TYPE با '_'.join(type(obj).__name__.split()) جایگزین می‌شود. اعزام (dispatch) به این متدها توسط repr1() مدیریت می‌شود. متدهای مختص به نوعی که نیاز دارند یک مقدار را به‌صورت بازگشتی قالب‌بندی کنند، باید self.repr1(subobj, level - 1) را فراخوانی کنند.

زیرکلاس‌سازی اشیاء Repr

استفاده از اعزام پویا (dynamic dispatching) توسط Repr.repr1() به زیرکلاس‌های Repr اجازه می‌دهد پشتیبانی از انواع بیشتری از اشیای توکار را اضافه کنند یا مدیریت انواع از پیش پشتیبانی‌شده را تغییر دهند. این مثال نشان می‌دهد که چگونه می‌توان پشتیبانی ویژه‌ای برای اشیای پرونده اضافه کرد:

import reprlib
import sys

class MyRepr(reprlib.Repr):

    def repr_TextIOWrapper(self, obj, level):
        if obj.name in {'<stdin>', '<stdout>', '<stderr>'}:
            return obj.name
        return repr(obj)

aRepr = MyRepr()
print(aRepr.repr(sys.stdin))         # prints '<stdin>'
<stdin>