تازههای پایتون 2.5¶
- نویسنده:
A.M. Kuchling
این مقاله ویژگیهای جدید پایتون 2.5 را توضیح میدهد. نسخهی نهایی پایتون 2.5 برای اوت ۲۰۰۶ برنامهریزی شده است؛ PEP 356 برنامهی زمانبندی انتشار برنامهریزیشده را توصیف میکند. پایتون 2.5 در ۱۹ سپتامبر ۲۰۰۶ منتشر شد.
تغییرات پایتون 2.5 ترکیبی جالب از بهبودهای زبان و کتابخانه است. به نظر من، بهبودهای کتابخانه برای کامیونیتی کاربران پایتون اهمیت بیشتری خواهند داشت، زیرا چندین بستهی مفید و پرکاربرد افزوده شدهاند. ماژولهای جدید شامل ElementTree برای پردازش XML (xml.etree.ElementTree)، ماژول پایگاه دادهی SQLite (sqlite3) و ماژول ctypes برای فراخوانی توابع C هستند.
تغییرات زبان اهمیتی متوسط دارند. برخی ویژگیهای جدید و خوشایند اضافه شدهاند، اما بیشتر آنها ویژگیهایی نیستند که هر روز از آنها استفاده کنید. عبارتهای شرطی سرانجام با استفاده از نحوی نو به زبان اضافه شدند؛ به بخش PEP 308: عبارتهای شرطی مراجعه کنید. دستور جدید 'with' نوشتن کد پاکسازی را آسانتر خواهد کرد (بخش PEP 343: دستور 'with'). اکنون میتوان مقادیر را به تولیدگرها ارسال کرد (بخش PEP 342: قابلیتهای جدید تولیدگر). ایمپورتها اکنون میتوانند بهصورت مطلق یا نسبی باشند (بخش PEP 328: ایمپورتهای مطلق و نسبی). با برخی حالتهای خاص (corner case) در مدیریت استثنا بهتر برخورد میشود (بخش PEP 341: یکپارچهسازی try/except/finally). همه این بهبودها ارزشمند هستند، اما هر یک از آنها بهبودی در این یا آن ویژگی مشخص از زبان است؛ هیچکدام از آنها تغییرات گستردهای در معناشناسی پایتون نیستند.
علاوه بر افزودههای زبان و کتابخانه، بهبودها و رفع اشکالهای دیگری نیز در سراسر درخت کد منبع صورت گرفت. جستوجویی در گزارشهای تغییرات SVN نشان میدهد که بین پایتون 2.4 و 2.5، ۳۵۳ وصل اعمال شده و ۴۵۸ اشکال رفع شده است. (هر دو رقم احتمالاً دستکم گرفته شدهاند.)
این مقاله تلاش نمیکند که مشخصات کاملی از ویژگیهای جدید باشد؛ در عوض، تغییرات بهاختصار و با استفاده از مثالهای مفید معرفی میشوند. برای جزئیات کامل، همیشه باید به مستندات پایتون 2.5 در https://docs.python.org مراجعه کنید. اگر میخواهید پیادهسازی کامل و منطق طراحی را درک کنید، به PEP مربوط به ویژگی جدید مورد نظر مراجعه کنید.
از نظرات، پیشنهادها و گزارشهای خطا دربارهی این سند استقبال میشود؛ لطفاً آنها را از طریق ایمیل برای نویسنده ارسال کنید یا در رهگیر باگ پایتون (Python bug tracker) یک باگ ثبت کنید.
PEP 308: عبارتهای شرطی¶
مدتهاست که کاربران راهی برای نوشتن عبارتهای شرطی را درخواست کردهاند؛ عبارتهایی که بسته به درست یا نادرست بودن یک مقدار بولی، مقدار A یا مقدار B را برمیگردانند. عبارت شرطی به شما امکان میدهد یک دستور انتساب واحد بنویسید که همان اثر موارد زیر را داشته باشد:
if condition:
x = true_value
else:
x = false_value
بحثهای بیپایان و خستهکنندهای دربارهی سینتکس در هر دو python-dev و comp.lang.python صورت گرفته است. حتی یک رأیگیری برگزار شد که در آن مشخص شد اکثریت رأیدهندگان عبارتهای شرطی را به شکلی میخواهند، اما هیچ نحوی وجود نداشت که اکثریتی قاطع آن را ترجیح دهد. نامزدها شامل cond ? true_v : false_v زبان C، if cond then true_v else false_v و ۱۶ گونهی دیگر بودند.
Guido van Rossum در نهایت سینتکسی غافلگیرکننده را انتخاب کرد:
x = true_value if condition else false_value
ارزیابی همچنان مانند عبارتهای بولی موجود بهصورت تنبل انجام میشود، بنابراین ترتیب ارزیابی کمی جابهجا میشود. عبارت condition که در وسط قرار دارد ابتدا ارزیابی میشود و عبارت true_value تنها در صورتی ارزیابی میشود که شرط درست باشد. بهطور مشابه، عبارت false_value تنها زمانی ارزیابی میشود که شرط نادرست باشد.
این سینتکس ممکن است عجیب و وارونه به نظر برسد؛ چرا شرط در وسط عبارت قرار میگیرد و نه در ابتدای آن، مانند c ? x : y در زبان C؟ این تصمیم با اعمال سینتکس جدید بر ماژولهای کتابخانه استاندارد و بررسی خوانایی کد حاصل، راستیآزمایی شد. در بسیاری از مواردی که از عبارت شرطی استفاده میشود، یک مقدار «حالت رایج» به نظر میرسد و یک مقدار «حالت استثنایی» است که تنها در مواقع نادرتر، هنگامی که شرط برقرار نیست، استفاده میشود. سینتکس شرطی این الگو را کمی آشکارتر میکند:
contents = ((doc + '\n') if doc else '')
جملهی بالا را به این معنا تفسیر میکنم که «اینجا معمولاً مقدار doc+'\n' به contents انتساب داده میشود؛ گاهی doc خالی است که در این حالت خاص، یک رشتهی خالی برگردانده میشود.» بعید میدانم که عبارتهای شرطی را در مواردی که حالت رایج و نادرِ واضحی وجود ندارد، زیاد به کار ببرم.
بحثهایی دربارهی اینکه آیا زبان باید احاطهکردن عبارتهای شرطی با پرانتز را الزامی کند، صورت گرفت. تصمیم گرفته شد که در گرامر زبان پایتون پرانتز الزامی نباشد، اما از نظر سبک، به نظر من شما همیشه باید از آنها استفاده کنید. این دو دستور را در نظر بگیرید:
# First version -- no parens
level = 1 if logging else 0
# Second version -- with parens
level = (1 if logging else 0)
در نسخهی اول، به نظرم ممکن است چشم خواننده دستور را به بخشهای 'level = 1'، 'if logging' و 'else 0' گروهبندی کند و تصور کند که شرط تعیین میکند آیا انتساب به level انجام میشود یا خیر. به نظر من، نسخهی دوم خواناتر است، زیرا بهروشنی نشان میدهد که انتساب همیشه انجام میشود و انتخاب بین دو مقدار صورت میگیرد.
دلیل دیگری برای گنجاندن کروشهها: برخی ترکیبهای عجیب از درکهای فهرستی و لامبداها ممکن است شبیه عبارتهای شرطی نادرست به نظر برسند. برای دیدن چند نمونه، PEP 308 را ببینید. اگر دور عبارتهای شرطی خود پرانتز بگذارید، با این حالت مواجه نخواهید شد.
همچنین ملاحظه نمائید
- PEP 308 - عبارتهای شرطی
PEP نوشتهشده توسط گیدو فان روسوم و ریموند دی. هتینگر؛ پیادهسازیشده توسط توماس ووترز.
PEP 309: اعمال جزئی تابع¶
ماژول functools در نظر گرفتهشده است تا ابزارهایی برای برنامهنویسی به سبک تابعی را در بر بگیرد.
یکی از ابزارهای سودمند این ماژول، تابع partial() است. برای برنامههایی که به سبک تابعی نوشته میشوند، گاهی اوقات ممکن است بخواهید گونههایی از توابع موجود بسازید که برخی از پارامترهایشان از پیش پر شده باشد. تابع پایتونی f(a, b, c) را در نظر بگیرید؛ میتوانید تابع جدیدی g(b, c) بسازید که معادل f(1, b, c) باشد. به این کار «اعمال جزئی تابع» (partial function application) گفته میشود.
partial() آرگومانهای (function, arg1, arg2, ... kwarg1=value1, kwarg2=value2) را میگیرد. شیء حاصل فراخوانیپذیر است، بنابراین میتوانید بهسادگی آن را فراخوانی کنید تا تابع با آرگومانهای تکمیلشده اجرا شود.
این یک مثال کوچک اما واقعگرایانه است:
import functools
def log (message, subsystem):
"Write the contents of 'message' to the specified subsystem."
print '%s: %s' % (subsystem, message)
...
server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')
این مثال دیگری است، از برنامهای که از PyGTK استفاده میکند. در اینجا یک منوی بازشوی حساس به زمینه بهصورت پویا ساخته میشود. کالبکی که برای گزینهی منو فراهم شده است، نسخهای از متد open_item() است که اعمال جزئی روی آن انجام شده و آرگومان اول آن ارائه شده است.
...
class Application:
def open_item(self, path):
...
def init (self):
open_func = functools.partial(self.open_item, item_path)
popup_menu.append( ("Open", open_func, 1) )
تابع دیگری در ماژول functools، update_wrapper(wrapper, wrapped) است که به شما کمک میکند دکوراتورهای خوشرفتار بنویسید. update_wrapper() ویژگیهای نام، ماژول و رشته مستند را در تابع پوششی کپی میکند تا ردگیریهای پشته درون تابع دربرگرفتهشده آسانتر قابل درک باشند. برای مثال، ممکن است بنویسید:
def my_decorator(f):
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
functools.update_wrapper(wrapper, f)
return wrapper
wraps() یک دکوراتور است که میتوانید آن را درون دکوراتورهای خودتان به کار ببرید تا اطلاعات تابع دربرگرفتهشده را کپی کند. نسخهی جایگزین مثال قبلی به این صورت خواهد بود:
def my_decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
return wrapper
همچنین ملاحظه نمائید
- PEP 309 - اعمال جزئی تابع
PEP توسط پیتر هریس پیشنهاد و نوشته شد؛ توسط ههشیک چانگ و نیک کوگلان پیادهسازی شد و ریموند هتینگر تطبیقهایی بر آن انجام داد.
PEP 314: فراداده برای بستههای نرمافزاری پایتون v1.1¶
پشتیبانی سادهای از وابستگیها به Distutils اضافه شد. تابع setup() اکنون پارامترهای کلیدواژهای requires، provides و obsoletes را دارد. هنگامی که با استفاده از دستور sdist یک توزیع کد منبع میسازید، اطلاعات وابستگی در پروندهی PKG-INFO ثبت خواهد شد.
پارامتر کلیدواژهای جدید دیگری نیز download_url است که باید روی URL مربوط به کد منبع بسته تنظیم شود. این بدان معناست که اکنون میتوان یک ورودی را در فهرست بستهها جستوجو کرد، وابستگیهای یک بسته را تعیین کرد و بستههای موردنیاز را بارگیری کرد.
VERSION = '1.0'
setup(name='PyPackage',
version=VERSION,
requires=['numarray', 'zlib (>=1.1.4)'],
obsoletes=['OldPackage']
download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
% VERSION),
)
بهبود جدید دیگری در فهرست بستههای پایتون در https://pypi.org، ذخیرهسازی آرشیوهای سورس و دودویی برای یک بسته است. دستور جدید upload در Distutils یک بسته را به مخزن بارگذاری میکند.
پیش از آنکه بتوان بستهای را بارگذاری کرد، باید بتوانید با استفاده از دستور sdist در Distutils یک توزیع بسازید. وقتی این کار با موفقیت انجام شد، میتوانید python setup.py upload را اجرا کنید تا بستهتان را به آرشیو PyPI اضافه کنید. بهصورت اختیاری میتوانید با ارائه گزینههای --sign و --identity بسته را با GPG امضا کنید.
بارگذاری بسته توسط مارتین فون لویس و ریچارد جونز پیادهسازی شد.
همچنین ملاحظه نمائید
- PEP 314 - فراداده برای بستههای نرمافزاری پایتون v1.1
PEP توسط A.M. Kuchling، Richard Jones و Fred Drake پیشنهاد و نوشته شد؛ پیادهسازی آن توسط Richard Jones و Fred Drake انجام شد.
PEP 328: ایمپورتهای مطلق و نسبی¶
بخش سادهترِ PEP 328 در Python 2.4 پیادهسازی شد: اکنون میشد از پرانتزها برای دربرگرفتن نامهایی که با دستور from ... import ... از یک ماژول ایمپورت میشدند استفاده کرد، که این امر ایمپورت کردن نامهای متعدد و مختلف را آسانتر میکرد.
بخش پیچیدهتر در پایتون 2.5 پیادهسازی شده است: میتوان مشخص کرد که ایمپورت کردن یک ماژول از ایمپورتهای مطلق یا نسبی به بسته استفاده کند. برنامه این است که در نسخههای آینده پایتون، ایمپورتهای مطلق به پیشفرض تبدیل شوند.
فرض کنید پوشهی بستهای به شکل زیر دارید:
pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py
این یک بسته به نام pkg تعریف میکند که شامل زیرماژولهای pkg.main و pkg.string است.
کد موجود در ماژول main.py را در نظر بگیرید. اگر این آپکد import string را اجرا کند، چه اتفاقی میافتد؟ در پایتون 2.4 و نسخههای پیش از آن، ابتدا در پوشهی بسته جستوجو میکند تا یک ایمپورت نسبی انجام دهد، pkg/string.py را مییابد، محتویات آن پرونده را بهعنوان ماژول pkg.string ایمپورت میکند، و آن ماژول در فضای نام ماژول pkg.main به نام string مقید میشود.
اگر pkg.string همان چیزی بود که میخواستید، این اشکالی ندارد. اما اگر ماژول استاندارد string پایتون را میخواستید چه؟ هیچ راه تمیزی برای نادیده گرفتن pkg.string و یافتن ماژول استاندارد وجود ندارد؛ بهطور کلی مجبور بودید محتوای sys.modules را بررسی کنید، که این کار کمی ناتمیز است. بستهی py.std که Holger Krekel نوشته است، راه مرتبتری برای انجام ایمپورت از کتابخانه استاندارد فراهم میکند، import py; py.std.string.join()، اما این بسته در همهی نصبهای پایتون در دسترس نیست.
خواندن کدی که به ایمپورتهای نسبی متکی است نیز کمتر روشن است، زیرا خواننده ممکن است در تشخیص اینکه کدام ماژول — string یا pkg.string — برای استفاده در نظر گرفته شده است، دچار سردرگمی شود. کاربران پایتون بهزودی آموختند که نام ماژولهای کتابخانه استاندارد را در نام زیرماژولهای بستههای خود تکرار نکنند، اما نمیتوانید مانع آن شوید که نام زیرماژول شما برای ماژول جدیدی که در نسخهای آینده از پایتون اضافه میشود، استفاده شود.
در پایتون 2.5، میتوانید رفتار import را با استفاده از دایرکتیو from __future__ import absolute_import به ایمپورت مطلق تغییر دهید. این رفتار ایمپورت مطلق در نسخهای در آینده (احتمالاً پایتون 2.7) پیشفرض خواهد شد. وقتی که ایمپورتهای مطلق پیشفرض شوند، import string همیشه نسخهی کتابخانه استاندارد را پیدا خواهد کرد. پیشنهاد میشود کاربران تا حد ممکن شروع به استفاده از ایمپورتهای مطلق کنند، بنابراین بهتر است نوشتن from pkg import string را در کد خود آغاز کنید.
ایمپورتهای نسبی همچنان با افزودن نقطهای به ابتدای نام ماژول هنگام استفاده از صورت from ... import ممکن هستند:
# Import names from pkg.string
from .string import name1, name2
# Import pkg.string
from . import string
این دستور ماژول string را نسبت به بسته فعلی ایمپورت میکند، بنابراین در pkg.main این دستور name1 و name2 را از pkg.string ایمپورت خواهد کرد. نقطههای ابتدایی اضافی، ایمپورت نسبی را از والد بسته فعلی آغاز میکنند. برای مثال، کد موجود در ماژول A.B.C میتواند این کار را انجام دهد:
from . import D # Imports A.B.D
from .. import E # Imports A.E
from ..F import G # Imports A.F.G
نقطههای ابتدایی را نمیتوان با شکل import modname از دستور ایمپورت به کار برد؛ این نقطهها فقط با شکل from ... import قابل استفادهاند.
همچنین ملاحظه نمائید
- PEP 328 - ایمپورتها: چندسطری و مطلق/نسبی
PEP نوشتهشده توسط Aahz؛ پیادهسازیشده توسط Thomas Wouters.
- https://pylib.readthedocs.io/
کتابخانهی py نوشتهی Holger Krekel، که بستهی
py.stdرا در بر میگیرد.
PEP 338: اجرای ماژولها بهعنوان اسکریپت¶
سوییچ -m که در پایتون 2.4 برای اجرای یک ماژول بهعنوان اسکریپت افزوده شده بود، چند قابلیت دیگر نیز به دست آورد. بهجای آنکه در کد C درون مفسر پایتون پیادهسازی شود، این سوییچ اکنون از پیادهسازی موجود در ماژول جدید runpy استفاده میکند.
ماژول runpy یک سازوکار ایمپورت پیشرفتهتر را پیادهسازی میکند بهطوریکه اکنون میتوان ماژولهایی را در بستهای مانند pychecker.checker اجرا کرد. این ماژول همچنین از سازوکارهای ایمپورت جایگزین مانند ماژول zipimport پشتیبانی میکند. این بدان معناست که میتوانید مسیر یک آرشیو .zip را به sys.path اضافه کنید و سپس با استفاده از سوئیچ -m کد را از آرشیو اجرا کنید.
همچنین ملاحظه نمائید
- PEP 338 - اجرای ماژولها بهعنوان اسکریپت
PEP نوشته و پیادهسازیشده توسط نیک کولان.
PEP 341: یکپارچهسازی try/except/finally¶
تا پیش از پایتون 2.5، دستور try دو گونه داشت. میتوانستید از یک بلوک finally برای اطمینان از اینکه کد همیشه اجرا میشود استفاده کنید، یا از یک یا چند بلوک except برای گرفتن استثناهای خاص. نمیتوانستید هم بلوکهای except و هم یک بلوک finally را با هم ترکیب کنید، زیرا تولید بایتکد درست برای نسخهی ترکیبی پیچیده بود و مشخص نبود که معناشناسی دستور ترکیبی چه باید باشد.
گیدو ون روسوم مدتی با جاوا کار کرد، زبانی که از معادل ترکیب بلوکهای except و یک بلوک finally پشتیبانی میکند، و این موضوع روشن کرد که این دستور باید چه معنایی داشته باشد. در پایتون 2.5، اکنون میتوانید بنویسید:
try:
block-1 ...
except Exception1:
handler-1 ...
except Exception2:
handler-2 ...
else:
else-block
finally:
final-block
کدِ درون block-1 اجرا میشود. اگر کد استثنایی ایجاد کند، بلوکهای مختلف except بررسی میشوند: اگر استثنا از کلاس Exception1 باشد، handler-1 اجرا میشود؛ در غیر این صورت اگر از کلاس Exception2 باشد، handler-2 اجرا میشود، و به همین ترتیب. اگر هیچ استثنایی ایجاد نشود، else-block اجرا میشود.
صرفنظر از اینکه پیشتر چه اتفاقی افتاده باشد، بلوک پایانی پس از کامل شدن بلوک کد و مدیریت هر استثنای مطرحشده اجرا میشود. حتی اگر در هندلر استثنا یا بلوک else خطایی رخ دهد و استثنای جدیدی مطرح شود، کد موجود در بلوک پایانی همچنان اجرا میشود.
همچنین ملاحظه نمائید
- PEP 341 - یکپارچهسازی try-except و try-finally
PEP (پیشنهاد بهبود پایتون) نوشتهشده توسط Georg Brandl؛ پیادهسازی توسط Thomas Lee.
PEP 342: قابلیتهای جدید تولیدگر¶
پایتون 2.5 راهی ساده برای ارسال مقادیر به درون یک تولیدگر اضافه میکند. همانطور که در پایتون 2.3 معرفی شد، تولیدگرها فقط خروجی تولید میکنند؛ پس از آنکه کد یک تولیدگر برای ایجاد یک پیمایشگر فراخوانی میشد، هیچ راهی برای ارسال اطلاعات جدیدی به درون تابع هنگام از سرگیری اجرای آن وجود نداشت. گاهی توانایی ارسال مقداری اطلاعات به درون آن مفید خواهد بود. راهحلهای هکوار (hackish) برای این مشکل شامل این موارد است: وادار کردن کد تولیدگر به بررسی یک متغیر سراسری و سپس تغییر دادن مقدار آن متغیر سراسری، یا ارسال یک شیء تغییرپذیر که فراخوانندهها سپس آن را تغییر میدهند.
برای یادآوری تولیدگرهای پایهای، در اینجا یک مثال ساده آورده شده است:
def counter (maximum):
i = 0
while i < maximum:
yield i
i += 1
وقتی counter(10) را فراخوانی میکنید، نتیجه یک پیمایشگر است که مقادیر از ۰ تا ۹ را برمیگرداند. هنگام مواجهه با دستور yield، پیمایشگر مقدار ارائهشده را برمیگرداند، اجرای تابع را معلق میکند و متغیرهای محلی را حفظ میکند. اجرا در فراخوانی بعدی متد next() پیمایشگر از سر گرفته میشود و از بعد از دستور yield ادامه مییابد.
در پایتون 2.3، yield یک دستور بود؛ هیچ مقداری را برنمیگرداند. در 2.5، yield اکنون یک عبارت است و مقداری را برمیگرداند که میتوان آن را به یک متغیر منتسب کرد یا به سینتکس دیگری روی آن عمل کرد:
val = (yield i)
توصیه میکنم که همیشه هنگام انجام کاری با مقدار بازگشتی، دور عبارت yield پرانتز قرار دهید، همانطور که در مثال بالا آمده است. پرانتزها همیشه ضروری نیستند، اما همیشه اضافه کردن آنها آسانتر از آن است که مجبور باشید به یاد بیاورید چه زمانی به آنها نیاز است.
(PEP 342 قوانین دقیق را توضیح میدهد که بر اساس آنها یک عبارت yield همیشه باید داخل پرانتز قرار گیرد، مگر آنکه در بالاترین سطح عبارت سمت راست یک انتساب ظاهر شود. این بدان معناست که میتوانید val = yield i بنویسید، اما وقتی عملیاتی در میان است، باید از پرانتز استفاده کنید، مانند val = (yield i) + 12.)
مقادیر با فراخوانی متد send(value) آن به داخل تولیدگر فرستاده میشوند. سپس کد تولیدگر از سر گرفته میشود و عبارت yield مقدار مشخصشده را برمیگرداند. اگر متد عادی next() فراخوانی شود، yield مقدار None را برمیگرداند.
این همان مثال قبلی است که برای امکان تغییر مقدار شمارنده داخلی، تغییر داده شده است.
def counter (maximum):
i = 0
while i < maximum:
val = (yield i)
# If value provided, change counter
if val is not None:
i = val
else:
i += 1
و اینجا مثالی از تغییر دادن شمارنده:
>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
File "t.py", line 15, in ?
print it.next()
StopIteration
yield معمولاً None را برمیگرداند، بنابراین باید همیشه این حالت را بررسی کنید. مقدار آن را بهسادگی در عبارتها بهکار نبرید، مگر اینکه مطمئن باشید متد send() تنها متدی خواهد بود که برای ادامه دادن تابع تولیدگر شما استفاده میشود.
علاوه بر send()، دو متد جدید دیگر نیز روی تولیدگرها وجود دارد:
throw(type, value=None, traceback=None)برای ایجاد استثنا درون تولیدگر استفاده میشود؛ این استثنا توسط عبارتyieldکه اجرای تولیدگر در آن مکث کرده است، ایجاد میشود.close()یک استثنای جدیدGeneratorExitرا درون تولیدگر raise میکند تا به پیمایش پایان دهد. پس از دریافت این استثنا، کد تولیدگر باید یاGeneratorExitیاStopIterationرا raise کند. گرفتن استثنایGeneratorExitو برگرداندن یک مقدار، غیرمجاز است و یکRuntimeErrorرا بهوجود خواهد آورد؛ اگر تابع استثنای دیگری raise کند، آن استثنا به فراخواننده منتقل میشود.close()همچنین هنگامی که تولیدگر زبالهروبی میشود، توسط زبالهروب پایتون فراخوانی خواهد شد.اگر نیاز دارید هنگام رخ دادن
GeneratorExitکد پاکسازی را اجرا کنید، پیشنهاد میکنم بهجای گرفتنGeneratorExitاز یک بدنهیtry: ... finally:استفاده کنید.
اثر تجمعی این تغییرات آن است که تولیدگرها را از تولیدکنندههای یکطرفهی اطلاعات به هم تولیدکننده و هم مصرفکننده تبدیل میکند.
تولیدگرها همچنین به همروالها تبدیل میشوند که شکلی عمومیتر از زیرروالها هستند. زیرروالها در یک نقطه وارد و در نقطهای دیگر خارج میشوند (ابتدای تابع و دستور return)، اما همروالها میتوانند در نقاط مختلف بسیاری وارد، خارج و از سر گرفته شوند (دستورهای yield). باید الگوهایی برای استفادهی مؤثر از همروالها در پایتون بیابیم.
افزودن متد close() یک اثر جانبی دارد که بدیهی نیست. متد close() زمانی فراخوانی میشود که یک تولیدگر زبالهروبی شود؛ بنابراین این بدان معناست که کد تولیدگر پیش از نابود شدن تولیدگر، یک فرصت آخر برای اجرا شدن به دست میآورد. این فرصت آخر بدان معناست که اکنون میتوان تضمین کرد دستورهای try...finally در تولیدگرها کار میکنند؛ بند finally از این پس همیشه فرصتی برای اجرا شدن خواهد داشت. به همین دلیل، محدودیت نحویای که بر اساس آن نمیتوانستید دستورهای yield را با بدنهی try...finally ترکیب کنید، حذف شده است. این موضوع بهظاهر تنها یک نکتهی جزئی دربارهی زبان است، اما در واقع استفاده از تولیدگرها و try...finally برای پیادهسازی دستور with که در PEP 343 توصیف شده است ضروری است. در بخش بعدی، این دستور جدید را بررسی خواهم کرد.
اثر دیگر و حتی مبهمتر این تغییر: پیشتر، ویژگی gi_frame یک تولیدگر همیشه یک شیء فریم بود. اکنون ممکن است gi_frame پس از تمامشدن تولیدگر None باشد.
همچنین ملاحظه نمائید
- PEP 342 - همروالها از طریق تولیدگرهای بهبودیافته
PEP نوشتهشده توسط Guido van Rossum و Phillip J. Eby؛ پیادهسازیشده توسط Phillip J. Eby. شامل نمونههایی از برخی کاربردهای پیشرفتهتر تولیدگرها بهعنوان همروال است.
نسخههای اولیه این قابلیتها در PEP 288 توسط Raymond Hettinger و PEP 325 توسط Samuele Pedroni پیشنهاد شدند.
- https://en.wikipedia.org/wiki/Coroutine
مدخل ویکیپدیا برای همروالها.
- https://web.archive.org/web/20160321211320/http://www.sidhe.org/~dan/blog/archives/000178.html
توضیحی دربارهی همروالها از دیدگاه پرل، نوشتهی Dan Sugalski.
PEP 343: دستور 'with'¶
دستور «with» کدهایی را که پیشتر برای اطمینان از اجرای کد پاکسازی از بلوکهای try...finally استفاده میکردند، شفافتر میسازد. در این بخش، این دستور را همانگونه که معمولاً به کار میرود بحث خواهم کرد. در بخش بعدی، جزئیات پیادهسازی را بررسی خواهم کرد و نشان خواهم داد که چگونه میتوان اشیایی را برای استفاده با این دستور نوشت.
دستور 'with' یک ساختار جدید برای کنترل جریان است که ساختار بنیادی آن چنین است:
with expression [as variable]:
with-block
عبارت ارزیابی میشود و باید به شیءای منجر شود که از پروتکل مدیریت زمینه پشتیبانی کند (یعنی متدهای __enter__() و __exit__() را داشته باشد.
متد __enter__() شیء پیش از اجرای with-block فراخوانی میشود و بنابراین میتواند کد راهاندازی را اجرا کند. این متد همچنین ممکن است مقداری را برگرداند که در صورت تعیین شدن، به نام variable مقید میشود. (دقت کنید که نتیجهی expression به variable انتساب داده نمیشود.)
پس از پایان اجرای بلوک with، متد __exit__() شیء فراخوانی میشود، حتی اگر بلوک استثنایی ایجاد کرده باشد، و بنابراین میتواند کد پاکسازی را اجرا کند.
برای فعالسازی این دستور در Python 2.5، باید دایرکتیو زیر را به ماژول خود اضافه کنید:
from __future__ import with_statement
این دستور در Python 2.6 همیشه فعال خواهد بود.
برخی از اشیاء استاندارد پایتون اکنون از پروتکل مدیریت زمینه پشتیبانی میکنند و میتوان از آنها با دستور 'with' استفاده کرد. اشیاء پرونده یکی از مثالها هستند:
with open('/etc/passwd', 'r') as f:
for line in f:
print line
... more processing code ...
پس از اجرای این دستور، شیء پرونده در f بهطور خودکار بسته شده خواهد بود، حتی اگر حلقهی for در میانهی بدنه استثنایی ایجاد کرده باشد.
توجه
در این حالت، f همان شیء است که توسط open() ایجاد شده است، زیرا __enter__() self را برمیگرداند.
قفلها و متغیرهای شرط ماژول threading نیز از دستور 'with' پشتیبانی میکنند:
lock = threading.Lock()
with lock:
# Critical section of code
...
قفل پیش از اجرای بلوک به دست گرفته میشود و همیشه پس از تکمیل بلوک آزاد میشود.
تابع جدید localcontext() در ماژول decimal ذخیره و بازگردانی زمینه اعشاری فعلی را آسان میکند؛ زمینهای که دقت و ویژگیهای گرد کردن مطلوب برای محاسبات را در بر میگیرد:
from decimal import Decimal, Context, localcontext
# Displays with default precision of 28 digits
v = Decimal('578')
print v.sqrt()
with localcontext(Context(prec=16)):
# All code in this block uses a precision of 16 digits.
# The original context is restored on exiting the block.
print v.sqrt()
نوشتن مدیرهای زمینه¶
در باطن، دستور 'with' نسبتاً پیچیده است. بیشتر افراد فقط 'with' را همراه با اشیاء موجود به کار میبرند و نیازی به دانستن این جزئیات ندارند، بنابراین در صورت تمایل میتوانید از باقی این بخش عبور کنید. نویسندگان اشیاء جدید باید جزئیات پیادهسازی زیربنایی را درک کنند و به خواندن ادامه دهند.
توضیح سطح بالای پروتکل مدیریت زمینه چنین است:
عبارت ارزیابی میشود و باید به شیئی به نام «مدیر زمینه» منجر شود. مدیر زمینه باید متدهای
__enter__()و__exit__()را داشته باشد.متد
__enter__()مدیر زمینه فراخوانی میشود. مقدار بازگشتی به VAR منتسب میشود. اگر بند'as VAR'وجود نداشته باشد، مقدار صرفاً دور انداخته میشود.کد موجود در BLOCK اجرا میشود.
اگر BLOCK استثنایی ایجاد کند،
__exit__(type, value, traceback)با جزئیات استثنا فراخوانی میشود؛ همان مقادیری کهsys.exc_info()برمیگرداند. مقدار بازگشتی متد کنترل میکند که استثنا دوباره ایجاد شود یا نه: هر مقدار کاذبی استثنا را دوباره ایجاد میکند وTrueموجب سرکوب آن خواهد شد. بهندرت پیش میآید که بخواهید استثنا را سرکوب کنید، زیرا اگر چنین کنید، نویسندهی کدی که دستور «with» در آن به کار رفته است، هرگز متوجه نخواهد شد که مشکلی پیش آمده است.اگر BLOCK استثنایی ایجاد نکرده باشد، متد
__exit__()همچنان فراخوانی میشود، اما type، value و traceback همگیNoneهستند.
بیایید یک مثال را بررسی کنیم. کد تفصیلی ارائه نمیکنم، بلکه تنها طرحی کلی از متدهای لازم برای پایگاه دادهای که از تراکنشها پشتیبانی میکند ارائه میکنم.
(برای افرادی که با اصطلاحات پایگاه داده آشنا نیستند: مجموعهای از تغییرات در پایگاه داده در قالب یک تراکنش گروهبندی میشوند. تراکنشها میتوانند یا ثبت نهایی شوند، به این معنا که تمام تغییرات در پایگاه داده نوشته میشوند، یا بازگردانی شوند، به این معنا که تمام تغییرات دور ریخته میشوند و پایگاه داده بدون تغییر باقی میماند. برای اطلاعات بیشتر به هر کتاب درسی پایگاه داده مراجعه کنید.)
فرض کنید شیئی وجود دارد که نمایانگر یک اتصال به پایگاه داده است. هدف ما این خواهد بود که به کاربر اجازه دهیم کدی مانند این بنویسد:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... more operations ...
تراکنش باید در صورتی که کد داخل بلوک بینقص اجرا شود، ثبت نهایی شود یا در صورت رخ دادن استثنا، بازگردانی شود. رابط پایهای که برای DatabaseConnection فرض میکنم به این صورت است:
class DatabaseConnection:
# Database interface
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
متد __enter__() بسیار ساده است و تنها باید یک تراکنش جدید را آغاز کند. برای این کاربرد، شیء نشانگرِ بهدستآمده نتیجهی مفیدی خواهد بود، بنابراین این متد آن را برمیگرداند. سپس کاربر میتواند as cursor را به دستور 'with' خود اضافه کند تا نشانگر را به یک نام متغیر مقید کند.
class DatabaseConnection:
...
def __enter__ (self):
# Code to start a new transaction
cursor = self.cursor()
return cursor
متد __exit__() پیچیدهترین متد است، زیرا بیشترِ کار باید در آن انجام شود. این متد باید بررسی کند که آیا استثنایی رخ داده است یا خیر. اگر استثنایی رخ نداده باشد، تراکنش ثبت نهایی میشود. اگر استثنایی رخ داده باشد، تراکنش بازگردانی میشود.
در کد زیر، اجرا صرفاً از انتهای تابع خارج میشود و مقدار پیشفرض None را برمیگرداند. None نادرست است، بنابراین استثنا بهطور خودکار مجدداً مطرح میشود. اگر مایل بودید، میتوانستید صریحتر عمل کنید و یک دستور return در مکان مشخصشده اضافه کنید.
class DatabaseConnection:
...
def __exit__ (self, type, value, tb):
if tb is None:
# No exception, so commit
self.commit()
else:
# Exception occurred, so rollback.
self.rollback()
# return False
ماژول contextlib¶
ماژول جدید contextlib تعدادی تابع و یک دکوراتور فراهم میکند که برای نوشتن اشیایی که در دستور 'with' به کار میروند مفید هستند.
این دکوراتور @~contextlib.contextmanager نام دارد و به شما اجازه میدهد به جای تعریف کلاس جدید، تنها یک تابع تولیدگر بنویسید. تولیدگر باید دقیقاً یک مقدار را yield کند. کد تا پیش از yield بهعنوان متد __enter__() اجرا خواهد شد و مقداری که yield میشود، مقدار بازگشتی این متد خواهد بود که در صورت وجود بند as در دستور «with»، به متغیر آن مقید خواهد شد. کد پس از yield در متد __exit__() اجرا خواهد شد. هر استثنایی که در بلوک ایجاد شود، توسط دستور yield ایجاد خواهد شد.
مثال پایگاه دادهی ما از بخش قبلی را میتوان با استفاده از این دکوراتور به صورت زیر نوشت:
from contextlib import contextmanager
@contextmanager
def db_transaction (connection):
cursor = connection.cursor()
try:
yield cursor
except:
connection.rollback()
raise
else:
connection.commit()
db = DatabaseConnection()
with db_transaction(db) as cursor:
...
ماژول contextlib همچنین تابع nested(mgr1, mgr2, ...) را دارد که تعدادی مدیر زمینه را ترکیب میکند تا نیازی به نوشتن دستورهای 'with' تودرتو نداشته باشید. در این مثال، دستور 'with' منفرد هم یک تراکنش پایگاه داده را آغاز میکند و هم یک قفل نخ را به دست میآورد:
lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
...
در نهایت، تابع closing(object) شیء را برمیگرداند تا بتواند به یک متغیر مقید شود و object.close را در پایان بلوک فراخوانی میکند.
import urllib, sys
from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f:
for line in f:
sys.stdout.write(line)
همچنین ملاحظه نمائید
- PEP 343 - دستور «with»
PEP نوشتهشده توسط Guido van Rossum و Nick Coghlan؛ پیادهسازیشده توسط Mike Bland، Guido van Rossum و Neal Norwitz. این PEP کد تولیدشده برای دستور «
with» را نشان میدهد که میتواند در یادگیری نحوهی کارکرد این دستور مفید باشد.
مستندات ماژول contextlib.
PEP 352: استثناها بهعنوان کلاسهای سبک جدید¶
کلاسهای استثنا اکنون میتوانند کلاسهای سبک جدید باشند، نه فقط کلاسهای کلاسیک، و کلاس توکار Exception و تمام استثناهای توکار استاندارد (NameError، ValueError و غیره) اکنون کلاسهای سبک جدید هستند.
سلسلهمراتب وراثت استثناها کمی بازآرایی شده است. در 2.5، روابط وراثت به شرح زیر است:
BaseException # New in Python 2.5
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (تمام سایر استثناهای توکار فعلی)
این بازآرایی به این دلیل انجام شد که افراد اغلب میخواهند همهی استثناهایی را که نشاندهندهی خطاهای برنامه هستند بگیرند. اما KeyboardInterrupt و SystemExit خطا نیستند و معمولاً نمایانگر یک کنش صریح هستند، مانند فشردن Control-C توسط کاربر یا فراخوانی sys.exit() از سوی کد. یک except: خالی همهی استثناها را میگیرد، بنابراین معمولاً باید KeyboardInterrupt و SystemExit را ذکر کنید تا دوباره raise شوند. الگوی معمول چنین است:
try:
...
except (KeyboardInterrupt, SystemExit):
raise
except:
# Log error...
# Continue running program...
در پایتون 2.5، اکنون میتوانید برای دستیابی به همان نتیجه، except Exception بنویسید که همهی استثناهایی را که معمولاً نشاندهندهی خطا هستند میگیرد، اما KeyboardInterrupt و SystemExit را دستنخورده باقی میگذارد. مانند نسخههای قبلی، except: خالی همچنان همهی استثناها را میگیرد.
هدف پایتون 3.0 این است که هر کلاسی که بهعنوان استثنا raise میشود، الزاماً از BaseException یا فرزندی از BaseException مشتق شده باشد، و ممکن است نسخههای آتی در سری پایتون 2.x شروع به اعمال این محدودیت کنند. بنابراین، پیشنهاد میکنم از همین حالا همه کلاسهای استثنای خود را از Exception مشتق کنید. پیشنهاد شده است که شکل خالی except: در پایتون 3.0 حذف شود، اما گیدو ون روسوم هنوز تصمیم نگرفته است که این کار را انجام دهد یا خیر.
پرتاب رشتهها بهعنوان استثنا، مانند دستور raise "Error occurred"، در پایتون 2.5 منسوخ شده است و هشداری را فعال خواهد کرد. هدف این است که بتوان ویژگی استثناهای رشتهای را در چند نسخهی آینده حذف کرد.
همچنین ملاحظه نمائید
- PEP 352 - ابرکلاس مورد نیاز برای استثناها
PEP نوشتهشده توسط برت کانون و گیدو ون روسوم؛ پیادهسازیشده توسط برت کانون.
PEP 353: استفاده از ssize_t بهعنوان نوع اندیس¶
تغییر گستردهای در C API پایتون که به جای int از تعریف نوع جدید Py_ssize_t استفاده میکند، به مفسر اجازه میدهد تا در پلتفرمهای ۶۴ بیتی دادههای بیشتری را مدیریت کند. این تغییر بر ظرفیت پایتون در پلتفرمهای ۳۲ بیتی تأثیری نمیگذارد.
بخشهای گوناگونی از مفسر پایتون از نوع int زبان C برای ذخیرهسازی اندازهها یا تعدادها استفاده میکردند؛ برای مثال، تعداد آیتمهای یک فهرست یا تاپل در یک int ذخیره میشد. کامپایلرهای C برای بیشتر پلتفرمهای ۶۴ بیتی هنوز int را بهصورت یک نوع ۳۲ بیتی تعریف میکنند، بنابراین این بدان معنا بود که فهرستها حداکثر میتوانستند 2**31 - 1 = 2147483647 آیتم را در خود جای دهند. (در واقع چند مدل برنامهنویسی متفاوت وجود دارد که کامپایلرهای ۶۴ بیتی زبان C میتوانند از آنها استفاده کنند -- برای بحثی در این باره به https://unix.org/version2/whatsnew/lp64_wp.html مراجعه کنید -- اما رایجترین مدل در دسترس، int را ۳۲ بیتی باقی میگذارد.)
محدودیتی بر ۲۱۴۷۴۸۳۶۴۷ آیتم روی یک پلتفرم ۳۲ بیتی واقعاً اهمیتی ندارد، زیرا پیش از برخورد به محدودیت طول، حافظهتان تمام میشود. هر آیتم فهرست به فضایی برای یک اشارهگر — که ۴ بایت است — بهعلاوهی فضایی برای یک PyObject که نمایندهی آن آیتم است، نیاز دارد. ۲۱۴۷۴۸۳۶۴۷*۴ بهخودیخود از تعداد بایتهایی که یک فضای آدرس ۳۲ بیتی میتواند در بر بگیرد بیشتر است.
با این حال، آدرسدهی این مقدار حافظه روی یک پلتفرم ۶۴بیتی ممکن است. اشارهگرهای فهرستی با چنین اندازهای تنها به ۱۶ گیبایت فضا نیاز خواهند داشت، بنابراین دور از انتظار نیست که برنامهنویسان پایتون فهرستهایی به آن بزرگی بسازند. در نتیجه، مفسر پایتون باید تغییر میکرد تا از نوعی غیر از int استفاده کند، و این نوع روی پلتفرمهای ۶۴بیتی یک نوع ۶۴بیتی خواهد بود. این تغییر روی رایانههای ۶۴بیتی ناسازگاریهایی ایجاد خواهد کرد، از این رو تشخیص داده شد که گذار را همین حالا انجام دادن میارزد، در حالی که تعداد کاربران ۶۴بیتی هنوز نسبتاً کم است. (در ۵ یا ۱۰ سال، ممکن است همه ما روی رایانههای ۶۴بیتی باشیم و در آن زمان گذار دردناکتر خواهد بود.)
این تغییر بیشترین تأثیر را بر نویسندگان ماژولهای توسعهای C میگذارد. رشتههای پایتون و نوعهای ظرف مانند فهرستها و تاپلها اکنون از Py_ssize_t برای ذخیرهی اندازه خود استفاده میکنند. توابعی مانند PyList_Size() اکنون Py_ssize_t برمیگردانند. بنابراین ممکن است کد موجود در ماژولهای توسعهای نیاز داشته باشد برخی از متغیرهای خود را به Py_ssize_t تغییر دهد.
توابع PyArg_ParseTuple() و Py_BuildValue() یک کد تبدیل جدید با نام n برای Py_ssize_t دارند. کدهای s# و t# در PyArg_ParseTuple() همچنان بهطور پیشفرض int را خروجی میدهند، اما میتوانید ماکروی PY_SSIZE_T_CLEAN را پیش از گنجاندن Python.h تعریف کنید تا این کدها Py_ssize_t را برگردانند.
PEP 353 بخشی دربارهی دستورالعملهای تبدیل دارد که نویسندگان ماژولهای توسعهای باید آن را بخوانند تا با نحوهی پشتیبانی از پلتفرمهای ۶۴ بیتی آشنا شوند.
همچنین ملاحظه نمائید
- PEP 353 - استفاده از ssize_t بهعنوان نوع اندیس
PEP نوشته و پیادهسازیشده توسط مارتین فون لوویس (Martin von Löwis).
PEP 357: متد '__index__'¶
توسعهدهندگان NumPy مشکلی داشتند که تنها با افزودن یک متد ویژهی جدید، __index__()، قابل حل بود. هنگام استفاده از نمادگذاری اسلایس، مانند [start:stop:step]، مقادیر اندیسهای start، stop و step باید همگی اعداد صحیح یا اعداد صحیح بلند باشند. NumPy انواع تخصصی مختلفی از اعداد صحیح تعریف میکند که متناظر با اعداد صحیح بدون علامت و علامتدار ۸، ۱۶، ۳۲ و ۶۴ بیتی هستند، اما راهی برای نشان دادن اینکه این انواع میتوانند بهعنوان اندیسهای اسلایس استفاده شوند وجود نداشت.
اسلایس کردن نمیتواند صرفاً از متد موجود __int__() استفاده کند، زیرا این متد همچنین برای پیادهسازی تبدیل ضمنی نوع به اعداد صحیح استفاده میشود. اگر اسلایس کردن از __int__() استفاده میکرد، اعداد ممیز شناور نیز به اندیسهای مجاز اسلایس تبدیل میشدند و این بهوضوح رفتاری ناخواسته است.
در عوض، یک متد ویژه جدید به نام __index__() اضافه شد. این متد هیچ آرگومانی نمیگیرد و یک عدد صحیح برمیگرداند که اندیس اسلایس مورد استفاده را مشخص میکند. برای مثال:
class C:
def __index__ (self):
return self.value
مقدار بازگشتی باید یک عدد صحیح پایتون یا عدد صحیح بلند (long integer) باشد. مفسر بررسی میکند که نوع بازگشتی درست باشد، و در صورتی که این الزام برآورده نشود، TypeError را ایجاد میکند.
جایگاه متناظری nb_index به ساختار PyNumberMethods در سطح C اضافه شد تا ماژولهای توسعهای C بتوانند این پروتکل را پیادهسازی کنند. میتوان از PyNumber_Index(obj) در کد توسعهای برای فراخوانی تابع __index__() و بازیابی نتیجهی آن استفاده کرد.
همچنین ملاحظه نمائید
- PEP 357 - اجازه استفاده از هر شیء برای اسلایس کردن
PEP نوشته و پیادهسازی شده توسط تراویس اولیفانت.
سایر تغییرات زبان¶
در اینجا تمام تغییراتی که پایتون 2.5 در هسته زبان پایتون ایجاد میکند، آمدهاند.
نوع
dictقلاب جدیدی دارد که به زیرکلاسها اجازه میدهد هنگامی که کلیدی در دیکشنری وجود ندارد، مقداری پیشفرض ارائه کنند. وقتی کلیدی یافت نشود، متد__missing__(key)دیکشنری فراخوانی خواهد شد. از این قلاب برای پیادهسازی کلاس جدیدdefaultdictدر ماژولcollectionsاستفاده شده است. مثال زیر دیکشنریای را تعریف میکند که برای هر کلید مفقود صفر برمیگرداند:class zerodict (dict): def __missing__ (self, key): return 0 d = zerodict({1:1, 2:2}) print d[1], d[2] # Prints 1, 2 print d[3], d[4] # Prints 0, 0
هم رشتههای ۸-بیتی و هم رشتههای یونیکد متدهای جدید
partition(sep)وrpartition(sep)دارند که یک کاربرد رایج را ساده میکنند.متد
find(S)اغلب برای بهدستآوردن اندیسی به کار میرود که سپس از آن برای اسلایس کردن رشته و بهدستآوردن قطعات پیش و پس از جداکننده استفاده میشود.partition(sep)این الگو را در قالب یک فراخوانی متد واحد خلاصه میکند و یک تاپل سهعضوی برمیگرداند که شامل زیررشتهی پیش از جداکننده، خودِ جداکننده و زیررشتهی پس از جداکننده است. اگر جداکننده یافت نشود، نخستین عنصر تاپل کل رشته است و دو عنصر دیگر خالی هستند.rpartition(sep)نیز یک تاپل سهعضوی برمیگرداند اما جستجو را از انتهای رشته آغاز میکند؛ حرفrمخفف «reverse» (معکوس) است.چند مثال:
>>> ('http://www.python.org').partition('://') ('http', '://', 'www.python.org') >>> ('file:/usr/share/doc/index.html').partition('://') ('file:/usr/share/doc/index.html', '', '') >>> (u'Subject: a quick question').partition(':') (u'Subject', u':', u' a quick question') >>> 'www.python.org'.rpartition('.') ('www.python', '.', 'org') >>> 'www.python.org'.rpartition(':') ('', '', 'www.python.org')
(پیادهسازیشده توسط Fredrik Lundh بر اساس پیشنهاد Raymond Hettinger.)
متدهای
startswith()وendswith()از انواع رشته اکنون تاپلهایی از رشتهها را برای بررسی میپذیرند.def is_image_file (filename): return filename.endswith(('.gif', '.jpg', '.tiff'))
(پیادهسازیشده توسط Georg Brandl بر اساس پیشنهاد Tom Lynn.)
توابع توکار
min()وmax()پارامتر کلیدواژهایkeyمشابه آرگومانkeyدرsort()به دست آوردند. این پارامتر تابعی را فراهم میکند که یک آرگومان میگیرد و برای هر مقدار در فهرست فراخوانی میشود؛min()/max()المانی را برمیگردانند که کوچکترین/بزرگترین مقدار بازگشتی از این تابع را دارد. برای مثال، برای یافتن بلندترین رشته در یک فهرست، میتوانید این کار را انجام دهید:L = ['medium', 'longest', 'short'] # Prints 'longest' print max(L, key=len) # Prints 'short', because lexicographically 'short' has the largest value print max(L)
(مشارکتشده توسط استیون بثارد و ریموند هتینگر.)
دو تابع توکار جدید،
any()وall()، ارزیابی میکنند که آیا یک پیمایشگر حاوی مقادیر درست یا نادرست است.any()در صورتیTrueرا برمیگرداند که یکی از مقادیر برگرداندهشده توسط پیمایشگر درست باشد؛ در غیر این صورتFalseرا برمیگرداند.all()تنها زمانیTrueرا برمیگرداند که همهی مقادیر برگرداندهشده توسط پیمایشگر درست ارزیابی شوند. (پیشنهاد Guido van Rossum و پیادهسازی Raymond Hettinger.)نتیجهی متد
__hash__()یک کلاس اکنون میتواند یک عدد صحیح بلند یا یک عدد صحیح معمولی باشد. اگر یک عدد صحیح بلند برگردانده شود، هش آن مقدار به کار گرفته میشود. در نسخههای پیشین، الزامی بود که مقدار هش یک عدد صحیح معمولی باشد، اما در نسخهی 2.5 تابع توکارid()تغییر کرد تا همیشه اعداد نامنفی برگرداند، و به نظر میرسد کاربران اغلب ازid(self)در متدهای__hash__()استفاده میکنند (هرچند این کار توصیه نمیشود).اسکی اکنون کدگذاری پیشفرض ماژولها است. اگر ماژولی حاوی مقادیر لفظی رشتهای با نویسههای ۸-بیتی باشد اما اعلان کدگذاری نداشته باشد، اکنون این یک خطای نحوی است. در پایتون 2.4 این مورد هشداری ایجاد میکرد، نه خطای نحوی. برای نحوهی اعلان کدگذاری یک ماژول به PEP 263 مراجعه کنید؛ برای مثال، ممکن است سطری مانند این را نزدیک ابتدای پروندهی منبع اضافه کنید:
# -*- coding: latin1 -*-یک هشدار جدید،
UnicodeWarning، زمانی فعال میشود که شما تلاش کنید یک رشتهی یونیکد را با یک رشتهی ۸ بیتی که نمیتوان آن را با استفاده از کدگذاری پیشفرض اسکی به یونیکد تبدیل کرد، مقایسه کنید. نتیجهی مقایسه نادرست است:>>> chr(128) == unichr(128) # Can't convert chr(128) to Unicode __main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal False >>> chr(127) == unichr(127) # chr(127) can be converted True
پیشتر این مورد استثنای
UnicodeDecodeErrorایجاد میکرد، اما در 2.5 این موضوع میتوانست هنگام دسترسی به یک دیکشنری به مشکلات سردرگمکنندهای منجر شود. اگرunichr(128)را جستوجو میکردید وchr(128)بهعنوان کلید استفاده شده بود، با استثنایUnicodeDecodeErrorمواجه میشدید. سایر تغییرات در 2.5 باعث شدند این استثنا بهجای آنکه توسط کد پیادهسازیکنندهی دیکشنریها درdictobject.cسرکوب شود، ایجاد شود.ایجاد استثنا برای چنین مقایسهای از نظر اصولی کاملاً درست است، اما این تغییر ممکن بود کدها را بشکند، بنابراین در عوض
UnicodeWarningمعرفی شد.(پیادهسازیشده توسط Marc-André Lemburg.)
یکی از خطاهایی که برنامهنویسان پایتون گاهی مرتکب میشوند، فراموش کردن گنجاندن ماژول
__init__.pyدر پوشهی بسته است. اشکالزدایی این اشتباه میتواند گیجکننده باشد و معمولاً نیازمند اجرای پایتون با سوییچ-vبرای ثبت تمام مسیرهای جستجوشده است. در پایتون 2.5، هشدار جدیدImportWarningزمانی فعال میشود که یک ایمپورت پوشهای را بهعنوان بسته برمیگرفت، اما هیچ__init__.pyیافت نمیشد. این هشدار بهطور پیشفرض بهصورت بیصدا نادیده گرفته میشود؛ هنگام اجرای پرونده اجرایی پایتون، گزینهی-Wdرا ارائه دهید تا پیام هشدار نمایش داده شود. (پیادهسازی شده توسط Thomas Wouters.)فهرست کلاسهای پایه در تعریف کلاس اکنون میتواند خالی باشد. به عنوان مثال، این اکنون معتبر است:
class C(): pass
(توسط Brett Cannon پیادهسازی شده است.)
تغییرات مفسر تعاملی¶
در مفسر تعاملی، quit و exit مدتهاست که رشته بودهاند تا کاربران جدید هنگام تلاش برای خروج، پیامی تا حدی مفید دریافت کنند:
>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'
در پایتون 2.5، quit و exit اکنون اشیایی هستند که همچنان نمایش رشتهای خود را تولید میکنند، اما فراخوانیپذیر نیز هستند. تازهکارانی که quit() یا exit() را امتحان میکنند، اکنون همانطور که انتظار دارند از مفسر خارج خواهند شد. (پیادهسازیشده توسط Georg Brandl.)
پرونده اجرایی پایتون اکنون گزینههای بلند استاندارد --help و --version را میپذیرد؛ در ویندوز، گزینه /? را نیز برای نمایش پیام راهنما میپذیرد. (پیادهسازیشده توسط Georg Brandl.)
بهینهسازیها¶
تعدادی از بهینهسازیها در اسپرینت NeedForSpeed توسعه یافتند؛ رویدادی که از ۲۱ تا ۲۸ مه ۲۰۰۶ در ریکیاویک، ایسلند برگزار شد. این اسپرینت بر افزایش سرعت پیادهسازی سیپایتون متمرکز بود و توسط EWT LLC با حمایت محلی از سوی CCP Games تأمین مالی شد. بهینهسازیهایی که در این اسپرینت افزوده شدند، در فهرست زیر بهطور ویژه مشخص شدهاند.
وقتی در پایتون 2.4 معرفی شدند، نوعهای توکار
setوfrozensetبر پایهی نوع دیکشنری پایتون ساخته شده بودند. در نسخهی 2.5 ساختار دادهی داخلی برای پیادهسازی مجموعهها سفارشیسازی شده است و در نتیجه، مجموعهها یکسوم حافظهی کمتری استفاده میکنند و تا حدی سریعتر هستند. (پیادهسازی شده توسط Raymond Hettinger.)سرعت برخی از عملیات یونیکد، مانند یافتن زیررشتهها، تقسیم رشته، و کدگذاری و کدگشایی نگاشت نویسه، بهبود یافته است. (بهبودهای جستوجوی زیررشته و تقسیم رشته توسط Fredrik Lundh و Andrew Dalke در اسپرینت NeedForSpeed اضافه شدند. نگاشتهای نویسه توسط Walter Dörwald و Martin von Löwis بهبود یافتند.)
تابع
long(str, base)اکنون روی رشتههای رقمی بلند سریعتر است، زیرا نتایج میانی کمتری محاسبه میشود. اوج آن برای رشتههایی با حدود ۸۰۰--۱۰۰۰ رقم است که در آنها تابع ۶ برابر سریعتر است. (مشارکتشده توسط Alan McIntyre و کامیتشده در اسپرینت NeedForSpeed.)اکنون ترکیب پیمایش روی یک پرونده با
for line in fileو فراخوانی متدهایread()/readline()/readlines()شیء پرونده غیرمجاز است. پیمایش از یک بافر داخلی استفاده میکند و متدهایread*()از آن بافر استفاده نمیکنند. در عوض، این متدها دادههای پس از بافر را برمیگرداندند که باعث میشد دادهها نامرتب به نظر برسند. ترکیب پیمایش و این متدها اکنون موجب میشود متدread*()یکValueErrorایجاد کند. (پیادهسازی توسط Thomas Wouters.)ماژول
structاکنون رشتههای قالب ساختار را به نمایشی داخلی کامپایل میکند و این نمایش را در نهانگاه ذخیره میکند، که منجر به افزایش ۲۰ درصدی سرعت میشود. (ارائهشده توسط باب ایپولیتو در اسپرینت NeedForSpeed.)ماژول
reبا تغییر به توابع تخصیصدهنده حافظهی پایتون بهجایmalloc()وfree()سیستم، ۱ یا ۲ درصد سریعتر شد. (ارائهشده توسط Jack Diederich در اسپرینت NeedForSpeed.)بهینهساز پنجرهای (peephole) تولیدگر کد اکنون تاشدگی ثابت (constant folding) ساده را در عبارتها انجام میدهد. اگر چیزی مانند
a = 2+3بنویسید، تولیدگر کد محاسبات را انجام میدهد و کدی متناظر باa = 5تولید میکند. (پیشنهاد و پیادهسازی توسط Raymond Hettinger.)فراخوانی توابع اکنون سریعتر است، زیرا اشیای کد اکنون جدیدترین فریم پایانیافته (یک «فریم زامبی» (zombie frame)) را در یک فیلد داخلی از شیء کد نگه میدارند و دفعه بعد که شیء کد فراخوانی میشود، دوباره از آن استفاده میکنند. (وصل اصلی توسط Michael Hudson، اصلاحشده توسط Armin Rigo و Richard Jones؛ در اسپرینت NeedForSpeed ثبت نهایی شد.) اشیای فریم همچنین اندکی کوچکتر شدهاند، که ممکن است محلیت نهانگاه (cache locality) را بهبود بخشد و مصرف حافظه را کمی کاهش دهد. (مشارکتشده توسط Neal Norwitz.)
استثناهای توکار پایتون اکنون کلاسهای سبک جدید هستند، تغییری که سرعت نمونهسازی را بهطور چشمگیری افزایش میدهد. بنابراین مدیریت استثنا در پایتون 2.5 حدود ۳۰٪ سریعتر از 2.4 است. (مشارکتشده توسط Richard Jones، Georg Brandl و Sean Reifschneider در اسپرینت NeedForSpeed.)
ایمپورت کردن اکنون مسیرهای امتحانشده را در نهانگاه ذخیره میکند و ثبت میکند که آیا وجود دارند یا نه، تا مفسر هنگام راهاندازی فراخوانیهای کمتری از
open()وstat()انجام دهد. (مشارکتشده توسط Martin von Löwis و Georg Brandl.)
ماژولهای جدید، بهبودیافته و حذفشده¶
کتابخانه استاندارد در پایتون 2.5 بهبودها و رفع اشکالهای بسیاری دریافت کرد. در ادامه، فهرست ناقصی از مهمترین تغییرات که به ترتیب حروف الفبا بر اساس نام ماژول مرتب شدهاند، آمده است. برای فهرست کاملتری از تغییرات، به پرونده Misc/NEWS در درخت سورس مراجعه کنید، یا برای همه جزئیات، گزارشهای SVN را بررسی کنید.
ماژول
audioopاکنون از کدگذاری a-LAW پشتیبانی میکند و کد مربوط به کدگذاری u-LAW بهبود یافته است. (مشارکت توسط Lars Immisch.)به ماژول
codecsپشتیبانی از کدکهای افزایشی اضافه شد. تابعcodecs.lookup()اکنون به جای یک تاپل، یک نمونهیCodecInfoبرمیگرداند. نمونههایCodecInfoبرای حفظ سازگاری با نسخههای پیشین مانند یک تاپل ۴تایی رفتار میکنند، اما ویژگیهایencode،decode،incrementalencoder،incrementaldecoder،streamwriterوstreamreaderرا نیز دارند. کدکهای افزایشی میتوانند ورودی را دریافت کنند و خروجی را در چندین بخش تولید کنند؛ خروجی همان چیزی است که اگر کل ورودی به کدک غیرافزایشی داده میشد، تولید میشد. برای جزئیات، مستندات ماژولcodecsرا ببینید. (طراحی و پیادهسازی توسط والتر دوروالد.)ماژول
collectionsنوع جدیدی دریافت کرد،defaultdict، که زیرکلاسی از نوع استانداردdictاست. این نوع جدید عمدتاً مانند یک دیکشنری رفتار میکند، اما هنگامی که کلیدی وجود ندارد، یک مقدار پیشفرض میسازد و آن را بهطور خودکار برای مقدار کلید درخواستی به دیکشنری اضافه میکند.اولین آرگومانِ سازندهی
defaultdictیک تابع کارخانهای است که هر زمان که کلیدی درخواست شود اما یافت نشود، فراخوانی میشود. این تابع کارخانهای هیچ آرگومانی دریافت نمیکند، بنابراین میتوانید از سازندههای نوعهای توکار مانندlist()یاint()استفاده کنید. برای مثال، میتوانید اندیسی از واژهها بر اساس حرف آغازینشان به این شکل بسازید:words = """Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura che la diritta via era smarrita""".lower().split() index = defaultdict(list) for w in words: init_letter = w[0] index[init_letter].append(w)
چاپ
indexخروجی زیر را نتیجه میدهد:defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'], 'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'], 'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'], 'p': ['per'], 's': ['selva', 'smarrita'], 'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}
(مشارکتشده توسط گیدو ون روسوم.)
نوع صف دوطرفهی
dequeکه توسط ماژولcollectionsارائه میشود، اکنون متدremove(value)دارد که نخستین رخداد value را در صف حذف میکند و در صورتی که مقدار یافت نشود، استثنایValueErrorرا بالا میبرد. (مشارکتکرده: Raymond Hettinger.)ماژول جدید: ماژول
contextlibشامل توابع کمکی برای استفاده با دستور جدید «with» است. برای اطلاعات بیشتر دربارهی این ماژول، به بخش ماژول contextlib مراجعه کنید.ماژول جدید: ماژول
cProfileیک پیادهسازی به زبان C از ماژول موجودprofileاست که سربار بسیار کمتری دارد. رابط این ماژول همانندprofileاست: برای پروفایلگیری یک تابع،cProfile.run('main()')را اجرا میکنید، میتوانید دادههای پروفایل را در یک پرونده ذخیره کنید و غیره. هنوز مشخص نیست که پروفایلگیر Hotshot، که آن هم به زبان C نوشته شده اما با رابط ماژولprofileمطابقت ندارد، در نسخههای آینده پایتون همچنان نگهداری خواهد شد یا خیر. (مشارکت Armin Rigo.)همچنین، ماژول
pstatsبرای تحلیل دادههای اندازهگیریشده توسط پروفایلگیر، اکنون با فراهمکردن آرگومان stream برای سازندهیStatsاز هدایت خروجی به هر شیء پروندهای پشتیبانی میکند. (ارائهشده توسط Skip Montanaro.)ماژول
csv، که پروندهها را با قالب مقادیر جداشده با ویرگول تجزیه میکند، چندین بهبود و تعدادی رفع اشکال دریافت کرد. اکنون میتوانید حداکثر اندازهی یک فیلد بر حسب بایت را با فراخوانی تابعcsv.field_size_limit(new_limit)تنظیم کنید؛ در صورت حذف آرگومان new_limit، محدودیت تنظیمشدهی فعلی برگردانده میشود. کلاسreaderاکنون دارای ویژگیline_numاست که تعداد سطرهای فیزیکی خواندهشده از منبع را شمارش میکند؛ رکوردها میتوانند چند سطر فیزیکی را در بر بگیرند، بنابراینline_numبا تعداد رکوردهای خواندهشده یکسان نیست.پارسر CSV اکنون نسبت به فیلدهای نقلقولی چندسطری سختگیرانهتر است. پیشتر، اگر سطری درون یک فیلد نقلقولی بدون نویسه سطر جدید پایانی به پایان میرسید، یک سطر جدید در فیلد بازگرداندهشده درج میشد. این رفتار هنگام خواندن پروندههایی که حاوی نویسههای بازگشت به ابتدای سطر درون فیلدها بودند، مشکلساز بود؛ بنابراین کد تغییر داده شد تا فیلد را بدون درج سطرهای جدید بازگرداند. در نتیجه، اگر سطرهای جدید تعبیهشده درون فیلدها اهمیت دارند، ورودی باید به شکلی که نویسههای سطر جدید را حفظ کند، به سطرها تقسیم شود.
(به همت Skip Montanaro و Andrew McNamara.)
کلاس
datetimeدر ماژولdatetimeاکنون متدstrptime(string, format)را برای تجزیهی رشتههای تاریخ دارد که حاصل مشارکت Josh Spoerri است. این متد از همان نویسههای قالببندیtime.strptime()وtime.strftime()استفاده میکند:import datetime as dt ts = dt.datetime.strptime('10:13:15 2006-03-07', '%H:%M:%S %Y-%m-%d')
متد
difflib.SequenceMatcher.get_matching_blocks()در ماژولdifflibاکنون تضمین میکند که فهرست کمینهای از بلوکهای توصیفکنندهی زیردنبالههای منطبق را برگرداند. پیشتر، الگوریتم گاهی یک بلوک از المانهای منطبق را به دو ورودی فهرست تقسیم میکرد. (بهبود توسط Tim Peters.)ماژول
doctestگزینهیSKIPرا دریافت کرد که باعث میشود یک مثال اصلاً اجرا نشود. این گزینه برای قطعههای کدی در نظر گرفته شده که مثالهای نحوهی استفاده برای خواننده هستند و در واقع موارد آزمون به شمار نمیآیند.پارامتر encoding به تابع
testfile()و کلاسDocFileSuiteبرای تعیین کدگذاری پرونده اضافه شد. این کار استفاده از نویسههای غیراسکی در آزمونهای موجود در یک رشته مستند را آسانتر میکند. (مشارکتشده توسط Bjorn Tillenius.)بستهی
emailبه نسخهی 4.0 بهروزرسانی شده است. (با مشارکت بری وارسو.)ماژول
fileinputانعطافپذیرتر شد. اکنون از نامهای پروندهی یونیکد پشتیبانی میشود و پارامتر mode با مقدار پیشفرض"r"به تابعinput()اضافه شد تا امکان باز کردن پروندهها در حالت دودویی یا سطرهای جدید همگانی فراهم شود. پارامتر جدید دیگر، openhook، به شما اجازه میدهد برای باز کردن پروندههای ورودی از تابعی غیر ازopen()استفاده کنید. هنگامی که روی مجموعهی پروندهها پیمایش میکنید، متد جدیدfileno()از شیءFileInputتوصیفگر پرونده مربوط به پروندهی هماکنون باز را برمیگرداند. (مشارکتشده توسط Georg Brandl.)در ماژول
gc، تابع جدیدget_count()یک تاپل سهتایی برمیگرداند که شامل شمارشهای جمعآوری فعلی برای سه نسل GC است. این اطلاعات حسابداری برای زبالهروب است؛ وقتی این شمارشها به آستانهی تعیینشدهای برسند، یک دور زبالهروبی انجام خواهد شد. تابع موجودgc.collect()اکنون یک آرگومان اختیاری generation با مقدار ۰، ۱ یا ۲ میگیرد تا مشخص کند کدام نسل جمعآوری شود. (نوشتهی Barry Warsaw.)توابع
nsmallest()وnlargest()در ماژولheapqاکنون از پارامتر کلیدواژهایkeyمشابه پارامتری که توسط توابعmin()/max()و متدهایsort()ارائه میشود، پشتیبانی میکنند. برای مثال:>>> import heapq >>> L = ["short", 'medium', 'longest', 'longer still'] >>> heapq.nsmallest(2, L) # Return two lowest elements, lexicographically ['longer still', 'longest'] >>> heapq.nsmallest(2, L, key=len) # Return two shortest elements ['short', 'medium']
(با مشارکت ریموند هتینگر.)
تابع
itertools.islice()اکنونNoneرا برای آرگومانهای start و step میپذیرد. این کار آن را با ویژگیهای اشیای اسلایس سازگارتر میکند، بهطوری که اکنون میتوانید موارد زیر را بنویسید:s = slice(5) # Create slice object itertools.islice(iterable, s.start, s.stop, s.step)
(با مشارکت ریموند هتینگر.)
تابع
format()در ماژولlocaleاصلاح شده و دو تابع جدیدformat_string()وcurrency()اضافه شدهاند.پارامتر val تابع
format()قبلاً میتوانست یک رشته باشد، به شرط آنکه بیش از یک مشخصکنندهی %char در آن ظاهر نشود؛ اکنون این پارامتر باید دقیقاً یک مشخصکنندهی %char بدون هیچ متنی در اطرافش باشد. همچنین یک پارامتر اختیاری monetary افزوده شد که اگرTrueباشد، هنگام قرار دادن جداکننده بین گروههای سهرقمی، از قواعد locale برای قالببندی واحد پول استفاده میکند.برای قالببندی رشتهها با چندین مشخصکنندهی %char، از تابع جدید
format_string()استفاده کنید که مانندformat()کار میکند، اما از ترکیب مشخصکنندههای %char با متن دلخواه نیز پشتیبانی میکند.تابع جدید
currency()نیز افزوده شد که یک عدد را مطابق با تنظیمات locale جاری قالببندی میکند.(مشارکتشده توسط Georg Brandl.)
ماژول
mailboxدستخوش بازنویسی گستردهای شد تا علاوه بر خواندن صندوقهای پستی، امکان تغییر آنها را نیز فراهم کند. مجموعهای جدید از کلاسها شاملmbox،MHوMaildirبرای خواندن صندوقهای پستی استفاده میشوند و دارای متدadd(message)برای افزودن پیامها،remove(key)برای حذف پیامها وlock()/unlock()برای قفل کردن/باز کردن قفل صندوق پستی هستند. مثال زیر یک صندوق پستی با قالب maildir را به یک صندوق پستی با قالب mbox تبدیل میکند:import mailbox # 'factory=None' uses email.Message.Message as the class representing # individual messages. src = mailbox.Maildir('maildir', factory=None) dest = mailbox.mbox('/tmp/mbox') for msg in src: dest.add(msg)
(مشارکتشده توسط گریگوری کی. جانسون. تأمین مالی این کار توسط برنامهی تابستانی کدنویسی گوگل در سال ۲۰۰۵ انجام شد.)
ماژول جدید: ماژول
msilibامکان ساخت پروندههای.msiنصبکننده مایکروسافت و پروندههای CAB را فراهم میکند. همچنین مقداری پشتیبانی برای خواندن پایگاه داده.msiدر آن گنجانده شده است. (ارائهشده توسط Martin von Löwis.)ماژول
nisاکنون از دسترسی به دامنههایی غیر از دامنهی پیشفرض سیستم، با دادن آرگومان domain به توابعnis.match()وnis.maps()پشتیبانی میکند. (مشارکتشده توسط Ben Bell.)توابع
itemgetter()وattrgetter()در ماژولoperatorاکنون از چندین فیلد پشتیبانی میکنند. فراخوانیای مانندoperator.attrgetter('a', 'b')تابعی را برمیگرداند که ویژگیهایaوbرا بازیابی میکند. ترکیب این قابلیت جدید با پارامترkeyمتدsort()به شما امکان میدهد فهرستها را بهسادگی با استفاده از چندین فیلد مرتب کنید. (مشارکت توسط Raymond Hettinger.)ماژول
optparseبه نسخهی 1.5.1 کتابخانهی Optik بهروزرسانی شد. کلاسOptionParserیک ویژگیepilogبه دست آورد — رشتهای که پس از پیام راهنما چاپ میشود — و یک متدdestroy()برای شکستن چرخههای ارجاعی که توسط شیء ایجاد میشوند. (مشارکت: Greg Ward.)ماژول
osدستخوش چندین تغییر شد. متغیرstat_float_timesاکنون بهطور پیشفرض برابر با true است، به این معنا کهos.stat()از این پس مقادیر زمانی را بهصورت اعداد اعشاری برمیگرداند. (این لزوماً به آن معنا نیست کهos.stat()زمانهایی با دقت کسری از ثانیه برگرداند؛ همهی سیستمها از چنین دقتی پشتیبانی نمیکنند.)ثابتهایی با نامهای
os.SEEK_SET،os.SEEK_CURوos.SEEK_ENDافزوده شدهاند؛ این ثابتها پارامترهای تابعos.lseek()هستند. دو ثابت جدید برای قفلگذاری عبارتاند ازos.O_SHLOCKوos.O_EXLOCK.دو تابع جدید،
wait3()وwait4()، اضافه شدند. این دو تابع مشابه تابعwaitpid()هستند که منتظر خروج یک فرایند فرزند میماند و تاپلی شامل شناسه فرایند و وضعیت خروج آن را برمیگرداند، اماwait3()وwait4()اطلاعات بیشتری برمیگردانند.wait3()شناسه فرایند را به عنوان ورودی نمیگیرد، بنابراین منتظر خروج هر فرایند فرزندی میماند و یک تاپل سهعضوی شامل شناسه فرایند، وضعیت خروج و مصرف منابع (همانطور که تابعresource.getrusage()برمیگرداند) برمیگرداند.wait4(pid)شناسه فرایند را میگیرد. (نوشتهشده توسط Chad J. Schroeder.)در FreeBSD، تابع
os.stat()اکنون زمانها را با وضوح نانوثانیهای برمیگرداند و شیء بازگرداندهشده اکنون دارایst_genوst_birthtimeاست. ویژگیst_flagsنیز در صورت پشتیبانی پلتفرم، در دسترس است. (مشارکت توسط Antti Louko و Diego Pettenò.)اشکالزدای پایتون که توسط ماژول
pdbارائه میشود، اکنون میتواند فهرستهایی از دستورها را ذخیره کند تا هنگامی که به نقطه توقف میرسد و اجرا متوقف میشود، اجرا شوند. پس از ایجاد نقطه توقف شماره ۱،commands 1را وارد کنید و مجموعهای از دستورها را که باید اجرا شوند وارد کنید و فهرست را باendبه پایان ببرید. فهرست دستورها میتواند شامل دستورهایی باشد که اجرا را از سر میگیرند، مانندcontinueیاnext. (مشارکتشده توسط Grégoire Dooms.)ماژولهای
pickleوcPickleدیگر مقدار بازگشتیNoneاز متد__reduce__()را نمیپذیرند؛ این متد باید بهجای آن یک تاپل از آرگومانها برگرداند. امکان برگرداندنNoneدر Python 2.4 منسوخ شده بود، بنابراین این کار حذف این قابلیت را کامل میکند.ماژول
pkgutilکه شامل توابع کاربردی گوناگون برای یافتن بستهها است، بهبود یافت تا از قلابهای ایمپورتِ PEP 302 پشتیبانی کند و اکنون برای بستههای ذخیرهشده در آرشیوهای با قالب ZIP نیز کار میکند. (مشارکت توسط Phillip J. Eby.)بدنهی بنچمارک pybench نوشتهی Marc-André Lemburg اکنون در پوشهی
Tools/pybenchگنجانده شده است. بدنهی pybench بهبودی بر برنامهی پرکاربردpystone.pyاست، زیرا pybench اندازهگیری سرعت مفسر را با جزئیات بیشتری ارائه میدهد. این بدنه بهجای آنکه مانندpystone.pyعملیاتهای متعدد و گوناگونی انجام دهد و نتیجه را به یک عدد واحد تقلیل دهد، زمان عملیاتهای خاصی مانند فراخوانی توابع، اسلایس کردن تاپلها، جستجوی متدها و عملیاتهای عددی را اندازهگیری میکند.ماژول
pyexpatاکنون از نسخه 2.0 پارسر Expat استفاده میکند. (مشارکت توسط Trent Mick.)کلاس
Queueکه توسط ماژولqueueارائه میشود، دو متد جدید به دست آورد.join()تا زمانی که همهی آیتمهای صف بازیابی شده باشند و تمام کارهای پردازش روی آیتمها به پایان رسیده باشند، مسدود میماند. نخهای کارگر متد جدید دیگر یعنیtask_done()را فراخوانی میکنند تا سیگنال دهند که پردازش یک آیتم به پایان رسیده است. (مشارکتشده توسط Raymond Hettinger.)ماژولهای قدیمی
regexوregsubکه از زمان پایتون 2.0 منسوخ شده بودند، سرانجام حذف شدند. سایر ماژولهای حذفشده:statcache،tzparse،whrandom.همچنین حذف شد: پوشهی
lib-oldکه ماژولهای بسیار قدیمیای مانندdircmpوniرا در بر میگرفت، حذف شد.lib-oldدرsys.pathپیشفرض قرار نداشت، بنابراین مگر اینکه برنامههای شما این پوشه را بهطور صریح بهsys.pathافزوده باشند، این حذف نباید بر کد شما تأثیری بگذارد.ماژول
rlcompleterدیگر به ایمپورت کردن ماژولreadlineوابسته نیست و بنابراین اکنون بر روی پلتفرمهای غیریونیکس کار میکند. (وصل از Robert Kiendl.)کلاسهای
SimpleXMLRPCServerوDocXMLRPCServerاکنون دارای ویژگیrpc_pathsهستند که عملیاتهای XML-RPC را به مجموعهای محدود از مسیرهای URL محدود میکند؛ پیشفرض این است که فقط'/'و'/RPC2'مجاز باشند. تنظیمrpc_pathsبهNoneیا یک تاپل خالی، این بررسی مسیر را غیرفعال میکند.ماژول
socketاکنون از سوکتهایAF_NETLINKدر لینوکس پشتیبانی میکند؛ به لطف وصلی از فیلیپ بیوندی. سوکتهای netlink سازوکاری ویژهی لینوکس برای برقراری ارتباط میان یک فرایند در فضای کاربر و کد هسته هستند؛ مقالهای مقدماتی دربارهی آنها در https://www.linuxjournal.com/article/7356 موجود است. در کد پایتون، نشانیهای netlink بهصورت تاپلی از ۲ عدد صحیح،(pid, group_mask)، نمایش داده میشوند.دو متد جدید روی شیءهای سوکت،
recv_into(buffer)وrecvfrom_into(buffer)، دادههای دریافتشده را بهجای بازگرداندن آنها بهصورت رشته، در شیئی ذخیره میکنند که پروتکل بافر را پشتیبانی میکند. این بدان معناست که میتوانید دادهها را مستقیماً در یک آرایه یا یک پرونده نگاشتشده در حافظه قرار دهید.به اشیاء سوکت همچنین متدهای دسترسی
getfamily()،gettype()وgetproto()اضافه شد تا مقادیر خانواده، نوع و پروتکل سوکت را بازیابی کنند.ماژول جدید: ماژول
spwdتوابعی برای دسترسی به پایگاه داده گذرواژههای سایه (shadow password) در سیستمهایی که از گذرواژههای سایه پشتیبانی میکنند، فراهم میکند.ماژول
structاکنون سریعتر است، زیرا رشتههای قالب را به شیءهایStructبا متدهایpack()وunpack()کامپایل میکند. این مشابه روشی است که ماژولreبه شما اجازه میدهد شیءهای عبارت باقاعدهی کامپایلشده بسازید. همچنان میتوانید از توابع در سطح ماژولpack()وunpack()استفاده کنید؛ این توابع شیءهایStructمیسازند و آنها را در نهانگاه ذخیره میکنند. یا میتوانید مستقیماً از نمونههایStructاستفاده کنید:s = struct.Struct('ih3s') data = s.pack(1972, 187, 'abc') year, number, name = s.unpack(data)
همچنین میتوانید با استفاده از متدهای
pack_into(buffer, offset, v1, v2, ...)وunpack_from(buffer, offset)، دادهها را مستقیماً در شیءهای بافر بستهبندی و از آنها واگشایی کنید. این به شما امکان میدهد دادهها را مستقیماً در یک آرایه یا پرونده نگاشتشده در حافظه ذخیره کنید.(اشیای
Structتوسط Bob Ippolito در اسپرینت NeedForSpeed پیادهسازی شدند. پشتیبانی از اشیای بافر نیز در اسپرینت NeedForSpeed توسط Martin Blais اضافه شد.)توسعهدهندگان پایتون در طول فرایند توسعهی نسخه 2.5 از CVS به Subversion مهاجرت کردند. اطلاعات مربوط به نسخهی دقیق ساخت بهصورت متغیر
sys.subversionدر دسترس است؛ این متغیر یک تاپل سهگانه به شکل(interpreter-name, branch-name, revision-range)است. برای مثال، در زمان نگارش این متن، نسخهی من از 2.5 مقدار('CPython', 'trunk', '45313:45315')را گزارش میکرد.این اطلاعات همچنین از طریق تابع
Py_GetBuildInfo()— که رشتهای از اطلاعات ساخت مانند"trunk:45355:45356M, Apr 13 2006, 07:42:19"را برمیگرداند — برای ماژولهای توسعهای C نیز در دسترس است. (مشارکتشده توسط Barry Warsaw.)تابع جدید دیگری،
sys._current_frames()، فریمهای پشتهی فعلی تمام نخهای در حال اجرا را بهصورت دیکشنریای برمیگرداند که شناسههای نخ را به بالاترین فریم پشتهای که در زمان فراخوانی تابع در آن نخ فعال است نگاشت میکند. (مشارکتشده توسط Tim Peters.)کلاس
TarFileدر ماژولtarfileاکنون متدextractall()را دارد که همه اعضای آرشیو را در پوشه کاری جاری استخراج میکند. همچنین میتوان پوشهای متفاوت را به عنوان مقصد استخراج تعیین کرد و تنها زیرمجموعهای از اعضای آرشیو را واگشایی کرد.فشردهسازی استفادهشده برای یک پرونده tar که در حالت جریانی باز شده است، اکنون میتواند با استفاده از حالت
'r|*'بهصورت خودکار تشخیص داده شود. (مشارکتشده توسط Lars Gustäbel.)ماژول
threadingاکنون به شما اجازه میدهد اندازهی پشتهای را که هنگام ایجاد نخهای جدید استفاده میشود، تنظیم کنید. تابعstack_size([*size*])اندازهی پشتهی پیکربندیشدهی فعلی را برمیگرداند و ارائهی پارامتر اختیاری size مقدار جدیدی را تنظیم میکند. همهی پلتفرمها از تغییر اندازهی پشته پشتیبانی نمیکنند، اما ویندوز، نخبندی POSIX و OS/2 همگی از آن پشتیبانی میکنند. (مشارکتشده توسط Andrew MacIntyre.)ماژول
unicodedataبهروزرسانی شده است تا از نسخهی 4.1.0 پایگاه داده نویسههای یونیکد استفاده کند. برخی مشخصات به نسخهی 3.2.0 نیاز دارند، بنابراین این نسخه همچنان بهصورتunicodedata.ucd_3_2_0در دسترس است.ماژول جدید: ماژول
uuidشناسههای یکتای همگانی (UUID) را مطابق با RFC 4122 تولید میکند. این RFC چندین نسخهی متفاوت از UUID را تعریف میکند که از یک رشتهی آغازین، از ویژگیهای سیستم، یا بهطور کاملاً تصادفی تولید میشوند. این ماژول شامل یک کلاسUUIDو توابعی به نامهایuuid1()،uuid3()،uuid4()وuuid5()برای تولید نسخههای مختلف UUID است. (UUIDهای نسخه 2 در RFC 4122 مشخص نشدهاند و توسط این ماژول پشتیبانی نمیشوند.)>>> import uuid >>> # make a UUID based on the host ID and current time >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') >>> # make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') >>> # make a random UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') >>> # make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
(مشارکتشده توسط Ka-Ping Yee.)
نوعهای
WeakKeyDictionaryوWeakValueDictionaryماژولweakrefمتدهای جدیدی برای پیمایش ارجاعهای ضعیف موجود در دیکشنری به دست آوردند. متدهایiterkeyrefs()وkeyrefs()بهWeakKeyDictionaryاضافه شدند وitervaluerefs()وvaluerefs()بهWeakValueDictionaryاضافه شدند. (مشارکت توسط Fred L. Drake, Jr.)ماژول
webbrowserبهبودهای متعددی دریافت کرد. اکنون میتوان از آن بهصورت اسکریپت باpython -m webbrowserاستفاده کرد که یک URL را بهعنوان آرگومان میگیرد؛ تعدادی سوییچ برای کنترل رفتار وجود دارد (-nبرای پنجره مرورگر جدید،-tبرای تب جدید). توابع جدیدی در سطح ماژول،open_new()وopen_new_tab()، برای پشتیبانی از این قابلیت اضافه شدند. تابعopen()این ماژول از یک قابلیت اضافی پشتیبانی میکند: پارامتر autoraise که مشخص میکند در صورت امکان پنجره بازشده به پیشزمینه آورده شود یا خیر. تعدادی مرورگر دیگر مانند Firefox، Opera، Konqueror و elinks به فهرست مرورگرهای پشتیبانیشده اضافه شدند. (با مشارکت Oleg Broytmann و Georg Brandl.)ماژول
xmlrpclibاکنون از بازگرداندن اشیاءdatetimeبرای نوع تاریخ XML-RPC پشتیبانی میکند. برای فعالسازی این قابلیت،use_datetime=Trueرا به تابعloads()یا کلاسUnmarshallerبدهید. (مشارکتشده توسط Skip Montanaro.)ماژول
zipfileاکنون نسخهی ZIP64 این قالب را پشتیبانی میکند، به این معنا که یک آرشیو .zip از این پس میتواند بزرگتر از ۴ گیبیبایت باشد و میتواند پروندههای منفرد بزرگتر از ۴ گیبیبایت را در خود جای دهد. (با مشارکت رونالد اوسورن.)اشیاء
CompressوDecompressدر ماژولzlibاکنون از متدcopy()پشتیبانی میکنند که رونوشتی از وضعیت داخلی شیء ایجاد میکند و شیء جدیدی از نوعCompressیاDecompressبرمیگرداند. (مشارکتشده توسط Chris AtLee.)
بستهی ctypes¶
بستهی ctypes که توسط توماس هلر نوشته شده است، به کتابخانه استاندارد افزوده شده است. با ctypes میتوانید توابع دلخواه را در کتابخانههای اشتراکی یا DLLها فراخوانی کنید. کاربران قدیمی ممکن است ماژول dl را به یاد بیاورند که توابعی برای بارگذاری کتابخانههای اشتراکی و فراخوانی توابع در آنها فراهم میکند. بستهی ctypes بسیار پیشرفتهتر است.
برای بارگذاری یک کتابخانهی اشتراکی یا DLL، باید نمونهای از کلاس CDLL را ایجاد کنید و نام یا مسیر کتابخانهی اشتراکی یا DLL را ارائه دهید. پس از انجام این کار، میتوانید توابع دلخواه را با دسترسی به آنها بهعنوان ویژگیهای شیء CDLL فراخوانی کنید.
import ctypes
libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")
سازندههای نوع برای انواع مختلف C فراهم شدهاند: c_int()، c_float()، c_double()، c_char_p() (معادل char*) و غیره. برخلاف انواع پایتون، نسخههای C همگی تغییرپذیر هستند؛ میتوانید با انتساب به ویژگی value آنها، مقدار دربرگرفتهشده را تغییر دهید. اعداد صحیح و رشتههای پایتون بهطور خودکار به انواع C متناظر تبدیل میشوند، اما برای سایر انواع باید سازندهی نوع درست را فراخوانی کنید. (و منظورم باید است؛ اشتباه کردن اغلب منجر به فروپاشی مفسر با خطای قطعهبندی (segmentation fault) میشود.)
نباید از c_char_p() با یک رشتهی پایتونی استفاده کنید زمانی که تابع C قرار باشد ناحیهی حافظه را تغییر دهد، زیرا رشتههای پایتون باید تغییرناپذیر باشند؛ نقض این قاعده باعث بروز باگهای سردرگمکننده خواهد شد. وقتی به ناحیهی حافظهی قابلتغییر نیاز دارید، از create_string_buffer() استفاده کنید:
s = "this is a string"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)
فرض میشود که توابع C اعداد صحیح را برگردانند، اما میتوانید ویژگی restype شیء تابع را برای تغییر این موضوع تنظیم کنید:
>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828
ctypes همچنین یک دربرگیرنده برای C API پایتون بهصورت شیء ctypes.pythonapi ارائه میدهد. این شیء قفل مفسر سراسری را پیش از فراخوانی یک تابع آزاد نمیکند، زیرا هنگام فراخوانی کد مفسر باید این قفل نگه داشته شود. یک سازنده نوع py_object وجود دارد که یک اشارهگر PyObject* ایجاد میکند. یک کاربرد ساده:
import ctypes
d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
ctypes.py_object("abc"), ctypes.py_object(1))
# d is now {'abc', 1}.
فراموش نکنید که از py_object() استفاده کنید؛ در صورت حذف آن، با خطای قطعهبندی (segmentation fault) مواجه میشوید.
ctypes مدتی است که وجود دارد، اما همچنان افراد ماژولهای توسعهای دستنویس را مینویسند و توزیع میکنند، زیرا نمیتوانید مطمئن باشید که ctypes موجود است. شاید توسعهدهندگان، اکنون که ctypes همراه با هستهی پایتون ارائه میشود، بهجای ماژولهای توسعهای، پوششهای پایتونی را برای کتابخانهای که از طریق ctypes به آن دسترسی میشود بنویسند.
همچنین ملاحظه نمائید
- https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/
صفحهی وب ctypes پیش از ورود به کتابخانه استاندارد، همراه با آموزش، مرجع و پرسشهای متداول.
مستندات ماژول ctypes.
بستهی ElementTree¶
زیرمجموعهای از کتابخانهی ElementTree فردریک لوند برای پردازش XML، بهعنوان xml.etree به کتابخانه استاندارد افزوده شده است. ماژولهای موجود عبارتاند از ElementTree، ElementPath و ElementInclude از ElementTree 1.2.6. ماژول شتابدهندهی cElementTree نیز گنجانده شده است.
ادامهی این بخش مروری مختصر بر استفاده از ElementTree ارائه خواهد کرد. مستندات کامل ElementTree در https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm در دسترس است.
ElementTree یک سند XML را بهصورت درختی از گرههای عنصر نمایش میدهد. محتوای متنی سند در ویژگیهای text و tail ذخیره میشود (این یکی از تفاوتهای اصلی بین ElementTree و مدل شیء سند (DOM) است؛ در DOM انواع مختلفی از گره وجود دارد، از جمله TextNode.)
پرکاربردترین تابع تجزیه parse() است که یا یک رشته (فرض میشود حاوی نام یک پرونده باشد) یا یک شیء شبهپرونده میگیرد و یک نمونهی ElementTree برمیگرداند:
from xml.etree import ElementTree as ET
tree = ET.parse('ex-1.xml')
feed = urllib.urlopen(
'http://planet.python.org/rss10.xml')
tree = ET.parse(feed)
هنگامی که یک نمونه از ElementTree داشته باشید، میتوانید متد getroot() آن را فراخوانی کنید تا گره ریشه از نوع Element را دریافت کنید.
همچنین تابع XML() وجود دارد که یک رشته لفظی را میگیرد و یک گره Element برمیگرداند (نه یک ElementTree). این تابع راهی مرتب برای گنجاندن قطعات XML فراهم میکند که به سهولت یک لفظی XML نزدیک میشود:
svg = ET.XML("""<svg width="10px" version="1.0">
</svg>""")
svg.set('height', '320px')
svg.append(elem1)
هر المان XML از برخی متدهای دسترسی شبهدیکشنری و برخی متدهای دسترسی شبهفهرست پشتیبانی میکند. از عملیاتهای شبهدیکشنری برای دسترسی به مقادیر ویژگیها و از عملیاتهای شبهفهرست برای دسترسی به گرههای فرزند استفاده میشود.
عملیات |
نتیجه |
|---|---|
|
عنصر فرزند n-اُم را برمیگرداند. |
|
فهرستی از عناصر فرزند m-ام تا n-ام را بازمیگرداند. |
|
تعداد المانهای فرزند را برمیگرداند. |
|
فهرست المانهای فرزند را بازمیگرداند. |
|
elem2 را بهعنوان فرزند اضافه میکند. |
|
elem2 را در مکان مشخصشده درج میکند. |
|
عنصر فرزند nاُم را حذف میکند. |
|
فهرست نامهای ویژگیها را بازمیگرداند. |
|
مقدار ویژگی name را برمیگرداند. |
|
مقدار جدیدی برای ویژگی name تنظیم میکند. |
|
دیکشنری حاوی ویژگیها را بازیابی میکند. |
|
ویژگی name را حذف میکند. |
کامنتها و دستورالعملهای پردازشی نیز بهصورت گرههای Element بازنمایی میشوند. برای بررسی اینکه آیا یک گره کامنت یا دستورالعمل پردازشی است:
if elem.tag is ET.Comment:
...
elif elem.tag is ET.ProcessingInstruction:
...
برای تولید خروجی XML، باید متد xml.etree.ElementTree.ElementTree.write() را فراخوانی کنید. مانند parse()، این متد میتواند یک رشته یا یک شیء شبهپرونده را بپذیرد:
# Encoding is US-ASCII
tree.write('output.xml')
# Encoding is UTF-8
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')
(احتیاط: کدگذاری پیشفرض استفادهشده برای خروجی، اسکی است. برای کارهای عمومی با XML، که در آن نام یک عنصر ممکن است شامل نویسههای دلخواه یونیکد باشد، اسکی کدگذاری بسیار مفیدی نیست، زیرا اگر نام یک عنصر شامل نویسههایی با مقادیر بزرگتر از ۱۲۷ باشد، استثنا ایجاد میکند. بنابراین، بهتر است کدگذاری دیگری مانند UTF-8 را مشخص کنید که میتواند هر نویسهی یونیکد را مدیریت کند.)
این بخش تنها شرحی جزئی از رابطهای ElementTree است. برای جزئیات بیشتر، لطفاً مستندات رسمی این بسته را بخوانید.
همچنین ملاحظه نمائید
- https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm
مستندات رسمی ElementTree.
بستهی hashlib¶
ماژول جدید hashlib، که توسط Gregory P. Smith نوشته شده است، برای جایگزینی ماژولهای md5 و sha اضافه شده است. hashlib پشتیبانی از هشهای امن بیشتری (SHA-224، SHA-256، SHA-384 و SHA-512) را میافزاید. در صورت موجود بودن، این ماژول از OpenSSL برای پیادهسازیهای سریع و بهینهشده برای پلتفرم الگوریتمها استفاده میکند.
ماژولهای قدیمی md5 و sha برای حفظ سازگاری با نسخههای پیشین، همچنان بهعنوان دربرگیرندههایی در اطراف hashlib وجود دارند. رابط ماژول جدید بسیار نزدیک به رابط ماژولهای قدیمی است، اما یکسان نیست. مهمترین تفاوت این است که توابع سازنده برای ایجاد اشیاء هشساز جدید، نامهای متفاوتی دارند.
# Old versions
h = md5.md5()
h = md5.new()
# New version
h = hashlib.md5()
# Old versions
h = sha.sha()
h = sha.new()
# New version
h = hashlib.sha1()
# Hash that weren't previously available
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()
# Alternative form
h = hashlib.new('md5') # Provide algorithm as a string
پس از ایجاد یک شیء هش، متدهای آن مانند قبل هستند: update(string) رشتهی مشخصشده را در وضعیت پردازش فعلی هش میکند، digest() و hexdigest() مقدار پردازش را بهصورت یک رشته دودویی یا رشتهای از ارقام مبنای شانزده برمیگردانند و copy() یک شیء هشکنندهی جدید با همان وضعیت پردازش برمیگرداند.
همچنین ملاحظه نمائید
مستندات ماژول hashlib.
بستهی sqlite3¶
ماژول pysqlite (https://www.pysqlite.org)، که دربرگیرندهای برای پایگاه داده تعبیهشده SQLite است، با نام بستهی sqlite3 به کتابخانه استاندارد افزوده شده است.
SQLite یک کتابخانه C است که پایگاه دادهای سبکوزن و مبتنی بر دیسک ارائه میکند که نیازی به فرایند جداگانه سرور ندارد و اجازه میدهد با استفاده از گونهای غیراستاندارد از زبان پرسوجوی SQL به پایگاه داده دسترسی داشته باشید. برخی از برنامهها میتوانند از SQLite برای ذخیرهسازی داخلی داده استفاده کنند. همچنین میتوان با استفاده از SQLite پیشنمونهای از یک برنامه ساخت و سپس کد را به یک پایگاه داده بزرگتر مانند PostgreSQL یا Oracle منتقل کرد.
pysqlite توسط Gerhard Häring نوشته شده است و رابطی SQL ارائه میدهد که مطابق با مشخصات DB-API 2.0 شرح دادهشده در PEP 249 است.
اگر خودتان سورس پایتون را کامپایل میکنید، توجه داشته باشید که درخت سورس شامل کد SQLite نیست و تنها ماژول پوششی را در بر دارد. باید پیش از کامپایل پایتون، کتابخانهها و سرآیندهای SQLite را نصب کرده باشید و فرایند ساخت نیز ماژول را هنگامی که سرآیندهای لازم در دسترس باشند کامپایل خواهد کرد.
برای استفاده از ماژول، ابتدا باید یک شیء Connection ایجاد کنید که نمایانگر پایگاه داده است. در اینجا دادهها در پروندهی /tmp/example ذخیره خواهند شد:
conn = sqlite3.connect('/tmp/example')
همچنین میتوانید نام ویژه :memory: را برای ایجاد یک پایگاه داده در حافظه (RAM) ارائه دهید.
پس از اینکه یک Connection داشته باشید، میتوانید یک شیء Cursor ایجاد کنید و برای اجرای دستورهای SQL، متد execute() آن را فراخوانی کنید:
c = conn.cursor()
# Create table
c.execute('''create table stocks
(date text, trans text, symbol text,
qty real, price real)''')
# Insert a row of data
c.execute("""insert into stocks
values ('2006-01-05','BUY','RHAT',100,35.14)""")
معمولاً عملیات SQL شما نیاز به استفاده از مقادیر متغیرهای پایتون خواهند داشت. نباید پرسوجوی خود را با استفاده از عملیات رشتهای پایتون بسازید، زیرا این کار ناامن است و برنامه شما را در برابر حمله تزریق SQL آسیبپذیر میکند.
در عوض، از جایگزینی پارامتر DB-API استفاده کنید. هر جا که میخواهید از مقداری استفاده کنید، ? را بهعنوان جاینگهدار قرار دهید و سپس تاپلی از مقادیر را بهعنوان آرگومان دوم به متد execute() نشانگر ارائه کنید. (ممکن است ماژولهای پایگاه داده دیگر از جاینگهدار متفاوتی استفاده کنند، مانند %s یا :1.) برای مثال:
# Never do this -- insecure!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)
# Do this instead
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)
# Larger example
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
('2006-04-06', 'SELL', 'IBM', 500, 53.00),
):
c.execute('insert into stocks values (?,?,?,?,?)', t)
برای بازیابی دادهها پس از اجرای دستور SELECT، میتوانید نشانگر را بهعنوان یک پیمایشگر در نظر بگیرید، متد fetchone() نشانگر را برای بازیابی یک ردیف منطبق فراخوانی کنید، یا fetchall() را برای دریافت فهرستی از ردیفهای منطبق فراخوانی کنید.
این مثال از شکل پیمایشگر استفاده میکند:
>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
... print row
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>
برای اطلاعات بیشتر دربارهی گویش SQL که توسط SQLite پشتیبانی میشود، به https://www.sqlite.org مراجعه کنید.
همچنین ملاحظه نمائید
- https://www.pysqlite.org
صفحهی وب pysqlite.
- https://www.sqlite.org
صفحه وب SQLite؛ مستندات، سینتکس و انواع دادهی موجود برای گویش SQL پشتیبانیشده را شرح میدهد.
مستندات ماژول sqlite3.
- PEP 249 - مشخصات API پایگاه داده 2.0
PEP نوشتهشده توسط مارک-آندره لمبرگ.
بستهی wsgiref¶
رابط دروازهی سرور وب (WSGI) v1.0 یک رابط استاندارد میان سرورهای وب و برنامههای وب پایتون را تعریف میکند و در PEP 333 شرح داده شده است. بستهی wsgiref یک پیادهسازی مرجع از مشخصات WSGI است.
این بسته شامل یک سرور HTTP پایه است که یک برنامه WSGI را اجرا میکند؛ این سرور برای اشکالزدایی مفید است اما برای استفاده در محیط عملیاتی در نظر گرفته نشده است. راهاندازی یک سرور تنها به چند سطر کد نیاز دارد:
from wsgiref import simple_server
wsgi_app = ...
host = ''
port = 8000
httpd = simple_server.make_server(host, port, wsgi_app)
httpd.serve_forever()
همچنین ملاحظه نمائید
- https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/
یک وبسایت مرکزی برای منابع مرتبط با WSGI.
- PEP 333 - Python Web Server Gateway Interface v1.0
PEP نوشتهشده توسط Phillip J. Eby.
تغییرات ساخت و API زبان C¶
تغییرات در فرایند ساخت پایتون و در API زبان C شامل موارد زیر است:
درخت سورس پایتون طی یک رویهی مهاجرت پیچیده که مارتین فون لویس بر آن نظارت داشت و آن را بینقص به اجرا درآورد، از CVS به Subversion تبدیل شد. این رویه بهصورت PEP 347 توسعه داده شد.
شرکت Coverity، که ابزار تحلیل کد منبعی به نام Prevent را به بازار عرضه میکند، نتایج بررسی خود از کد منبع پایتون را ارائه کرد. این تحلیل حدود ۶۰ اشکال را یافت که بهسرعت برطرف شدند. بسیاری از این اشکالات، مشکلات شمارش ارجاع بودند که اغلب در کد مدیریت خطا رخ میدادند. برای مشاهدهی آمار به https://scan.coverity.com مراجعه کنید.
بزرگترین تغییر در API زبان C از PEP 353 ناشی شد که مفسر را تغییر میدهد تا بهجای int از تعریف نوع
Py_ssize_tاستفاده کند. برای بحث درباره این تغییر، به بخش پیشین PEP 353: استفاده از ssize_t بهعنوان نوع اندیس مراجعه کنید.طراحی کامپایلر بایتکد تغییرات زیادی کرده است و دیگر بایتکد را با پیمایش درخت تجزیه تولید نمیکند. در عوض، درخت تجزیه به درخت سینتکس انتزاعی (یا AST) تبدیل میشود و همین درخت سینتکس انتزاعی است که برای تولید بایتکد پیمایش میشود.
کد پایتون میتواند با استفاده از توکار
compile()و مشخص کردن_ast.PyCF_ONLY_ASTبه عنوان مقدار پارامتر flags، اشیاء AST را به دست آورد:from _ast import PyCF_ONLY_AST ast = compile("""a=0 for i in range(10): a += i """, "<string>", 'exec', PyCF_ONLY_AST) assignment = ast.body[0] for_loop = ast.body[1]
هنوز هیچ مستند رسمی برای کد AST نوشته نشده است، اما PEP 339 به بحث دربارهی طراحی آن میپردازد. برای شروع آشنایی با این کد، تعریف گرههای مختلف AST را در
Parser/Python.asdlبخوانید. یک اسکریپت پایتون این پرونده را میخواند و مجموعهای از تعاریف ساختار C را درInclude/Python-ast.hتولید میکند. توابعPyParser_ASTFromString()وPyParser_ASTFromFile()که درInclude/pythonrun.hتعریف شدهاند، کد منبع پایتون را بهعنوان ورودی میگیرند و ریشهی یک AST را که نمایانگر محتویات است، برمیگردانند. سپس این AST میتواند توسطPyAST_Compile()به یک شیء کد تبدیل شود. برای اطلاعات بیشتر، کد منبع را بخوانید و سپس پرسشهای خود را در python-dev مطرح کنید.کد AST تحت مدیریت Jeremy Hylton توسعه یافت و توسط (به ترتیب الفبایی) Brett Cannon، Nick Coghlan، Grant Edwards، John Ehresman، Kurt Kaiser، Neal Norwitz، Tim Peters، Armin Rigo و Neil Schemenauer و همچنین شرکتکنندگان در تعدادی اسپرینت (sprint) AST در کنفرانسهایی مانند PyCon پیادهسازی شد.
وصل Evan Jones به obmalloc، که نخستینبار در یک سخنرانی در PyCon DC 2005 شرح داده شد، اعمال شد. پایتون 2.4 اشیاء کوچک را در آرناهایی (arena) به اندازهی 256K تخصیص میداد، اما هرگز آرناها را آزاد نمیکرد. با این وصل، پایتون آرناها را زمانی که خالی باشند آزاد میکند. اثر خالص این است که در برخی سکوها، وقتی اشیاء زیادی را تخصیص میدهید، ممکن است مصرف حافظهی پایتون با حذف آنها واقعاً کاهش یابد و حافظه ممکن است به سیستمعامل بازگردانده شود. (پیادهسازی توسط Evan Jones و بازنویسی توسط Tim Peters.)
توجه داشته باشید که این تغییر به این معناست که ماژولهای توسعهای باید هنگام تخصیص حافظه احتیاط بیشتری داشته باشند. API پایتون توابع مختلفی برای تخصیص حافظه دارد که در قالب خانوادههایی گروهبندی شدهاند. برای مثال،
PyMem_Malloc()،PyMem_Realloc()وPyMem_Free()یک خانواده هستند که حافظهی خام تخصیص میدهند، در حالی کهPyObject_Malloc()،PyObject_Realloc()وPyObject_Free()خانوادهی دیگری هستند که قرار است برای ایجاد اشیاء پایتون استفاده شوند.پیشتر این خانوادههای مختلف همگی به توابع
malloc()وfree()پلتفرم تقلیل مییافتند. این بدان معنا بود که اگر اشتباه میکردید و حافظه را با تابعPyMemتخصیص میدادید اما آن را با تابعPyObjectآزاد میکردید، اهمیتی نداشت. با تغییرات نسخهی 2.5 در obmalloc، این خانوادهها اکنون کارهای متفاوتی انجام میدهند و عدم تطابقها احتمالاً به خطای قطعهبندی (segfault) منجر خواهند شد. شما باید ماژولهای توسعهای C خود را با Python 2.5 بهدقت آزمایش کنید.نوعهای مجموعهی توکار اکنون یک API رسمی C دارند.
PySet_New()وPyFrozenSet_New()را برای ایجاد یک مجموعهی جدید،PySet_Add()وPySet_Discard()را برای افزودن و حذف المانها، وPySet_Contains()وPySet_Size()را برای بررسی وضعیت مجموعه فراخوانی کنید. (مشارکتشده توسط Raymond Hettinger.)کد C اکنون میتواند با فراخوانی تابع
Py_GetBuildInfo()که رشتهای از اطلاعات ساخت مانند"trunk:45355:45356M, Apr 13 2006, 07:42:19"را برمیگرداند، اطلاعاتی دربارهی نسخهی دقیق مفسر پایتون به دست آورد. (ارائهشده توسط بری ورشو.)از دو ماکروی جدید میتوان برای نشان دادن توابع Cای که محلی به پروندهی فعلی هستند استفاده کرد تا بتوان از یک قرارداد فراخوانی سریعتر بهره برد.
Py_LOCALتابع را بهعنوان تابعی که مقداری از نوع مشخصشده برمیگرداند اعلان میکند و از یک مشخصکنندهی فراخوانی سریع استفاده میکند.Py_LOCAL_INLINEهمین کار را انجام میدهد و همچنین درخواست میکند که تابع بهصورت درونخطی شود. اگر ماکروPY_LOCAL_AGGRESSIVEپیش از گنجانده شدنpython.hتعریف شده باشد، مجموعهای از بهینهسازیهای تهاجمیتر برای ماژول فعال میشوند؛ شما باید نتایج را بنچمارک کنید تا متوجه شوید که آیا این بهینهسازیها واقعاً کد را سریعتر میکنند یا خیر. (مشارکتشده توسط فردریک لوند در اسپرینت NeedForSpeed.)PyErr_NewException(name, base, dict)اکنون میتواند یک تاپل از کلاسهای پایه را بهعنوان آرگومان base خود بپذیرد. (مشارکتشده توسط Georg Brandl.)تابع
PyErr_Warn()برای صدور هشدارها اکنون منسوخ شده است و بهجای آن ازPyErr_WarnEx(category, message, stacklevel)استفاده میشود که به شما امکان میدهد تعداد فریمهای پشتهای را که این تابع و فراخواننده را از هم جدا میکنند مشخص کنید. مقدار stacklevel برابر با ۱ تابعی است کهPyErr_WarnEx()را فراخوانی میکند، ۲ تابع بالاتر از آن است، و به همین ترتیب. (اضافهشده توسط نیل نورویتز.)مفسر سیپایتون همچنان به زبان C نوشته شده است، اما اکنون میتوان کد را با کامپایلر C++ و بدون هیچ خطایی کامپایل کرد. (پیادهسازیشده توسط آنتونی باکستر، مارتین فون لوییس و اسکیپ مونتانارو.)
تابع
PyRange_New()حذف شد. این تابع هرگز مستند نشده بود، هرگز در کد هسته استفاده نشده بود و بررسی خطای آن بهطرز خطرناکی سست بود. در حالت بعید که ماژولهای توسعهای شما از آن استفاده میکردند، میتوانید آن را با چیزی شبیه به موارد زیر جایگزین کنید:range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll", start, stop, step);
تغییرات خاص پورت¶
MacOS X (10.3 و بالاتر): بارگذاری پویای ماژولها اکنون بهجای توابع اختصاصی MacOS از تابع
dlopen()استفاده میکند.MacOS X: سوییچ
--enable-universalsdkبه اسکریپت configure اضافه شد که مفسر را بهصورت یک دودویی همگانی (universal binary) قابل اجرا روی هر دو پردازندهی PowerPC و Intel کامپایل میکند. (با مشارکت Ronald Oussoren؛ bpo-2573.)ویندوز:
.dllدیگر بهعنوان پسوند نام پرونده برای ماژولهای توسعهای پشتیبانی نمیشود..pydاکنون تنها پسوند نام پروندهای است که جستجو خواهد شد.
انتقال به پایتون 2.5¶
این بخش، تغییراتی را که پیشتر شرح داده شدهاند و ممکن است نیازمند تغییراتی در کد شما باشند، فهرست میکند:
اسکی اکنون کدگذاری پیشفرض ماژولها است. اگر ماژولی حاوی مقادیر لفظی رشتهای با نویسههای ۸-بیتی باشد اما اعلان کدگذاری نداشته باشد، اکنون این یک خطای نحوی است. در پایتون 2.4 این مورد هشداری ایجاد میکرد، نه خطای نحوی.
پیشتر، ویژگی
gi_frameیک تولیدگر همیشه یک شیء فریم بود. به دلیل تغییرات PEP 342 که در بخش PEP 342: قابلیتهای جدید تولیدگر توضیح داده شدهاند، اکنون ممکن استgi_frameNoneباشد.یک هشدار جدید،
UnicodeWarning، زمانی فعال میشود که شما تلاش کنید یک رشتهی یونیکد را با یک رشتهی ۸-بیتی که نمیتوان آن را با استفاده از کدگذاری پیشفرض اسکی به یونیکد تبدیل کرد، مقایسه کنید. پیشتر چنین مقایسههایی استثنایUnicodeDecodeErrorایجاد میکردند.کتابخانه: ماژول
csvاکنون در مورد فیلدهای نقلقولی چندسطری سختگیرانهتر است. اگر پروندههای شما شامل سطرهای جدید تعبیهشده درون فیلدها هستند، ورودی باید به گونهای به سطرها تقسیم شود که نویسههای سطر جدید حفظ شوند.کتابخانه: تابع
format()ماژولlocaleپیشتر هر رشتهای را میپذیرفت، به شرط آنکه بیش از یک مشخصکنندهی %char در آن نباشد. در پایتون 2.5، آرگومان باید دقیقاً یک مشخصکنندهی %char بدون هیچ متنی در اطراف آن باشد.کتابخانه: ماژولهای
pickleوcPickleدیگر مقدار بازگشتیNoneرا از متد__reduce__()نمیپذیرند؛ این متد باید بهجای آن تاپلی از آرگومانها را برگرداند. این ماژولها همچنین دیگر پارامتر کلیدواژهای منسوخ bin را نمیپذیرند.کتابخانه: کلاسهای
SimpleXMLRPCServerوDocXMLRPCServerاکنون دارای ویژگیrpc_pathsهستند که عملیات XML-RPC را به مجموعهی محدودی از مسیرهای URL محدود میکند؛ پیشفرض این است که فقط'/'و'/RPC2'مجاز باشند. تنظیمrpc_pathsرویNoneیا یک تاپل خالی، این بررسی مسیر را غیرفعال میکند.API زبان C: بسیاری از توابع اکنون از
Py_ssize_tبه جای int استفاده میکنند تا امکان پردازش دادههای بیشتر روی رایانههای ۶۴ بیتی فراهم شود. کد توسعهای ممکن است برای جلوگیری از هشدارها و پشتیبانی از رایانههای ۶۴ بیتی، نیاز به اعمال همین تغییر داشته باشد. برای بحث دربارهی این تغییر، به بخش پیشین PEP 353: استفاده از ssize_t بهعنوان نوع اندیس مراجعه کنید.API زبان C: تغییرات obmalloc به این معناست که شما باید مراقب باشید که استفاده از خانوادههای توابع
PyMem_*وPyObject_*را با هم مخلوط نکنید. حافظهای که با*_Mallocیکی از خانوادهها تخصیص یافته است، باید با تابع*_Freeخانوادهی متناظر آزاد شود.
سپاسگزاریها¶
نویسنده مایل است از افراد زیر بهخاطر پیشنهادها، اصلاحات و کمکهایی که در پیشنویسهای مختلف این مقاله ارائه کردهاند، قدردانی کند: Georg Brandl, Nick Coghlan, Phillip J. Eby, Lars Gustäbel, Raymond Hettinger, Ralf W. Grosse-Kunstleve, Kent Johnson, Iain Lowe, Martin von Löwis, Fredrik Lundh, Andrew McNamara, Skip Montanaro, Gustavo Niemeyer, Paul Prescod, James Pryor, Mike Rovner, Scott Weikart, Barry Warsaw, Thomas Wouters.