تازه‌های پایتون 2.4

نویسنده:

A.M. Kuchling

این مقاله ویژگی‌های جدید پایتون 2.4.1 را که در تاریخ ۳۰ مارس ۲۰۰۵ منتشر شده است، توضیح می‌دهد.

پایتون 2.4 نسخه‌ای با حجم متوسط است. این نسخه به اندازه‌ی پایتون 2.2 که نسخه‌ای رادیکال بود، تغییرات زیادی معرفی نمی‌کند، اما ویژگی‌های بیشتری نسبت به نسخه‌ی محافظه‌کارانه‌ی 2.3 معرفی می‌کند. مهم‌ترین ویژگی‌های جدید زبان، دکوراتورهای تابع و عبارت‌های تولیدگر هستند؛ بیشتر تغییرات دیگر مربوط به کتابخانه‌ی استاندارد است.

بر اساس گزارش‌های تغییرات CVS، بین پایتون 2.3 و 2.4 تعداد ۴۸۱ وصل اعمال شد و ۵۰۲ اشکال رفع شد. هر دو رقم احتمالاً دست‌کم گرفته شده‌اند.

این مقاله تلاش نمی‌کند مشخصات کامل تک‌تک ویژگی‌های جدید را ارائه دهد، بلکه در عوض برای هر ویژگی مقدمه‌ای کوتاه فراهم می‌کند. برای جزئیات کامل، باید به مستندات پایتون 2.4، مانند مرجع کتابخانه پایتون و راهنمای مرجع پایتون، مراجعه کنید. اغلب برای توضیح پیاده‌سازی و منطق طراحی، به PEP مربوط به ویژگی جدید مورد نظر ارجاع داده خواهید شد.

PEP 218: اشیاء مجموعه توکار

پایتون 2.3 ماژول sets را معرفی کرد. پیاده‌سازی‌های C از نوع‌های داده‌ی مجموعه اکنون به‌عنوان دو نوع توکار جدید، set(iterable) و frozenset(iterable)، به هسته‌ی پایتون افزوده‌شده‌اند. این نوع‌ها عملیات پرسرعتی را برای آزمون عضویت، حذف موارد تکراری از دنباله‌ها و عملیات ریاضی مانند اجتماع، اشتراک، تفاضل و تفاضل متقارن فراهم می‌کنند.

>>> a = set('abracadabra')              # form a set from a string
>>> 'z' in a                            # fast membership testing
False
>>> a                                   # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a)                          # convert back into a string
'arbcd'

>>> b = set('alacazam')                 # form a second set
>>> a - b                               # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b                               # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b                               # letters in both a and b
set(['a', 'c'])
>>> a ^ b                               # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])

>>> a.add('z')                          # add a new element
>>> a.update('wxy')                     # add multiple new elements
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x')                       # take one element out
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])

نوع frozenset() نسخه‌ای تغییرناپذیر از set() است. از آنجا که تغییرناپذیر و هش‌پذیر است، می‌توان از آن به‌عنوان کلید دیکشنری یا عضوی از مجموعه‌ای دیگر استفاده کرد.

ماژول sets در کتابخانه استاندارد باقی می‌ماند و ممکن است در صورتی که بخواهید از کلاس‌های Set یا ImmutableSet زیرکلاس بسازید، مفید باشد. در حال حاضر هیچ برنامه‌ای برای منسوخ کردن این ماژول وجود ندارد.

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

PEP 218 - افزودن نوع شیء مجموعه توکار

در ابتدا توسط Greg Wilson پیشنهاد شد و در نهایت توسط Raymond Hettinger پیاده‌سازی شد.

PEP 237: یکسان‌سازی اعداد صحیح بلند و اعداد صحیح

فرایند گذار طولانی این PEP، که از پایتون 2.2 آغاز شده بود، در پایتون 2.4 گامی دیگر به پیش برمی‌دارد. در نسخه 2.3، برخی عملیات اعداد صحیح که پس از یکپارچه‌سازی int/long رفتار متفاوتی می‌داشتند، هشدارهای FutureWarning ایجاد می‌کردند و مقادیری محدود به ۳۲ یا ۶۴ بیت (بسته به پلتفرم شما) برمی‌گرداندند. در نسخه 2.4، این عبارت‌ها دیگر هشداری تولید نمی‌کنند و در عوض نتیجه‌ای متفاوت تولید می‌کنند که معمولاً یک عدد صحیح بلند است.

عبارت‌های مشکل‌ساز عمدتاً شیفت‌های به چپ و ثابت‌های طولانی مبنای شانزده و مبنای هشت هستند. برای مثال، 2 << 32 در 2.3 هشدار می‌دهد و روی پلتفرم‌های ۳۲ بیتی به ۰ ارزیابی می‌شود. در پایتون 2.4، این عبارت اکنون پاسخ صحیح یعنی ۸۵۸۹۹۳۴۵۹۲ را برمی‌گرداند.

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

PEP 237 - یکسان‌سازی اعداد صحیح بلند و اعداد صحیح

PEP اصلی توسط موشه زادکا و GvR نوشته شد. تغییرات نسخه‌ی 2.4 توسط کاله سونسون پیاده‌سازی شد.

PEP 289: عبارت‌های تولیدگر

قابلیت پیمایش‌گر معرفی‌شده در پایتون 2.2 و ماژول itertools نوشتن برنامه‌هایی را آسان‌تر می‌کنند که با حلقه از میان مجموعه داده‌های بزرگ عبور می‌کنند، بدون آنکه کل مجموعه داده در آن واحد در حافظه باشد. درک‌های فهرستی چندان در این تصویر جا نمی‌گیرند، زیرا یک شیء فهرست پایتون تولید می‌کنند که همه‌ی آیتم‌ها را در بر دارد. این کار به‌ناچار همه‌ی اشیاء را به حافظه می‌کشد، که اگر مجموعه داده شما بسیار بزرگ باشد، می‌تواند مشکل‌ساز باشد. هنگام تلاش برای نوشتن برنامه‌ای به سبک تابعی، طبیعی است که چیزی شبیه به این بنویسید:

links = [link for link in get_all_links() if not link.followed]
for link in links:
    ...

به‌جای

for link in get_all_links():
    if link.followed:
        continue
    ...

شکل اول مختصرتر و شاید هم خواناتر است، اما اگر با تعداد زیادی شیء پیوند سروکار دارید، باید شکل دوم را بنویسید تا از قرار گرفتن همه‌ی اشیاء پیوند به‌طور همزمان در حافظه جلوگیری کنید.

عبارت‌های تولیدگر مشابه درک‌های فهرستی کار می‌کنند، اما کل فهرست را به‌طور کامل ایجاد نمی‌کنند؛ در عوض، یک تولیدگر می‌سازند که عناصر را یکی‌یکی برمی‌گرداند. مثال بالا را می‌توان به این صورت نوشت:

links = (link for link in get_all_links() if not link.followed)
for link in links:
    ...

عبارت‌های تولیدگر همیشه باید داخل پرانتز نوشته شوند، همان‌طور که در مثال بالا آمده است. پرانتزهایی که فراخوانی تابع را نشان می‌دهند نیز به حساب می‌آیند، بنابراین اگر بخواهید پیمایش‌گری بسازید که بلافاصله به یک تابع پاس داده شود، می‌توانید بنویسید:

print sum(obj.count for obj in list_all_objects())

عبارت‌های تولیدگر از درک‌های فهرستی در جنبه‌های کوچک گوناگونی تفاوت دارند. چشمگیرترین تفاوت این است که متغیر حلقه (obj در مثال بالا) خارج از عبارت تولیدگر قابل دسترسی نیست. درک‌های فهرستی متغیر را به آخرین مقدارش منتسب باقی می‌گذارند؛ نسخه‌های آینده پایتون این رفتار را تغییر خواهند داد تا درک‌های فهرستی از این نظر با عبارت‌های تولیدگر مطابقت داشته باشند.

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

PEP 289 - عبارت‌های تولیدگر

پیشنهادشده توسط Raymond Hettinger و پیاده‌سازی‌شده توسط Jiwon Seo، با هدایت تلاش‌های اولیه توسط Hye-Shik Chang.

PEP 292: جایگزینی ساده‌تر در رشته‌ها

برخی از کلاس‌های جدید در کتابخانه استاندارد، سازوکاری جایگزین برای جایگزینی متغیرها در رشته‌ها فراهم می‌کنند؛ این سبک از جایگزینی ممکن است برای برنامه‌هایی که کاربران بدون آموزش باید قالب‌هایشان را ویرایش کنند، بهتر باشد.

روش معمول برای جایگزینی نام‌محور متغیرها، عملگر % است:

>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}
'2: The Best of Times'

هنگام نوشتن رشته قالب، به‌سادگی می‌توان i یا s را پس از پرانتز بسته فراموش کرد. اگر قالب درون یک ماژول پایتون باشد، این مشکل بزرگی نیست، زیرا کد را اجرا می‌کنید، یک ValueError با پیام «Unsupported format character» دریافت می‌کنید و مشکل را برطرف می‌کنید. اما برنامه‌ای مانند Mailman را در نظر بگیرید که در آن رشته‌های قالب یا ترجمه‌ها توسط کاربرانی ویرایش می‌شوند که با زبان پایتون آشنایی ندارند. توضیح سینتکس رشته قالب‌بندی به چنین کاربرانی پیچیده است و اگر اشتباهی کنند، ارائه بازخورد مفید به آن‌ها دشوار است.

PEP 292 کلاس Template را به ماژول string اضافه می‌کند که از $ برای نشان دادن جایگزینی استفاده می‌کند:

>>> import string
>>> t = string.Template('$page: $title')
>>> t.substitute({'page':2, 'title': 'The Best of Times'})
'2: The Best of Times'

اگر کلیدی در دیکشنری موجود نباشد، متد substitute() استثنای KeyError را ایجاد می‌کند. متد safe_substitute() نیز وجود دارد که کلیدهای مفقود را نادیده می‌گیرد:

>>> t = string.Template('$page: $title')
>>> t.safe_substitute({'page':3})
'3: $title'

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

PEP 292 - جایگزینی ساده‌تر رشته‌ها

توسط Barry Warsaw نوشته و پیاده‌سازی شده است.

PEP 318: دکوراتورها برای توابع و متدها

پایتون 2.2 مدل شیء پایتون را با افزودن متدهای ایستا و متدهای کلاس گسترش داد، اما سینتکس پایتون را برای ارائه‌ی هیچ روش جدیدی برای تعریف متدهای ایستا یا متدهای کلاس گسترش نداد. در عوض، باید دستور def را به شیوه‌ی معمول می‌نوشتید و متد حاصل را به تابع staticmethod() یا classmethod() پاس می‌دادید که تابع را به‌عنوان متدی از نوع جدید پوشش می‌داد. کد شما به این شکل بود:

class C:
   def meth (cls):
       ...

   meth = classmethod(meth)   # Rebind name to wrapped-up class method

اگر متد بسیار طولانی بود، به‌راحتی ممکن بود فراخوانی classmethod() را پس از بدنه تابع نادیده بگیرید یا فراموش کنید.

قصد همیشه این بود که نحوی برای خواناتر کردن چنین تعریف‌هایی افزوده شود، اما در زمان انتشار نسخه‌ی 2.2، سینتکس خوبی بدیهی نبود. امروز نیز هنوز سینتکس خوبی بدیهی نیست، اما کاربران خواستار دسترسی آسان‌تر به این قابلیت هستند؛ برای برآورده کردن این نیاز، قابلیت نحوی جدیدی افزوده شده است.

این ویژگی جدید «آراینده‌های تابع» نامیده می‌شود. این نام از ایده‌ای سرچشمه می‌گیرد که classmethod()، staticmethod() و مشابه‌های آن‌ها اطلاعات اضافی را روی یک شیء تابع ذخیره می‌کنند؛ آن‌ها توابع را با جزئیات بیشتر می‌آرایند.

نمادگذاری از جاوا وام گرفته شده و از نویسه '@' به‌عنوان نشانگر استفاده می‌کند. با استفاده از سینتکس جدید، مثال بالا به صورت زیر نوشته می‌شود:

class C:

   @classmethod
   def meth (cls):
       ...

@classmethod اختصاری برای انتساب meth=classmethod(meth) است. به‌طور کلی‌تر، اگر موارد زیر را داشته باشید:

@A
@B
@C
def f ():
    ...

این معادل کد پیش از دکوراتور زیر است:

def f(): ...
f = A(B(C(f)))

دکوراتورها باید در سطر قبل از تعریف تابع قرار بگیرند، یک دکوراتور در هر سطر، و نمی‌توانند در همان سطر دستور def باشند؛ یعنی @A def f(): ... غیرمجاز است. شما فقط می‌توانید تعریف‌های تابع را دکوراتور کنید، چه در سطح ماژول و چه درون یک کلاس؛ نمی‌توانید تعریف‌های کلاس را دکوراتور کنید.

دکوراتور چیزی نیست جز تابعی که تابعی را که قرار است دکوره شود به‌عنوان آرگومان می‌گیرد و همان تابع یا شیء جدیدی را برمی‌گرداند. مقدار بازگشتی دکوراتور لازم نیست فراخوانی‌پذیر باشد (هرچند معمولاً چنین است)، مگر آنکه دکوراتورهای بیشتری روی نتیجه اعمال شوند. نوشتن دکوراتورهای خودتان آسان است. مثال ساده‌ی زیر صرفاً یک ویژگی را روی شیء تابع تنظیم می‌کند:

>>> def deco(func):
...    func.attr = 'decorated'
...    return func
...
>>> @deco
... def f(): pass
...
>>> f
<function f at 0x402ef0d4>
>>> f.attr
'decorated'
>>>

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

def require_int (func):
    def wrapper (arg):
        assert isinstance(arg, int)
        return func(arg)

    return wrapper

@require_int
def p1 (arg):
    print arg

@require_int
def p2(arg):
    print arg*2

نمونه‌ای در PEP 318 نسخه‌ای پیشرفته‌تر از این ایده را در بر می‌گیرد که به شما امکان می‌دهد هم نوع مورد نیاز را مشخص کنید و هم نوع بازگشتی را بررسی کنید.

توابع دکوراتور می‌توانند آرگومان بپذیرند. اگر آرگومان‌هایی ارائه شوند، تابع دکوراتور شما فقط با همان آرگومان‌ها فراخوانی می‌شود و باید یک تابع دکوراتور جدید برگرداند؛ این تابع باید یک تابع واحد را بپذیرد و تابعی برگرداند، همان‌طور که پیش‌تر توضیح داده شد. به عبارت دیگر، @A @B @C(args) تبدیل می‌شود به:

def f(): ...
_deco = C(args)
f = A(B(_deco(f)))

درست انجام دادن این کار ممکن است کمی ذهن را درگیر کند، اما زیاد دشوار نیست.

یک تغییر کوچک مرتبط، ویژگی func_name توابع را قابل نوشتن می‌کند. این ویژگی برای نمایش نام توابع در ردگیری‌ها استفاده می‌شود، بنابراین دکوراتورها باید نام هر تابع جدیدی را که ساخته و بازگردانده می‌شود تغییر دهند.

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

PEP 318 - دکوراتورها برای توابع، متدها و کلاس‌ها

نوشته‌شده توسط Kevin D. Smith، Jim Jewett و Skip Montanaro. چندین نفر وصل‌هایی برای پیاده‌سازی دکوراتورهای تابع نوشتند، اما وصلی که در نهایت در مخزن ثبت شد، وصل #979728 بود که توسط Mark Russell نوشته شده بود.

https://wiki.python.org/moin/PythonDecoratorLibrary

این صفحه‌ی ویکی شامل چندین نمونه از دکوراتورها است.

PEP 322: پیمایش معکوس

یک تابع توکار جدید، reversed(seq)، یک دنباله را می‌گیرد و پیمایش‌گری برمی‌گرداند که عناصر دنباله را به ترتیب معکوس پیمایش می‌کند.

>>> for i in reversed(xrange(1,4)):
...    print i
...
3
2
1

در مقایسه با اسلایس توسعه‌یافته، مانند range(1,4)[::-1]، reversed() خواناتر است، سریع‌تر اجرا می‌شود و حافظه به‌مراتب کمتری استفاده می‌کند.

توجه داشته باشید که reversed() فقط دنباله‌ها را می‌پذیرد، نه پیمایش‌گرهای دلخواه. اگر می‌خواهید یک پیمایش‌گر را معکوس کنید، ابتدا آن را با list() به یک فهرست تبدیل کنید.

>>> input = open('/etc/passwd', 'r')
>>> for line in reversed(list(input)):
...   print line
...
root:*:0:0:System Administrator:/var/root:/bin/tcsh
  ...

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

PEP 322 - پیمایش معکوس

نوشته و پیاده‌سازی‌شده توسط ریموند هتینگر.

PEP 324: ماژول جدید subprocess

کتابخانه استاندارد روش‌های متعددی برای اجرای یک زیرفرایند ارائه می‌دهد که قابلیت‌ها و سطوح پیچیدگی متفاوتی دارند. استفاده از os.system(command) آسان است، اما کند است (یک فرایند پوسته اجرا می‌کند که دستور را اجرا می‌کند) و خطرناک است (باید مراقب خنثی کردن فرانویسه‌های پوسته باشید). ماژول popen2 کلاس‌هایی ارائه می‌دهد که می‌توانند خروجی استاندارد و خطای استاندارد را از زیرفرایند بگیرند، اما نام‌گذاری آن سردرگم‌کننده است. ماژول subprocess این آشفتگی را برطرف می‌کند و با ارائه رابطی یکپارچه، همه قابلیت‌هایی را که ممکن است به آن‌ها نیاز داشته باشید فراهم می‌آورد.

به‌جای مجموعه‌ی کلاس‌های popen2، ماژول subprocess تنها شامل یک کلاس به نام subprocess.Popen است که سازنده‌ی آن از تعدادی آرگومان کلیدواژه‌ای مختلف پشتیبانی می‌کند.

class Popen(args, bufsize=0, executable=None,
            stdin=None, stdout=None, stderr=None,
            preexec_fn=None, close_fds=False, shell=False,
            cwd=None, env=None, universal_newlines=False,
            startupinfo=None, creationflags=0):

args معمولاً دنباله‌ای از رشته‌ها است که آرگومان‌های برنامه‌ی اجرا‌شده به‌عنوان زیرفرایند خواهند بود. (اگر آرگومان shell درست باشد، args می‌تواند یک رشته باشد که آن‌گاه برای تفسیر به پوسته سپرده می‌شود، دقیقاً همان‌طور که os.system() انجام می‌دهد.)

stdin، stdout و stderr تعیین می‌کنند که جریان‌های ورودی، خروجی و خطای زیرفرایند چه خواهند بود. شما می‌توانید یک شیء پرونده یا یک توصیف‌گر پرونده فراهم کنید، یا می‌توانید از ثابت subprocess.PIPE برای ایجاد یک پایپ بین زیرفرایند و والد استفاده کنید.

سازنده تعدادی گزینه‌ی کاربردی دارد:

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

  • cwd پوشه کاری‌ای را مشخص می‌کند که زیرفرایند در آن اجرا خواهد شد (به‌طور پیش‌فرض، همان پوشه کاری فرایند والد).

  • env یک دیکشنری است که متغیرهای محیطی را مشخص می‌کند.

  • preexec_fn تابعی است که پیش از راه‌اندازی فرزند فراخوانی می‌شود.

  • universal_newlines ورودی و خروجی فرزند را با استفاده از قابلیت سطرهای جدید همگانی پایتون باز می‌کند.

پس از ایجاد نمونه‌ی Popen، می‌توانید متد wait() آن را برای توقف تا زمانی که زیرفرایند خارج شود، poll() را برای بررسی بدون توقف اینکه آیا زیرفرایند خارج شده است یا نه، یا communicate(data) را برای ارسال رشته‌ی data به ورودی استاندارد زیرفرایند فراخوانی کنید. سپس communicate(data) هر داده‌ای را که زیرفرایند به خروجی استاندارد یا خطای استاندارد خود فرستاده است می‌خواند و تاپل (stdout_data, stderr_data) را برمی‌گرداند.

call() یک میان‌بر است که آرگومان‌های خود را به سازنده‌ی Popen پاس می‌دهد، منتظر تکمیل فرمان می‌ماند و کد وضعیت زیرفرایند را برمی‌گرداند. می‌تواند به‌عنوان معادل امن‌تری برای os.system() عمل کند:

sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
if sts == 0:
    # Success
    ...
else:
    # dpkg returned an error
    ...

فرمان بدون استفاده از پوسته فراخوانی می‌شود. اگر واقعاً می‌خواهید از پوسته استفاده کنید، می‌توانید shell=True را به‌عنوان آرگومان کلیدواژه‌ای اضافه کنید و به جای دنباله، یک رشته ارائه دهید:

sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)

این PEP مثال‌های گوناگونی از کد پوسته و پایتون را مطرح می‌کند و نشان می‌دهد که چگونه آن‌ها به کد پایتونی که از subprocess استفاده می‌کند تبدیل می‌شوند. خواندن این بخش از PEP به‌شدت توصیه می‌شود.

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

PEP 324 - subprocess - ماژول جدید فرایند

نوشته و پیاده‌سازی‌شده توسط Peter Åstrand، با کمک Fredrik Lundh و دیگران.

PEP 327: نوع داده Decimal

پایتون همیشه از اعداد ممیز شناور (FP)، که بر پایه‌ی نوع زیربنایی double در C هستند، به‌عنوان یک نوع داده پشتیبانی کرده است. با این حال، اگرچه اکثر زبان‌های برنامه‌نویسی نوع ممیز شناور را ارائه می‌دهند، بسیاری از افراد (حتی برنامه‌نویسان) از این آگاه نیستند که اعداد ممیز شناور برخی کسرهای اعشاری را به‌طور دقیق بازنمایی نمی‌کنند. نوع جدید Decimal می‌تواند این کسرها را به‌طور دقیق، تا حد دقت تعیین‌شده توسط کاربر، بازنمایی کند.

چرا به Decimal نیاز است؟

این محدودیت‌ها از نمایش استفاده‌شده برای اعداد ممیز شناور ناشی می‌شوند. اعداد ممیز شناور از سه جزء تشکیل شده‌اند:

  • علامت، که مثبت یا منفی است.

  • مانتیس (mantissa)، که عددی دودویی تک‌رقمی است و جزء کسری پس از آن می‌آید. برای مثال، 1.01 در نمادگذاری مبنای ۲ برابر است با 1 + 0/2 + 1/4، یا ۱.۲۵ در نمادگذاری ده‌دهی.

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

برای مثال، عدد ۱٫۲۵ علامت مثبت، مقدار مانتیس ۱٫۰۱ (در مبنای دودویی) و نمای ۰ دارد (ممیز نیازی به جابه‌جایی ندارد). عدد ۵ همان علامت و مانتیس را دارد، اما نما ۲ است، زیرا مانتیس در ۴ ضرب می‌شود (۲ به توان نمای ۲)؛ ۱٫۲۵ * ۴ برابر با ۵ است.

سیستم‌های مدرن معمولاً پشتیبانی از ممیز شناور را ارائه می‌دهند که با استانداردی به نام IEEE 754 مطابقت دارد. نوع double در زبان C معمولاً به‌صورت یک عدد ۶۴بیتی IEEE 754 پیاده‌سازی می‌شود که برای منتیسا (mantissa) از ۵۲ بیت فضا استفاده می‌کند. این بدان معناست که اعداد را تنها می‌توان با دقت ۵۲بیتی مشخص کرد. اگر بخواهید اعدادی را بازنمایی کنید که بسط آن‌ها بی‌پایان تکرار می‌شود، این بسط پس از ۵۲ بیت قطع می‌شود. متأسفانه، بیشتر نرم‌افزارها باید خروجی خود را در مبنای ۱۰ تولید کنند و کسرهای رایج در مبنای ۱۰ اغلب در مبنای دودویی به‌صورت اعشار تکرارشونده هستند. برای مثال، عدد اعشاری 1.1 در مبنای دودویی برابر با 1.0001100110011 ... است؛ .1 = 1/16 + 1/32 + 1/256 به‌اضافه‌ی بی‌نهایت جمله‌ی دیگر. IEEE 754 ناچار است آن عدد اعشاری تکرارشونده‌ی بی‌پایان را پس از ۵۲ رقم قطع کند، در نتیجه بازنمایی اندکی نادقیق است.

گاهی اوقات می‌توانید این عدم دقت را هنگام چاپ شدن عدد ببینید:

>>> 1.1
1.1000000000000001

عدم دقت همیشه هنگام چاپ عدد قابل مشاهده نیست، زیرا تبدیل ممیز شناور به رشته مبنای ده توسط کتابخانه C ارائه می‌شود و بیشتر کتابخانه‌های C سعی می‌کنند خروجی معقولی تولید کنند. با این حال، حتی اگر نمایش داده نشود، عدم دقت همچنان وجود دارد و عملیات‌های بعدی می‌توانند خطا را بزرگ‌تر کنند.

برای بسیاری از کاربردها این موضوع اهمیتی ندارد. اگر در حال رسم نقاط و نمایش آن‌ها روی نمایشگر خود باشم، تفاوت بین 1.1 و 1.1000000000000001 آن‌قدر کوچک است که قابل مشاهده نیست. گزارش‌ها اغلب خروجی را به تعداد مشخصی رقم اعشار محدود می‌کنند، و اگر عدد را به دو یا سه یا حتی هشت رقم اعشار گرد کنید، خطا هرگز آشکار نمی‌شود. با این حال، برای کاربردهایی که این موضوع در آن‌ها اهمیت دارد، پیاده‌سازی روال‌های محاسباتی سفارشی خودتان کار زیادی می‌طلبد.

بنابراین، نوع Decimal ایجاد شد.

نوع Decimal

یک ماژول جدید، decimal، به کتابخانه استاندارد پایتون اضافه شد. این ماژول شامل دو کلاس است: Decimal و Context. نمونه‌های Decimal اعداد را نمایش می‌دهند و نمونه‌های Context برای دربرگرفتن تنظیمات مختلفی مانند دقت و حالت گرد کردن پیش‌فرض استفاده می‌شوند.

نمونه‌های Decimal مانند اعداد صحیح معمولی پایتون و اعداد ممیز شناور تغییرناپذیر هستند؛ پس از ایجاد شدن، نمی‌توانید مقداری را که یک نمونه نمایش می‌دهد تغییر دهید. نمونه‌های Decimal می‌توانند از اعداد صحیح یا رشته‌ها ایجاد شوند:

>>> import decimal
>>> decimal.Decimal(1972)
Decimal("1972")
>>> decimal.Decimal("1.1")
Decimal("1.1")

شما همچنین می‌توانید تاپل‌هایی شامل علامت، مانتیسی که به‌صورت تاپلی از ارقام مبنای ده نمایش داده می‌شود، و نما ارائه دهید:

>>> decimal.Decimal((1, (1, 4, 7, 5), -2))
Decimal("-14.75")

نکته‌ی هشدار: بیت علامت یک مقدار بولی است، بنابراین ۰ مثبت است و ۱ منفی است.

تبدیل از اعداد ممیز شناور کمی مشکل‌آفرین است: آیا عدد ممیز شناوری که 1.1 را نشان می‌دهد، باید به عدد ده‌دهی‌ای تبدیل شود که دقیقاً 1.1 باشد، یا به 1.1 به‌علاوه‌ی هر خطاهایی که در این میان پدید می‌آید؟ تصمیم گرفته شد که از این مسئله اجتناب شود و چنین تبدیلی در API گنجانده نشود. در عوض، شما باید عدد ممیز شناور را با دقت مطلوب به یک رشته تبدیل کنید و رشته را به سازنده‌ی Decimal بدهید:

>>> f = 1.1
>>> decimal.Decimal(str(f))
Decimal("1.1")
>>> decimal.Decimal('%.12f' % f)
Decimal("1.100000000000")

وقتی نمونه‌های Decimal را در اختیار دارید، می‌توانید عملیات‌های ریاضی متداول را روی آن‌ها انجام دهید. یک محدودیت: توان‌رسانی نیازمند توان عدد صحیح است:

>>> a = decimal.Decimal('35.72')
>>> b = decimal.Decimal('1.73')
>>> a+b
Decimal("37.45")
>>> a-b
Decimal("33.99")
>>> a*b
Decimal("61.7956")
>>> a/b
Decimal("20.64739884393063583815028902")
>>> a ** 2
Decimal("1275.9184")
>>> a**b
Traceback (most recent call last):
  ...
decimal.InvalidOperation: x ** (non-integer)

می‌توانید نمونه‌های Decimal را با اعداد صحیح ترکیب کنید، اما نه با اعداد ممیز شناور:

>>> a + 4
Decimal("39.72")
>>> a + 4.5
Traceback (most recent call last):
  ...
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>

می‌توان از عددهای Decimal با ماژول‌های math و cmath استفاده کرد، اما توجه داشته باشید که این عددها پیش از انجام عملیات، بی‌درنگ به عددهای ممیز شناور تبدیل می‌شوند که این امر می‌تواند به از دست رفتن دقت و صحت بینجامد. همچنین مقداری که دریافت می‌کنید یک عدد ممیز شناور معمولی است، نه یک Decimal.

>>> import math, cmath
>>> d = decimal.Decimal('123456789012.345')
>>> math.sqrt(d)
351364.18288201344
>>> cmath.sqrt(-d)
351364.18288201344j

نمونه‌های Decimal یک متد sqrt() دارند که یک Decimal برمی‌گرداند، اما اگر به چیزهای دیگری مانند توابع مثلثاتی نیاز داشته باشید، باید آن‌ها را پیاده‌سازی کنید.

>>> d.sqrt()
Decimal("351364.1828820134592177245001")

نوع Context

نمونه‌های کلاس Context چندین تنظیم برای عملیات‌های اعشاری را دربرمی‌گیرند:

  • prec دقت است، یعنی تعداد ارقام اعشار.

  • rounding حالت گرد کردن را مشخص می‌کند. ماژول decimal ثابت‌هایی برای امکان‌های مختلف دارد: ROUND_DOWN، ROUND_CEILING، ROUND_HALF_EVEN و موارد مختلف دیگر.

  • traps یک دیکشنری است که مشخص می‌کند هنگام مواجهه با شرایط خطای خاص چه اتفاقی می‌افتد: یا یک استثنا مطرح می‌شود یا یک مقدار برگردانده می‌شود. نمونه‌هایی از شرایط خطا عبارت‌اند از تقسیم بر صفر، از دست رفتن دقت و سرریز.

یک زمینه‌ی پیش‌فرض نخ‌محلی با فراخوانی getcontext() در دسترس است؛ می‌توانید ویژگی‌های این زمینه را تغییر دهید تا دقت پیش‌فرض، گرد کردن، یا مدیریت تله تغییر کند. مثال زیر اثر تغییر دادن دقت زمینه‌ی پیش‌فرض را نشان می‌دهد:

>>> decimal.getcontext().prec
28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 9
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.142857143")

کنش پیش‌فرض برای شرایط خطا قابل انتخاب است؛ ماژول می‌تواند یا مقدار ویژه‌ای مانند بی‌نهایت یا عدد نیست (not-a-number) را برگرداند، یا استثناها ایجاد شوند:

>>> decimal.Decimal(1) / decimal.Decimal(0)
Traceback (most recent call last):
  ...
decimal.DivisionByZero: x / 0
>>> decimal.getcontext().traps[decimal.DivisionByZero] = False
>>> decimal.Decimal(1) / decimal.Decimal(0)
Decimal("Infinity")
>>>

نمونه‌ی Context نیز متدهای گوناگونی برای قالب‌بندی اعداد مانند to_eng_string() و to_sci_string() دارد.

برای اطلاعات بیشتر، به مستندات ماژول decimal مراجعه کنید که شامل یک آموزش شروع سریع و یک مرجع است.

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

PEP 327 - نوع داده Decimal

نوشته‌ی Facundo Batista و پیاده‌سازی‌شده توسط Facundo Batista، Eric Price، Raymond Hettinger، Aahz و Tim Peters.

http://www.lahey.com/float.htm

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

https://speleotrove.com/decimal/

شرحی از یک بازنمایی مبتنی بر ده‌دهی. این بازنمایی به‌عنوان یک استاندارد پیشنهاد شده است و زیربنای نوع decimal جدید پایتون را تشکیل می‌دهد. بخش زیادی از این مطالب توسط Mike Cowlishaw، طراح زبان Rexx، نوشته شده است.

PEP 328: ایمپورت‌های چندسطری

یکی از تغییرات زبان، اصلاح کوچکی در سینتکس است که هدف آن آسان‌تر کردن ایمپورت نام‌های متعدد از یک ماژول است. در دستور from module import names، names دنباله‌ای از نام‌ها است که با کاما از هم جدا شده‌اند. اگر این دنباله بسیار طولانی باشد، می‌توانید یا چند ایمپورت از همان ماژول بنویسید، یا برای خنثی کردن انتهای سطرها از بک‌اسلش‌ها استفاده کنید، به این شکل:

from SimpleXMLRPCServer import SimpleXMLRPCServer,\
            SimpleXMLRPCRequestHandler,\
            CGIXMLRPCRequestHandler,\
            resolve_dotted_attribute

تغییر نحوی در پایتون 2.4 صرفاً اجازه می‌دهد نام‌ها درون پرانتز قرار بگیرند. پایتون سطرهای جدید را در یک عبارت داخل پرانتز نادیده می‌گیرد، بنابراین دیگر نیازی به بک‌اسلش‌ها نیست:

from SimpleXMLRPCServer import (SimpleXMLRPCServer,
                                SimpleXMLRPCRequestHandler,
                                CGIXMLRPCRequestHandler,
                                resolve_dotted_attribute)

این PEP همچنین پیشنهاد می‌کند که همه‌ی دستورهای import، ایمپورت مطلق باشند و نویسه‌ی . در ابتدا نشان‌دهنده‌ی ایمپورت نسبی باشد. این بخش از PEP در پایتون 2.4 پیاده‌سازی نشد، اما در پایتون 2.5 تکمیل شد.

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

PEP 328 - ایمپورت‌ها: چندسطری و مطلق/نسبی

نوشته‌ی Aahz. ایمپورت‌های چندسطری توسط Dima Dorfman پیاده‌سازی شدند.

PEP 331: تبدیل‌های اعشاری/رشته مستقل از locale

ماژول locale به نرم‌افزار پایتون اجازه می‌دهد تا تبدیل‌ها و قراردادهای نمایش گوناگونی را که برای کشور یا زبان خاصی بومی‌سازی شده‌اند انتخاب کند. با این حال، این ماژول مراقب بود که locale عددی را تغییر ندهد، زیرا توابع مختلفی در پیاده‌سازی پایتون نیاز داشتند که locale عددی روی 'C' تنظیم باقی بماند. اغلب دلیل این امر آن بود که کد از تابع atof() کتابخانه C استفاده می‌کرد.

اما عدم تنظیم locale عددی برای ماژول‌های توسعه‌ای که از کتابخانه‌های C شخص ثالث استفاده می‌کردند مشکل ایجاد می‌کرد، زیرا locale درست برای آن‌ها تنظیم نمی‌شد. مثال انگیزه‌بخش GTK+ بود که ابزارک‌های رابط کاربری آن اعداد را مطابق با locale جاری نمایش نمی‌دادند.

راه‌حل توصیف‌شده در PEP، افزودن سه تابع جدید به API پایتون است که با نادیده گرفتن تنظیمات locale، تبدیل‌های فقط‌اسکی انجام می‌دهند:

  • PyOS_ascii_strtod(str, ptr) و PyOS_ascii_atof(str, ptr) هر دو یک رشته را به یک double در C تبدیل می‌کنند.

  • PyOS_ascii_formatd(buffer, buf_len, format, d) یک double را به رشته‌ی اسکی تبدیل می‌کند.

کد این توابع از کتابخانه‌ی GLib (https://developer-old.gnome.org/glib/2.26/) گرفته شده است؛ توسعه‌دهندگان این کتابخانه با کمال مهربانی مجوز توابع مربوطه را تغییر دادند و آن‌ها را به بنیاد نرم‌افزار پایتون اهدا کردند. ماژول locale اکنون می‌تواند locale عددی را تغییر دهد و به ماژول‌های توسعه‌ای مانند GTK+ اجازه دهد تا نتایج صحیح را تولید کنند.

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

PEP 331 - تبدیل‌های اعشاری/رشته مستقل از locale

نوشته‌ی Christian R. Reis، و پیاده‌سازی‌شده توسط Gustavo Carneiro.

سایر تغییرات زبان

این‌ها تمام تغییراتی هستند که پایتون 2.4 در هسته‌ی زبان پایتون ایجاد می‌کند.

  • دکوراتورها برای توابع و متدها افزوده شدند (PEP 318).

  • نوع‌های توکار set() و frozenset() افزوده شدند (PEP 218). سایر توکارهای جدید شامل تابع reversed(seq) هستند (PEP 322).

  • عبارت‌های تولیدگر افزوده شدند (PEP 289).

  • برخی عبارت‌های عددی دیگر مقادیر محدود به ۳۲ یا ۶۴ بیت را برنمی‌گردانند (PEP 237).

  • اکنون می‌توانید در دستور from module import names دور فهرست نام‌ها پرانتز قرار دهید (PEP 328).

  • متد dict.update() اکنون همان شکل‌های آرگومانِ سازنده‌ی dict را می‌پذیرد. این شامل هر نگاشتی، هر پیمایش‌پذیری از جفت‌های کلید/مقدار، و آرگومان‌های کلیدواژه‌ای می‌شود. (مشارکت‌شده توسط Raymond Hettinger.)

  • متدهای رشته ljust()، rjust() و center() اکنون یک آرگومان اختیاری برای تعیین نویسه‌ی پُرکننده‌ای غیر از فاصله می‌پذیرند. (مشارکت‌شده توسط Raymond Hettinger.)

  • رشته‌ها همچنین متد rsplit() را به دست آوردند که مانند متد split() کار می‌کند، اما از انتهای رشته جدا می‌کند. (مشارکت‌شده توسط Sean Reifschneider.)

    >>> 'www.python.org'.split('.', 1)
    ['www', 'python.org']
    'www.python.org'.rsplit('.', 1)
    ['www.python', 'org']
    
  • سه پارامتر کلیدواژه‌ای، cmp، key و reverse، به متد sort() فهرست‌ها افزوده شدند. این پارامترها برخی از کاربردهای رایج sort() را ساده‌تر می‌کنند. همه‌ی این پارامترها اختیاری هستند.

    برای پارامتر cmp، مقدار باید یک تابع مقایسه باشد که دو پارامتر می‌گیرد و بسته به نحوه مقایسه پارامترها، -1، 0 یا +1 را برمی‌گرداند. سپس از این تابع برای مرتب‌سازی فهرست استفاده خواهد شد. پیش‌تر این تنها پارامتری بود که می‌توان به sort() ارائه داد.

    key باید تابعی تک‌پارامتری باشد که یک عنصر فهرست را دریافت می‌کند و کلید مقایسه‌ای برای آن عنصر برمی‌گرداند. سپس فهرست با استفاده از کلیدهای مقایسه مرتب می‌شود. مثال زیر یک فهرست را بدون حساسیت به بزرگی و کوچکی حروف مرتب می‌کند:

    >>> L = ['A', 'b', 'c', 'D']
    >>> L.sort()                 # Case-sensitive sort
    >>> L
    ['A', 'D', 'b', 'c']
    >>> # Using 'key' parameter to sort list
    >>> L.sort(key=lambda x: x.lower())
    >>> L
    ['A', 'b', 'c', 'D']
    >>> # Old-fashioned way
    >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))
    >>> L
    ['A', 'b', 'c', 'D']
    

    آخرین مثال، که از پارامتر cmp استفاده می‌کند، روش قدیمی برای انجام مرتب‌سازی بدون توجه به بزرگی و کوچکی حروف است. این روش کار می‌کند اما کندتر از استفاده از پارامتر key است. استفاده از key متد lower() را برای هر عنصر در فهرست یک بار فراخوانی می‌کند، در حالی که استفاده از cmp آن را برای هر مقایسه دو بار فراخوانی می‌کند؛ بنابراین استفاده از key در فراخوانی‌های متد lower() صرفه‌جویی می‌کند.

    برای توابع کلید ساده و توابع مقایسه، اغلب می‌توان از عبارت lambda اجتناب کرد و به جای آن از یک متد غیرمقید (unbound method) استفاده نمود. برای مثال، مرتب‌سازی بدون حساسیت به بزرگی و کوچکی حروف بالا را بهتر است به این صورت بنویسید:

    >>> L.sort(key=str.lower)
    >>> L
    ['A', 'b', 'c', 'D']
    

    در نهایت، پارامتر reverse یک مقدار بولی می‌گیرد. اگر مقدار درست باشد، فهرست به ترتیب معکوس مرتب می‌شود. به جای L.sort(); L.reverse() می‌توانید اکنون L.sort(reverse=True) بنویسید.

    اکنون تضمین می‌شود که نتایج مرتب‌سازی پایدار باشند. این بدان معناست که دو ورودی با کلیدهای برابر، به همان ترتیبی که وارد شده بودند بازگردانده می‌شوند. برای مثال، می‌توانید فهرستی از افراد را بر اساس نام مرتب کنید و سپس فهرست را بر اساس سن مرتب کنید؛ در نتیجه، فهرستی مرتب‌شده بر اساس سن به دست می‌آید که در آن افراد هم‌سن به ترتیب نام مرتب شده‌اند.

    (تمام تغییرات sort() توسط Raymond Hettinger ارائه‌شده است.)

  • یک تابع توکار جدید به نام sorted(iterable) وجود دارد که مانند متد درجا list.sort() عمل می‌کند، اما می‌توان از آن در عبارت‌ها استفاده کرد. تفاوت‌ها عبارت‌اند از:

  • ورودی می‌تواند هر شیء پیمایش‌پذیری باشد؛

  • رونوشتی تازه‌ایجادشده مرتب می‌شود و نسخه‌ی اصلی دست‌نخورده باقی می‌ماند؛ و

  • عبارت نسخه‌ی مرتب‌شده‌ی جدید را برمی‌گرداند

    >>> L = [9,7,8,3,2,4,1,6,5]
    >>> [10+i for i in sorted(L)]       # usable in a list comprehension
    [11, 12, 13, 14, 15, 16, 17, 18, 19]
    >>> L                               # original is left unchanged
    [9,7,8,3,2,4,1,6,5]
    >>> sorted('Monty Python')          # any iterable may be an input
    [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y']
    
    >>> # List the contents of a dict sorted by key values
    >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5)
    >>> for k, v in sorted(colormap.iteritems()):
    ...     print k, v
    ...
    black 4
    blue 2
    green 3
    red 1
    yellow 5
    

    (مشارکت‌شده توسط Raymond Hettinger.)

  • عملیات عدد صحیح دیگر هشدار OverflowWarning را فعال نمی‌کنند. هشدار OverflowWarning در پایتون 2.5 حذف خواهد شد.

  • مفسر سوییچ جدیدی به نام -m گرفت که نامی را دریافت می‌کند، ماژول متناظر را در sys.path جست‌وجو می‌کند و ماژول را به‌عنوان اسکریپت اجرا می‌کند. برای مثال، اکنون می‌توانید پروفایل‌گیر پایتون را با python -m profile اجرا کنید. (مشارکت‌شده توسط Nick Coghlan.)

  • توابع eval(expr, globals, locals) و execfile(filename, globals, locals) و دستور exec اکنون هر نوع نگاشتی را برای پارامتر locals می‌پذیرند. پیش‌تر این باید یک دیکشنری معمولی پایتون می‌بود. (ارائه‌شده توسط ریموند هتینگر.)

  • تابع توکار zip() و itertools.izip() اکنون در صورت فراخوانی بدون آرگومان، فهرست خالی برمی‌گردانند. پیش‌تر این توابع استثنای TypeError ایجاد می‌کردند. این امر آن‌ها را برای استفاده در فهرست‌های آرگومان با طول متغیر مناسب‌تر می‌کند:

    >>> def transpose(array):
    ...    return zip(*array)
    ...
    >>> transpose([(1,2,3), (4,5,6)])
    [(1, 4), (2, 5), (3, 6)]
    >>> transpose([])
    []
    

    (مشارکت‌شده توسط Raymond Hettinger.)

  • برخورد با خطا هنگام ایمپورت کردن یک ماژول، دیگر شیء ماژولِ به‌طور ناقص مقداردهی‌شده‌ای در sys.modules باقی نمی‌گذارد. شیء ماژول ناقصِ به‌جامانده، ایمپورت‌های بعدی همان ماژول را فریب می‌داد تا به اشتباه موفق تلقی شوند و این امر منجر به خطاهای گیج‌کننده‌ای می‌شد. (اصلاح‌شده توسط تیم پیترز.)

  • None اکنون یک ثابت است؛ کدی که مقدار جدیدی را به نام None مقید می‌کند، اکنون یک خطای سینتکس است. (مشارکت‌شده توسط Raymond Hettinger.)

بهینه‌سازی‌ها

  • حلقه‌های داخلی اسلایس‌کردن فهرست‌ها و تاپل‌ها بهینه‌سازی شدند و اکنون حدود یک‌سوم سریع‌تر اجرا می‌شوند. حلقه‌های داخلی دیکشنری‌ها نیز بهینه‌سازی شدند که این امر منجر به افزایش کارایی keys()، values()، items()، iterkeys()، itervalues() و iteritems() شد. (مشارکت‌کرده: Raymond Hettinger.)

  • سازوکار رشد و کوچک‌شدن فهرست‌ها برای سرعت و کارایی فضایی بهینه‌سازی شد. افزودن به فهرست‌ها و برداشتن از آن‌ها اکنون به دلیل مسیرهای کد کارآمد‌تر و استفاده‌ی کمتر از realloc() سیستمِ زیرین، سریع‌تر اجرا می‌شود. درک‌های فهرستی نیز از این بهره‌مند می‌شوند. list.extend() نیز بهینه‌سازی شد و دیگر پیش از گسترش فهرست پایه، آرگومان خود را به فهرستی موقت تبدیل نمی‌کند. (مشارکت: Raymond Hettinger.)

  • list()، tuple()، map()، filter() و zip() اکنون با آرگومان‌های غیردنباله‌ای که متد __len__() را فراهم می‌کنند، چندین برابر سریع‌تر اجرا می‌شوند. (مشارکت‌شده توسط Raymond Hettinger.)

  • متدهای list.__getitem__()، dict.__getitem__() و dict.__contains__() اکنون به‌صورت اشیاء method_descriptor به جای اشیاء wrapper_descriptor پیاده‌سازی شده‌اند. این شکل از دسترسی، کارایی آن‌ها را دو برابر می‌کند و آن‌ها را برای استفاده به‌عنوان آرگومان به توابع مرتبه‌بالا (functionals) مناسب‌تر می‌کند: map(mydict.__getitem__, keylist). (مشارکت‌شده توسط ریموند هتینگر.)

  • آپ‌کد جدیدی با نام LIST_APPEND اضافه شد که بایت‌کد تولیدشده برای درک‌های فهرستی را ساده‌سازی می‌کند و سرعت آن‌ها را حدود یک‌سوم افزایش می‌دهد. (مشارکت‌کننده: Raymond Hettinger)

  • بهینه‌ساز روزنه‌ای (peephole) بایت‌کد بهبود یافته است تا بایت‌کد کوتاه‌تر و سریع‌تری تولید کند؛ به‌طور شگفت‌آوری، بایت‌کد حاصل خواناتر نیز هست. (بهبودیافته توسط ری‌موند هتینگر.)

  • الحاق رشته‌ها در دستورهایی به شکل s = s + "abc" و s += "abc" اکنون در شرایط خاصی کارآمدتر انجام می‌شود. این بهینه‌سازی در پیاده‌سازی‌های دیگر پایتون مانند Jython وجود نخواهد داشت، بنابراین نباید به آن تکیه کنید؛ هنگامی که می‌خواهید تعداد زیادی رشته را به‌طور کارآمد به هم بچسبانید، همچنان استفاده از متد join() رشته‌ها توصیه می‌شود. (مشارکت‌شده توسط Armin Rigo.)

نتیجه‌ی نهایی بهینه‌سازی‌های 2.4 این است که پایتون 2.4 بنچمارک (benchmark) pystone را حدود ۵٪ سریع‌تر از پایتون 2.3 و ۳۵٪ سریع‌تر از پایتون 2.2 اجرا می‌کند. (pystone بنچمارک به‌خصوص خوبی نیست، اما رایج‌ترین معیار اندازه‌گیری عملکرد پایتون است. ممکن است برنامه‌های خود شما مزایای بیشتر یا کمتری از پایتون 2.4 نشان دهند.)

ماژول‌های جدید، بهبودیافته و منسوخ

طبق معمول، کتابخانه استاندارد پایتون تعدادی بهبود و رفع اشکال دریافت کرد. در ادامه، فهرست ناقصی از مهم‌ترین تغییرات، مرتب‌شده به ترتیب الفبایی بر اساس نام ماژول، ارائه می‌شود. برای فهرست کامل‌تری از تغییرات، به پرونده‌ی Misc/NEWS در درخت منبع مراجعه کنید، یا برای همه‌ی جزئیات، گزارش‌های CVS را بررسی کنید.

  • تابع loop() ماژول asyncore اکنون یک پارامتر count دارد که به شما امکان می‌دهد تعداد محدودی گذر از حلقه پایش را انجام دهید. پیش‌فرض همچنان این است که حلقه برای همیشه اجرا شود.

  • ماژول base64 اکنون پشتیبانی کامل‌تری از RFC 3548 برای کدگذاری و کدگشایی Base64، Base32 و Base16 دارد، از جمله تا کردن اختیاری بزرگی و کوچکی حروف (case folding) و الفباهای جایگزین اختیاری. (مشارکت از سوی Barry Warsaw.)

  • ماژول bisect اکنون یک پیاده‌سازی C در زیربنای خود برای بهبود کارایی دارد. (مشارکت توسط Dmitry Vasiliev.)

  • مجموعه‌های CJKCodecs از کدک‌های آسیای شرقی، که توسط Hye-Shik Chang نگهداری می‌شدند، در نسخه‌ی 2.4 ادغام شدند. کدگذاری‌های جدید عبارت‌اند از:

  • چینی (جمهوری خلق چین): gb2312, gbk, gb18030, big5hkscs, hz

  • چینی (جمهوری چین): big5, cp950

  • ژاپنی: cp932, euc-jis-2004, euc-jp, euc-jisx0213, iso-2022-jp,

    iso-2022-jp-1, iso-2022-jp-2, iso-2022-jp-3, iso-2022-jp-ext, iso-2022-jp-2004, shift-jis, shift-jisx0213, shift-jis-2004

  • کره‌ای: cp949, euc-kr, johab, iso-2022-kr

  • چند کدگذاری جدید دیگر نیز افزوده شدند: HP Roman8، ISO_8859-11، ISO_8859-16، PCTP-154 و TIS-620.

  • کدک‌های UTF-8 و UTF-16 اکنون بهتر با دریافت ورودی ناقص کنار می‌آیند. پیش‌تر کلاس StreamReader تلاش می‌کرد داده‌های بیشتری بخواند، که این امر از سر گرفتن کدگشایی از جریان را ناممکن می‌کرد. متد read() اکنون هر مقدار داده که بتواند برمی‌گرداند و فراخوانی‌های بعدی کدگشایی را از جایی که فراخوانی‌های قبلی رها کرده بودند از سر می‌گیرند. (پیاده‌سازی‌شده توسط Walter Dörwald.)

  • یک ماژول جدید collections برای انواع مختلف داده‌های مجموعه‌ای تخصصی وجود دارد. در حال حاضر این ماژول تنها یک نوع را در بر می‌گیرد، deque، که صفی دوطرفه است و از افزودن و حذف کارآمد عناصر از هر دو سر پشتیبانی می‌کند:

    >>> from collections import deque
    >>> d = deque('ghi')        # make a new deque with three items
    >>> d.append('j')           # add a new entry to the right side
    >>> d.appendleft('f')       # add a new entry to the left side
    >>> d                       # show the representation of the deque
    deque(['f', 'g', 'h', 'i', 'j'])
    >>> d.pop()                 # return and remove the rightmost item
    'j'
    >>> d.popleft()             # return and remove the leftmost item
    'f'
    >>> list(d)                 # list the contents of the deque
    ['g', 'h', 'i']
    >>> 'h' in d                # search the deque
    True
    

    چندین ماژول، مانند ماژول‌های queue و threading، اکنون برای بهبود کارایی از collections.deque بهره می‌برند. (با مشارکت Raymond Hettinger.)

  • کلاس‌های ConfigParser کمی بهبود یافته‌اند. متد read() اکنون فهرستی از پرونده‌هایی که با موفقیت تجزیه شده‌اند را برمی‌گرداند، و متد set() در صورتی که آرگومان valueای که رشته نیست به آن ارسال شود، استثنای TypeError ایجاد می‌کند. (مشارکت توسط John Belmonte و David Goodger.)

  • ماژول curses اکنون از افزونه‌ی ncurses با نام use_default_colors() پشتیبانی می‌کند. در پلتفرم‌هایی که پایانه از شفافیت پشتیبانی می‌کند، این امکان را فراهم می‌کند که از پس‌زمینه‌ی شفاف استفاده کنید. (مشارکت‌شده توسط Jörg Lehmann.)

  • ماژول difflib اکنون شامل کلاس HtmlDiff است که جدولی HTML ایجاد می‌کند که مقایسه‌ی دو نسخه از یک متن را به‌صورت کنار‌به‌کنار نشان می‌دهد. (مشارکت Dan Gass.)

  • بسته‌ی email به نسخه 3.0 به‌روزرسانی شد که در آن APIهای منسوخ‌شده‌ی مختلف حذف شدند و پشتیبانی از نسخه‌های پایتون پیش از 2.3 برداشته شد. نسخه 3.0 این بسته از یک پارسر افزایشی جدید برای پیام‌های MIME استفاده می‌کند که در ماژول email.FeedParser در دسترس است. پارسر جدید نیازی به خواندن کل پیام در حافظه ندارد و اگر پیامی بدشکل باشد، استثنا ایجاد نمی‌کند؛ در عوض، هرگونه مشکل را در ویژگی defect پیام ثبت می‌کند. (توسعه‌یافته توسط آنتونی باکستر، بری ورشو، توماس ووترز و دیگران.)

  • ماژول heapq به C تبدیل شده است. بهبود ده‌برابری حاصل در سرعت، این ماژول را برای پردازش حجم زیاد داده‌ها مناسب می‌سازد. علاوه بر این، این ماژول دو تابع جدید nlargest() و nsmallest() دارد که از هیپ‌ها برای یافتن بزرگ‌ترین یا کوچک‌ترین N مقدار در یک مجموعه داده، بدون هزینه‌ی مرتب‌سازی کامل استفاده می‌کنند. (مشارکت‌شده توسط Raymond Hettinger.)

  • ماژول httplib اکنون شامل ثابت‌هایی برای کدهای وضعیت HTTP است که در اسناد RFC مختلف مرتبط با HTTP تعریف شده‌اند. این ثابت‌ها نام‌هایی مانند OK، CREATED، CONTINUE و MOVED_PERMANENTLY دارند؛ برای دریافت فهرست کامل، از pydoc استفاده کنید. (مشارکت: Andrew Eland.)

  • ماژول imaplib اکنون از فرمان THREAD در IMAP (با مشارکت Yves Dionne) و متدهای جدید deleteacl() و myrights() (با مشارکت Arnaud Mazin) پشتیبانی می‌کند.

  • تابع groupby(iterable[, *func*]) به ماژول itertools اضافه شد. iterable چیزی است که می‌توان روی آن پیمایش کرد تا جریانی از عناصر را برگرداند، و پارامتر اختیاری func تابعی است که یک عنصر را دریافت می‌کند و یک مقدار کلید برمی‌گرداند؛ اگر ذکر نشود، کلید به‌سادگی خودِ عنصر است. سپس groupby() عناصر را به زیردنباله‌هایی گروه‌بندی می‌کند که مقدار کلید یکسانی دارند، و دنباله‌ای از تاپل‌های دوتایی شامل مقدار کلید و پیمایش‌گری بر روی زیردنباله برمی‌گرداند.

    در اینجا مثالی برای شفاف‌تر شدن موضوع آورده شده است. تابع کلید صرفاً برمی‌گرداند که یک عدد زوج است یا فرد؛ بنابراین نتیجه‌ی groupby() بازگرداندن دنباله‌های متوالی از اعداد فرد یا زوج است.

    >>> import itertools
    >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14]
    >>> for key_val, it in itertools.groupby(L, lambda x: x % 2):
    ...    print key_val, list(it)
    ...
    0 [2, 4, 6]
    1 [7]
    0 [8]
    1 [9, 11]
    0 [12, 14]
    >>>
    

    groupby() معمولاً با ورودی مرتب‌شده استفاده می‌شود. منطق groupby() مشابه فیلتر uniq در یونیکس است که آن را برای حذف، شمارش یا شناسایی المان‌های تکراری سودمند می‌کند:

    >>> word = 'abracadabra'
    >>> letters = sorted(word)   # Turn string into a sorted list of letters
    >>> letters
    ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r']
    >>> for k, g in itertools.groupby(letters):
    ...    print k, list(g)
    ...
    a ['a', 'a', 'a', 'a', 'a']
    b ['b', 'b']
    c ['c']
    d ['d']
    r ['r', 'r']
    >>> # List unique letters
    >>> [k for k, g in groupby(letters)]
    ['a', 'b', 'c', 'd', 'r']
    >>> # Count letter occurrences
    >>> [(k, len(list(g))) for k, g in groupby(letters)]
    [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
    

    (مشارکت‌شده توسط Hye-Shik Chang.)

  • itertools همچنین تابعی به نام tee(iterator, N) به دست آورد که N پیمایش‌گر مستقل را برمی‌گرداند که iterator را بازتولید می‌کنند. اگر N ذکر نشود، مقدار پیش‌فرض ۲ است.

    >>> L = [1,2,3]
    >>> i1, i2 = itertools.tee(L)
    >>> i1,i2
    (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>)
    >>> list(i1)               # Run the first iterator to exhaustion
    [1, 2, 3]
    >>> list(i2)               # Run the second iterator to exhaustion
    [1, 2, 3]
    

    توجه داشته باشید که tee() باید کپی‌هایی از مقادیر بازگردانده‌شده توسط پیمایش‌گر را نگه دارد؛ در بدترین حالت، ممکن است لازم باشد همه‌ی آن‌ها را نگه دارد. بنابراین اگر پیمایش‌گر پیش‌رو بتواند در جریانی بلند از ورودی‌ها بسیار از پیمایش‌گر دنباله‌رو جلو بزند، باید با احتیاط از آن استفاده کرد. اگر فاصله زیاد باشد، بهتر است به‌جای آن از list() استفاده کنید. وقتی پیمایش‌گرها به‌طور نزدیکی هم‌گام با یکدیگر پیش می‌روند، tee() ایده‌آل است. کاربردهای احتمالی شامل نشانک‌گذاری، پنجره‌بندی (windowing)، یا پیمایش‌گرهای پیش‌نگر است. (مشارکت‌شده توسط Raymond Hettinger.)

  • تعدادی تابع به ماژول locale اضافه شد، مانند bind_textdomain_codeset() برای تعیین یک کدگذاری خاص و خانواده‌ای از توابع l*gettext() که پیام‌ها را با کدگذاری انتخاب‌شده برمی‌گردانند. (مشارکت‌شده توسط Gustavo Niemeyer.)

  • برای ساده‌سازی پیکربندی گزارش‌گیری، چند آرگومان کلیدواژه‌ای به تابع basicConfig() بسته‌ی logging افزوده شد. رفتار پیش‌فرض، ثبت پیام‌ها در خطای استاندارد است، اما می‌توان آرگومان‌های کلیدواژه‌ای گوناگونی را مشخص کرد تا گزارش‌ها در یک پرونده‌ی خاص ثبت شوند، قالب گزارش‌گیری تغییر کند یا سطح گزارش‌گیری تنظیم شود. برای مثال:

    import logging
    logging.basicConfig(filename='/var/log/application.log',
        level=0,  # Log all messages
        format='%(levelname):%(process):%(thread):%(message)')
    

    دیگر افزوده‌های بسته‌ی logging شامل یک متد کمکی log(level, msg) و همچنین کلاس TimedRotatingFileHandler است که پرونده‌های گزارش خود را در بازه‌های زمانی معین چرخش می‌دهد. این ماژول پیش‌تر RotatingFileHandler را داشت که گزارش‌ها را پس از آنکه پرونده از اندازه‌ی معینی فراتر می‌رفت، چرخش می‌داد. هر دو کلاس از کلاس جدید BaseRotatingHandler مشتق شده‌اند که می‌توان از آن برای پیاده‌سازی هندلرهای چرخشی دیگر استفاده کرد.

    (تغییرات توسط Vinay Sajip پیاده‌سازی شده است.)

  • ماژول marshal اکنون هنگام واگشایی یک ساختار داده، رشته‌های درونی‌سازی‌شده را به اشتراک می‌گذارد. این کار ممکن است اندازه‌ی برخی رشته‌های پیکل را کاهش دهد، اما اثر اصلی آن این است که پرونده‌های .pyc به‌طور چشمگیری کوچک‌تر شوند. (مشارکت‌شده توسط Martin von Löwis.)

  • به کلاس NNTP در ماژول nntplib متدهای description() و descriptions() برای بازیابی توضیحات گروه‌های خبری برای یک گروه یا محدوده‌ای از گروه‌ها افزوده شد. (مشارکت‌شده توسط Jürgen A. Erhard.)

  • دو تابع جدید به ماژول operator افزوده شدند: attrgetter(attr) و itemgetter(index). هر دو تابع فراخوانی‌پذیرهایی برمی‌گردانند که یک آرگومان واحد می‌گیرند و ویژگی یا آیتم مربوطه را برمی‌گردانند؛ این فراخوانی‌پذیرها هنگامی که با map() یا sorted() استفاده می‌شوند، استخراج‌کننده‌های داده‌ی عالی‌ای هستند. برای مثال:

    >>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]
    >>> map(operator.itemgetter(0), L)
    ['c', 'd', 'a', 'b']
    >>> map(operator.itemgetter(1), L)
    [2, 1, 4, 3]
    >>> sorted(L, key=operator.itemgetter(1)) # Sort list by second tuple item
    [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
    

    (مشارکت‌شده توسط Raymond Hettinger.)

  • ماژول optparse به روش‌های گوناگونی به‌روزرسانی شد. این ماژول اکنون پیام‌های خود را از طریق gettext.gettext() عبور می‌دهد که این امر امکان بین‌المللی‌سازی پیام‌های راهنما و خطای Optik را فراهم می‌سازد. پیام‌های راهنمای گزینه‌ها اکنون می‌توانند شامل رشته‌ی '%default' باشند که با مقدار پیش‌فرض گزینه جایگزین خواهد شد. (مشارکت‌شده توسط گرگ وارد.)

  • برنامه‌ی بلندمدت این است که ماژول rfc822 در نسخه‌ای آینده از پایتون به نفع بسته‌ی email منسوخ شود. به این منظور، تابع email.Utils.formatdate تغییر کرده است تا بتواند به‌عنوان جایگزینی برای rfc822.formatdate() استفاده شود. ممکن است بخواهید کدهای جدید پردازش ایمیل را با در نظر داشتن این موضوع بنویسید. (این تغییر توسط آنتونی باکستر پیاده‌سازی شد.)

  • تابع جدید urandom(n) به ماژول os اضافه شد که رشته‌ای حاوی n بایت داده‌ی تصادفی برمی‌گرداند. این تابع دسترسی به منابع تصادفی مخصوص پلتفرم مانند /dev/urandom در لینوکس یا CryptoAPI ویندوز را فراهم می‌کند. (مشارکت توسط Trevor Perrin.)

  • تابع جدید دیگر: os.path.lexists(path) اگر پرونده‌ی مشخص‌شده توسط path وجود داشته باشد، مقدار true را برمی‌گرداند؛ صرف‌نظر از اینکه پیوند نمادین باشد یا نباشد. این تابع با تابع موجود os.path.exists(path) تفاوت دارد که اگر path پیوندی نمادین به مقصدی باشد که وجود ندارد، مقدار false را برمی‌گرداند. (مشارکت‌شده توسط Beni Cherniavsky.)

  • تابع جدید getsid() به ماژول posix که زیربنای ماژول os است، افزوده شد. (مشارکت: J. Raynor.)

  • ماژول poplib اکنون از POP بر روی SSL پشتیبانی می‌کند. (مشارکت: Hector Urtubia.)

  • ماژول profile اکنون می‌تواند توابع توسعه‌ای C را پروفایل‌گیری کند. (مشارکت‌شده توسط Nick Bastin.)

  • ماژول random متد جدیدی به نام getrandbits(N) دارد که یک عدد صحیح بلند به طول N بیت برمی‌گرداند. متد موجود randrange() اکنون در موارد مناسب از getrandbits() استفاده می‌کند که این امر تولید اعداد تصادفی با هر اندازه‌ی بزرگ دلخواه را کارآمدتر می‌کند. (مشارکت Raymond Hettinger.)

  • زبان عبارت باقاعده‌ی پذیرفته‌شده توسط ماژول re با عبارت‌های شرطی ساده که به شکل (?(group)A|B) نوشته می‌شوند گسترش یافت. group یا یک شناسه‌ی گروه عددی است یا نام گروهی که پیش‌تر در عبارت با (?P<group>...) تعریف شده است. اگر گروه مشخص‌شده تطبیق یافته باشد، الگوی عبارت باقاعده A در برابر رشته آزموده می‌شود؛ اگر گروه تطبیق نیافته باشد، به جای آن الگوی B به کار می‌رود. (با مشارکت گوستاوو نیمایر.)

  • ماژول re نیز به لطف حجم عظیمی از کار گوستاوو نیمایر، دیگر بازگشتی نیست. در موتور عبارت باقاعده‌ی بازگشتی، برخی الگوها باعث می‌شوند مقدار زیادی از فضای پشته‌ی C مصرف شود و امکان سرریز پشته وجود داشت. برای مثال، اگر رشته‌ای ۳۰۰۰۰ بایتی از نویسه‌های a را با عبارت (a|b)+ تطبیق می‌دادید، به ازای هر نویسه یک فریم پشته مصرف می‌شد. پایتون 2.3 تلاش می‌کرد سرریز پشته را بررسی کند و استثنای RuntimeError ایجاد کند، اما برخی الگوها می‌توانستند بررسی را دور بزنند و اگر بدشانس می‌بودید، ممکن بود پایتون دچار خطای قطعه‌بندی (segmentation fault) شود. موتور عبارت باقاعده‌ی پایتون 2.4 می‌تواند این الگو را بدون مشکل تطبیق دهد.

  • ماژول signal اکنون بررسی خطای سخت‌گیرانه‌تری روی پارامترهای تابع signal.signal() انجام می‌دهد. برای مثال، نمی‌توانید روی سیگنال SIGKILL هندلری تنظیم کنید؛ نسخه‌های قبلی پایتون این را بی‌سروصدا می‌پذیرفتند، اما 2.4 استثنای RuntimeError پرتاب می‌کند.

  • دو تابع جدید به ماژول socket اضافه شدند. socketpair() یک جفت سوکت متصل را برمی‌گرداند و getservbyport(port) نام سرویس مربوط به یک شماره پورت مشخص را جستجو می‌کند. (با مشارکت Dave Cole و Barry Warsaw.)

  • تابع sys.exitfunc() منسوخ شده است. کد باید از ماژول موجود atexit استفاده کند که فراخوانی چندین تابع خروج را به‌درستی مدیریت می‌کند. در نهایت sys.exitfunc() به رابطی صرفاً داخلی تبدیل خواهد شد که تنها atexit به آن دسترسی خواهد داشت.

  • ماژول tarfile اکنون به‌طور پیش‌فرض پرونده‌های tar با قالب GNU تولید می‌کند. (مشارکت‌شده توسط لارس گوستابل.)

  • ماژول threading اکنون راهی ساده و زیبا برای پشتیبانی از داده‌های نخ‌محلی دارد. این ماژول شامل کلاس local است که مقادیر ویژگی‌های آن برای نخ‌های مختلف محلی است.

    import threading
    
    data = threading.local()
    data.number = 42
    data.url = ('www.python.org', 80)
    

    نخ‌های دیگر می‌توانند مقادیر خاص خود را برای ویژگی‌های number و url انتساب و بازیابی کنند. شما می‌توانید از local زیرکلاس‌سازی کنید تا ویژگی‌ها را مقداردهی اولیه کنید یا متدهایی اضافه کنید. (مشارکت‌شده توسط Jim Fulton.)

  • ماژول timeit اکنون زباله‌روبی دوره‌ای را در طول حلقه‌ی زمان‌سنجی به‌طور خودکار غیرفعال می‌کند. این تغییر زمان‌سنجی‌های متوالی را قابل مقایسه‌تر می‌کند. (مشارکت Raymond Hettinger.)

  • ماژول weakref اکنون از طیف گسترده‌تری از شیءها پشتیبانی می‌کند؛ از جمله توابع پایتون، نمونه‌های کلاس، مجموعه‌ها، frozensetها، صف‌های دوطرفه، آرایه‌ها، پرونده‌ها، سوکت‌ها و شیءهای الگوی عبارت باقاعده. (مشارکت‌شده توسط Raymond Hettinger.)

  • ماژول xmlrpclib اکنون از یک افزونه‌ی چندفراخوانی (multi-call) برای ارسال چندین فراخوانی XML-RPC در یک عملیات HTTP واحد پشتیبانی می‌کند. (با مشارکت برایان کوئینلن.)

  • ماژول‌های mpz، rotor و xreadlines حذف شده‌اند.

cookielib

کتابخانه‌ی cookielib از مدیریت سمت کلاینت کوکی‌های HTTP پشتیبانی می‌کند و همتای پشتیبانی سمت سرور کوکی در ماژول Cookie است. کوکی‌ها در ظرف کوکی (cookie jar) ذخیره می‌شوند؛ این کتابخانه به‌طور شفاف کوکی‌های ارائه‌شده از سوی سرور وب را در ظرف کوکی ذخیره می‌کند و هنگام اتصال به سرور، کوکی را از ظرف برمی‌دارد. مانند مرورگرهای وب، شیءهای سیاست کنترل می‌کنند که کوکی‌ها پذیرفته شوند یا خیر.

به منظور ذخیره‌ی کوکی‌ها بین نشست‌ها، دو پیاده‌سازی از ظرف کوکی (cookie jar) فراهم شده است: یکی که کوکی‌ها را در قالب Netscape ذخیره می‌کند تا برنامه‌ها بتوانند از پرونده‌های کوکی Mozilla یا Lynx استفاده کنند، و دیگری که کوکی‌ها را در همان قالب کتابخانه libwww زبان Perl ذخیره می‌کند.

urllib2 به‌گونه‌ای تغییر کرده است که با cookielib تعامل داشته باشد: HTTPCookieProcessor یک ظرف کوکی (cookie jar) را مدیریت می‌کند که هنگام دسترسی به URL‌ها از آن استفاده می‌شود.

این ماژول توسط John J. Lee ارائه شده است.

doctest

ماژول doctest به لطف Edward Loper و Tim Peters دستخوش بازآرایی قابل توجهی شد. آزمون همچنان می‌تواند به سادگی اجرای doctest.testmod() باشد، اما این بازآرایی‌ها امکان سفارشی‌سازی عملکرد ماژول را به شیوه‌های گوناگون فراهم می‌کنند

کلاس جدید DocTestFinder آزمون‌ها را از رشته‌های مستند یک شیء معین استخراج می‌کند:

def f (x, y):
    """>>> f(2,2)
4
>>> f(3,2)
6
    """
    return x*y

finder = doctest.DocTestFinder()

# Get list of DocTest instances
tests = finder.find(f)

سپس کلاس جدید DocTestRunner آزمون‌های جداگانه را اجرا می‌کند و می‌تواند خلاصه‌ای از نتایج تولید کند:

runner = doctest.DocTestRunner()
for t in tests:
    tried, failed = runner.run(t)

runner.summarize(verbose=1)

مثال بالا خروجی زیر را تولید می‌کند:

1 items passed all tests:
   2 tests in f
2 tests in 1 items.
2 passed and 0 failed.
Test passed.

DocTestRunner برای مقایسه‌ی خروجی مورد انتظار با خروجی واقعی، از یک نمونه از کلاس OutputChecker استفاده می‌کند. این کلاس تعدادی پرچم مختلف دریافت می‌کند که رفتار آن را سفارشی می‌کنند؛ کاربران بلندپرواز همچنین می‌توانند یک زیرکلاس کاملاً جدید از OutputChecker بنویسند.

بررسی‌گر خروجی پیش‌فرض، تعدادی ویژگی کاربردی فراهم می‌کند. برای مثال، با پرچم گزینه‌ی doctest.ELLIPSIS، یک سه‌نقطه (...) در خروجی مورد انتظار با هر زیررشته‌ای تطبیق می‌کند، که این امر پذیرفتن خروجی‌هایی را که تفاوت‌های جزئی دارند آسان‌تر می‌کند:

def o (n):
    """>>> o(1)
<__main__.C instance at 0x...>
>>>
"""

رشته‌ی ویژه‌ی دیگری، <BLANKLINE>، با یک سطر خالی تطبیق می‌کند:

def p (n):
    """>>> p(1)
<BLANKLINE>
>>>
"""

قابلیت جدید دیگر، تولید نمایشی از خروجی به سبک تفاوت (diff) با مشخص کردن پرچم‌های گزینه‌ی doctest.REPORT_UDIFF (تفاوت‌های یکپارچه)، doctest.REPORT_CDIFF (تفاوت‌های زمینه‌ای) یا doctest.REPORT_NDIFF (به سبک دلتا) است. برای مثال:

def g (n):
    """>>> g(4)
here
is
a
lengthy
>>>"""
    L = 'here is a rather lengthy list of words'.split()
    for word in L[:n]:
        print word

هنگام اجرای آزمون‌های تابع فوق با تعیین doctest.REPORT_UDIFF، خروجی زیر را دریافت می‌کنید:

**********************************************************************
File "t.py", line 15, in g
Failed example:
    g(4)
Differences (unified diff with -expected +actual):
    @@ -2,3 +2,3 @@
     is
     a
    -lengthy
    +rather
**********************************************************************

تغییرات ساخت و C API

برخی از تغییرات در فرایند ساخت پایتون و در API زبان C عبارت‌اند از:

  • سه ماکروی جدید برای راحتی بازگرداندن مقادیر رایج از توابع توسعه‌ای اضافه شدند: Py_RETURN_NONE، Py_RETURN_TRUE و Py_RETURN_FALSE. (مشارکت‌شده توسط Brett Cannon.)

  • یک ماکرو جدید دیگر، Py_CLEAR، شمارش ارجاع obj را کاهش می‌دهد و obj را به اشاره‌گر تهی تنظیم می‌کند. (مشارکت‌شده توسط Jim Fulton.)

  • تابع جدید PyTuple_Pack(N, obj1, obj2, ..., objN) تاپل‌ها را از یک فهرست آرگومان با طول متغیر از اشیاء پایتون می‌سازد. (ارائه‌شده توسط Raymond Hettinger.)

  • تابع جدید، PyDict_Contains(d, k)، جستجوهای سریع دیکشنری را پیاده‌سازی می‌کند، بدون آنکه استثناهای ایجادشده در طول فرایند جستجو را پوشاند. (مشارکت از Raymond Hettinger.)

  • ماکروی Py_IS_NAN در صورتی که آرگومان اعشاری یا ممیز شناور با دقت مضاعف آن، X، یک NaN باشد، مقدار ۱ را برمی‌گرداند. (مشارکت‌شده توسط تیم پیترز.)

  • کد C می‌تواند با استفاده از تابع جدید PyEval_ThreadsInitialized() که مشخص می‌کند آیا عملیات‌های نخ انجام شده‌اند یا نه، از قفل‌گذاری غیرضروری اجتناب کند. اگر این تابع مقدار نادرست برگرداند، هیچ عملیات قفلی لازم نیست. (با مشارکت Nick Coghlan.)

  • تابع جدید PyArg_VaParseTupleAndKeywords() مانند PyArg_ParseTupleAndKeywords() است، اما به جای تعدادی آرگومان، یک va_list می‌گیرد. (مشارکت‌شده توسط گرگ چپمن.)

  • پرچم متد جدید METH_COEXIST به تابعی که در جایگاه‌ها تعریف‌شده است اجازه می‌دهد با PyCFunction هم‌نام هم‌زیستی کند. این امر می‌تواند زمان دسترسی به متدی مانند set.__contains__() را به نصف کاهش دهد. (مشارکت‌شده توسط Raymond Hettinger.)

  • اکنون می‌توان پایتون را با پروفایل‌گیری اضافی برای خودِ مفسر ساخت که به‌عنوان کمکی برای توسعه‌دهندگان هسته‌ی پایتون در نظر گرفته شده است. ارائه‌ی --enable-profiling به اسکریپت configure به شما امکان می‌دهد مفسر را با gprof پروفایل‌گیری کنید، و ارائه‌ی سوییچ --with-tsc امکان پروفایل‌گیری با استفاده از ثبات شمارنده‌ی زمان (Time-Stamp-Counter) پنتیوم را فراهم می‌کند. توجه داشته باشید که نام سوییچ --with-tsc اندکی نادرست انتخاب شده است، زیرا قابلیت پروفایل‌گیری روی پلتفرم PowerPC نیز کار می‌کند، هرچند در آن معماری پردازنده این ثبات «ثبات TSC» نامیده نمی‌شود. (مشارکت‌شده توسط جرمی هایلتون.)

  • نوع tracebackobject به PyTracebackObject تغییر نام داده شده است.

تغییرات خاص پورت

  • نسخه‌ی ویندوزی اکنون علاوه بر نسخه‌ی 6، با MSVC++ 7.1 نیز ساخته می‌شود. (با مشارکت Martin von Löwis.)

انتقال به پایتون 2.4

این بخش تغییراتی را که پیش‌تر شرح داده‌شده‌اند و ممکن است نیازمند تغییراتی در کد شما باشند، فهرست می‌کند:

  • شیفت‌های به چپ و ثابت‌های مبنای شانزده/هشت که بیش از حد بزرگ هستند، دیگر یک FutureWarning ایجاد نمی‌کنند و مقداری محدود به ۳۲ یا ۶۴ بیت برنمی‌گردانند؛ در عوض یک عدد صحیح بلند برمی‌گردانند.

  • عملیات عدد صحیح دیگر هشدار OverflowWarning را فعال نمی‌کنند. هشدار OverflowWarning در پایتون 2.5 حذف خواهد شد.

  • تابع توکار zip() و itertools.izip() اکنون اگر بدون آرگومان فراخوانی شوند، به جای ایجاد استثنای TypeError، یک فهرست خالی برمی‌گردانند.

  • دیگر نمی‌توانید نمونه‌های date و datetime ارائه‌شده توسط ماژول datetime را مقایسه کنید. دو نمونه از کلاس‌های مختلف اکنون همیشه نابرابر خواهند بود و مقایسه‌های نسبی (<، >) استثنای TypeError مطرح می‌کنند.

  • dircache.listdir() اکنون به‌جای بازگرداندن فهرست‌های خالی، استثناها را به فراخواننده منتقل می‌کند.

  • LexicalHandler.startDTD شناسه‌های عمومی و سیستمی را به ترتیب نادرست دریافت می‌کرد. این مورد اصلاح شده است؛ برنامه‌هایی که به ترتیب نادرست تکیه دارند باید اصلاح شوند.

  • fcntl.ioctl() اکنون در صورتی که آرگومان mutate حذف شده و مرتبط باشد، هشدار می‌دهد.

  • ماژول tarfile اکنون به‌صورت پیش‌فرض پرونده‌های tar با قالب GNU تولید می‌کند.

  • مواجهه با شکست هنگام ایمپورت کردن یک ماژول، دیگر شیء ماژول نیمه‌مقداردهی‌شده‌ای در sys.modules باقی نمی‌گذارد.

  • None اکنون یک ثابت است؛ کدی که مقدار جدیدی را به نام None مقید می‌کند، اکنون یک خطای نحوی است.

  • تابع signal.signal() اکنون برای برخی مقادیر غیرمجاز، استثنای RuntimeError ایجاد می‌کند؛ پیش‌تر این خطاها بی‌صدا نادیده گرفته می‌شدند. برای نمونه، دیگر نمی‌توانید روی سیگنال SIGKILL هندلری تنظیم کنید.

سپاسگزاری‌ها

نویسنده از افراد زیر برای ارائه پیشنهادها، اصلاحات و کمک در پیش‌نویس‌های مختلف این مقاله سپاسگزار است: Koray Can، Hye-Shik Chang، Michael Dyck، Raymond Hettinger، Brian Hurt، Hamish Lawson، Fredrik Lundh، Sean Reifschneider، Sadruddin Rejeb.