تازههای پایتون 2.1¶
- نویسنده:
A.M. Kuchling
مقدمه¶
این مقاله قابلیتهای جدید پایتون 2.1 را توضیح میدهد. اگرچه تغییرات نسخهی 2.1 به اندازهی پایتون 2.0 فراوان نیستند، همچنان شگفتیهای خوشایندی در انتظار شماست. نسخهی 2.1 نخستین نسخهی پایتون است که با استفاده از پیشنهادهای بهبود پایتون یا همان PEPها هدایت شده است؛ بنابراین بیشترِ تغییرات بزرگ دارای PEPهای همراهی هستند که مستنداتی کاملتر و منطق طراحیِ تغییر ارائه میدهند. این مقاله تلاشی برای مستندسازی کامل قابلیتهای جدید نمیکند، بلکه صرفاً نمای کلی از قابلیتهای جدید برای برنامهنویسان پایتون ارائه میدهد. برای جزئیات بیشتر دربارهی هر قابلیت جدیدی که بهطور خاص مورد علاقهی شماست، به مستندات پایتون 2.1 یا به PEP مربوطه مراجعه کنید.
یکی از اهداف اخیر تیم توسعه پایتون، شتاب بخشیدن به آهنگ انتشار نسخههای جدید بوده است، بهگونهای که هر ۶ تا ۹ ماه یک نسخهی جدید منتشر میشود. نسخه 2.1 نخستین نسخهای است که با این آهنگ سریعتر عرضه شد؛ بهطوری که نخستین نسخه آلفا در ژانویه، ۳ ماه پس از انتشار نسخه نهایی 2.0، ظاهر شد.
نسخه نهایی پایتون 2.1 در ۱۷ آوریل ۲۰۰۱ منتشر شد.
PEP 227: محدودههای تودرتو¶
بزرگترین تغییر در پایتون 2.1، در قواعد تعیین محدوده پایتون است. در پایتون 2.0، در هر لحظه حداکثر سه فضای نام برای جستجوی نام متغیرها استفاده میشود: محلی، سطح ماژول، و فضای نام توکار. این امر اغلب افراد را غافلگیر میکرد، زیرا با انتظارات شهودیشان مطابقت نداشت. برای مثال، تعریف یک تابع بازگشتی تودرتو کار نمیکند:
def f():
...
def g(value):
...
return g(value-1) + 1
...
تابع g() همیشه یک استثنای NameError ایجاد میکند، زیرا مقیدسازی نام g نه در فضای نام محلی آن و نه در فضای نام در سطح ماژول وجود ندارد. این در عمل مشکل چندانی نیست (چند وقت یکبار توابع داخلیای از این دست را بهصورت بازگشتی تعریف میکنید؟)، اما همین امر استفاده از عبارت lambda را نیز دستوپاگیرتر میکرد و این در عمل مشکلساز بود. در کدهایی که از lambda استفاده میکنند، اغلب میتوانید متغیرهای محلیای را بیابید که با ارسال آنها بهعنوان مقادیر پیشفرض آرگومانها کپی میشوند.
def find(self, name):
"Return list of any entries equal to 'name'"
L = filter(lambda x, name=name: x == name,
self.list_attribute)
return L
در نتیجه، خوانایی کد پایتونی که به سبکی کاملاً تابعی نوشتهشده است، بهشدت آسیب میبیند.
مهمترین تغییر در Python 2.1 این است که محدودهدهی ایستا (static scoping) برای رفع این مشکل به زبان افزوده شده است. بهعنوان نخستین اثر، آرگومان پیشفرض name=name در مثال بالا دیگر ضروری نیست. به زبان ساده، وقتی درون تابع مقداری به نام متغیر معینی انتساب داده نشود (از طریق یک انتساب یا دستورهای def، class یا import)، ارجاعهای به آن متغیر در فضای نام محلیِ محدوده دربرگیرنده جستجو خواهند شد. توضیح دقیقتر قواعد و کالبدشکافی پیادهسازی را میتوان در PEP یافت.
این تغییر ممکن است برخی مشکلات سازگاری برای کدی ایجاد کند که در آن، نام متغیر یکسان هم در سطح ماژول و هم بهعنوان متغیر محلی درون تابعی که تعریفهای تابع بیشتری در بر دارد، استفاده میشود. با این حال، این موضوع نسبتاً بعید بهنظر میرسد، زیرا چنین کدی از همان ابتدا برای خواندن بسیار سردرگمکننده بود.
یکی از اثرهای جانبی این تغییر آن است که دستورهای from module import * و exec تحت شرایط خاصی درون محدودهی تابع غیرمجاز شدهاند. راهنمای مرجع پایتون از همان ابتدا گفته است که from module import * فقط در سطح بالای یک ماژول مجاز است، اما مفسر سیپایتون پیش از این هرگز این موضوع را اعمال نکرده بود. بهعنوان بخشی از پیادهسازی محدودههای تودرتو، کامپایلری که کد منبع پایتون را به بایتکد تبدیل میکند، باید برای دسترسی به متغیرها در محدودهی دربرگیرنده کد متفاوتی تولید کند. دستورهای from module import * و exec امکان تشخیص این موضوع را از کامپایلر میگیرند، زیرا این دستورها نامهایی به فضای نام محلی اضافه میکنند که در زمان کامپایل قابل دانستن نیستند. بنابراین، اگر تابعی شامل تعریفهای تابع یا عبارتهای lambda با متغیرهای آزاد باشد، کامپایلر این موضوع را با ایجاد استثنای SyntaxError علامتگذاری میکند.
برای اینکه توضیح پیشین کمی روشنتر شود، در اینجا مثالی آورده شده است:
x = 1
def f():
# The next line is a syntax error
exec 'x=2'
def g():
return x
سطر ۴ حاوی دستور exec یک خطای سینتکسی است، زیرا exec متغیر محلی جدیدی به نام x تعریف میکرد که مقدار آن باید توسط g() قابل دسترسی باشد.
این موضوع نباید محدودیت زیادی باشد، زیرا exec بهندرت در بیشتر کدهای پایتون استفاده میشود (و هنگامی که استفاده میشود، اغلب به هر حال نشانهی یک طراحی ضعیف است).
نگرانیهای سازگاری باعث شد که محدودههای تودرتو بهتدریج معرفی شوند؛ در پایتون 2.1، این محدودهها بهطور پیشفرض فعال نیستند، اما میتوان آنها را درون یک ماژول با استفاده از دستور آینده (future statement)، همانطور که در PEP 236 شرح داده شده است، فعال کرد. (برای بحث بیشتر دربارهی PEP 236 به بخش بعدی مراجعه کنید.) در پایتون 2.2، محدودههای تودرتو پیشفرض خواهند شد و هیچ راهی برای غیرفعال کردن آنها وجود نخواهد داشت، اما کاربران تمام طول عمر نسخهی 2.1 را برای رفع هرگونه خرابی ناشی از معرفی آنها در اختیار خواهند داشت.
همچنین ملاحظه نمائید
- PEP 227 - محدودههای تودرتوی ایستا
نوشته و پیادهسازیشده توسط جرمی هایلتون.
PEP 236: دایرکتیوهای __future__¶
واکنش به محدودههای تودرتو، نگرانی گستردهای دربارهی خطر از کار افتادن کدها با نسخهی 2.1 بود و این نگرانی به اندازهای قوی بود که پایتونکارها (Pythoneers) را واداشت رویکردی محافظهکارانهتر در پیش بگیرند. این رویکرد شامل معرفی یک قرارداد برای فعالسازی قابلیت اختیاری در نسخهی N است که در نسخهی N+1 الزامی خواهد شد.
این سینتکس از دستور from...import با استفاده از نام ماژول رزروشدهی __future__ استفاده میکند. محدودههای تودرتو را میتوان با دستور زیر فعال کرد:
from __future__ import nested_scopes
اگرچه این دستور شبیه یک دستور import معمولی به نظر میرسد، چنین نیست؛ قواعد سختگیرانهای دربارهی محل قرارگیری چنین دستور آیندهای (future statement) وجود دارد. این دستورها تنها میتوانند در ابتدای یک ماژول قرار بگیرند و باید پیش از هر کد پایتون یا دستور import معمولی بیایند. این بدان دلیل است که چنین دستورهایی میتوانند بر نحوهی پارس کردن کد و تولید بایتکد توسط کامپایلر بایتکد پایتون تأثیر بگذارند، بنابراین باید پیش از هر دستوری که منجر به تولید بایتکدها میشود بیایند.
همچنین ملاحظه نمائید
- PEP 236 - بازگشت به
__future__ نوشته Tim Peters، و عمدتاً پیادهسازیشده توسط Jeremy Hylton.
PEP 207: مقایسههای غنی (Rich Comparisons)¶
در نسخههای پیشین، پشتیبانی پایتون از پیادهسازی مقایسهها روی کلاسهای تعریفشده توسط کاربر و نوعهای توسعهای بسیار ساده بود. کلاسها میتوانستند متد __cmp__() را پیادهسازی کنند که دو نمونه از یک کلاس به آن داده میشد و تنها میتوانست در صورت برابر بودن آنها مقدار 0 و در صورت برابر نبودن مقدار +1 یا -1 برگرداند؛ این متد نمیتوانست استثنا مطرح کند یا چیزی غیر از یک مقدار بولی برگرداند. کاربران Numeric Python اغلب این مدل را بیش از حد ضعیف و محدودکننده مییافتند، زیرا در برنامههای محاسبات عددی سنگینی که Numeric Python برای آنها به کار میرود، مفیدتر بود که بتوان مقایسههای درایهبهدرایهی دو ماتریس را انجام داد و ماتریسی حاوی نتایج یک مقایسهی مشخص برای هر درایه را برگرداند. اگر دو ماتریس اندازههای متفاوتی داشته باشند، مقایسه باید بتواند برای علامتدادن به خطا، استثنا مطرح کند.
در پایتون 2.1، مقایسههای غنی (rich comparisons) به منظور پشتیبانی از این نیاز اضافه شدند. کلاسهای پایتون اکنون میتوانند هر یک از عملیاتهای <، <=، >، >=، == و != را بهطور جداگانه سربارگذاری کنند. نامهای متدهای جادویی جدید عبارتاند از:
عملیات |
نام متد |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
(متدهای جادویی بر اساس عملگرهای متناظر فورترن .LT.، .LE. و غیره نامگذاری شدهاند. برنامهنویسان محاسبات عددی تقریباً بهطور قطع با این نامها کاملاً آشنا هستند و بهسادگی آنها را به یاد خواهند سپرد.)
هر یک از این متدهای جادویی به شکل method(self, other) است، که در آن self شیء سمت چپ عملگر و other شیء سمت راست عملگر خواهد بود. برای مثال، عبارت A < B باعث میشود A.__lt__(B) فراخوانی شود.
هر یک از این متدهای جادویی میتواند هر چیزی را بازگرداند: یک مقدار بولی، یک ماتریس، یک فهرست، یا هر شیء پایتون دیگری. از سوی دیگر، اگر مقایسه غیرممکن، ناسازگار یا به هر شکل بیمعنا باشد، میتوانند استثنا ایجاد کنند.
تابع توکار cmp(A,B) میتواند از سازوکار مقایسهی غنی استفاده کند و اکنون یک آرگومان اختیاری میپذیرد که مشخص میکند از کدام عملیات مقایسه استفاده شود؛ این آرگومان بهصورت یکی از رشتههای "<"، "<="، ">"، ">="، "==" یا "!=" داده میشود. اگر بدون سومین آرگومان اختیاری فراخوانی شود، cmp() مانند نسخههای قبلی پایتون فقط -۱، ۰ یا +۱ را برمیگرداند؛ در غیر این صورت، متد مناسب را فراخوانی میکند و میتواند هر شیء پایتونی را برگرداند.
تغییرات متناظری نیز وجود دارد که برای برنامهنویسان C جالب توجهاند؛ یک جایگاه جدید tp_richcmp در اشیاء نوع و یک API برای انجام یک مقایسه غنی (rich comparison) مشخص وجود دارد. من در اینجا C API را پوشش نمیدهم، اما برای فهرست کامل توابع مرتبط، شما را به PEP 207 یا مستندات C API نسخه 2.1 ارجاع میدهم.
همچنین ملاحظه نمائید
- PEP 207 - مقایسههای غنی (Rich Comparisons)
نوشتهی گیدو ونروسوم، بهطور گستردهای بر پایهی کارهای پیشین دیوید آشر، و پیادهسازیشده توسط گیدو ونروسوم.
PEP 230: چارچوب هشدار¶
پایتون در طول ۱۰ سال وجود خود، در این مسیر تعدادی ماژول و قابلیت منسوخ انباشته است. دانستن اینکه حذف یک قابلیت چه زمانی بیخطر است دشوار است، زیرا هیچ راهی برای دانستن اینکه چه مقدار کد از آن استفاده میکند وجود ندارد --- شاید هیچ برنامهای به آن قابلیت وابسته نباشد، یا شاید برنامههای بسیاری وابسته باشند. برای اینکه حذف قابلیتهای قدیمی به شکلی ساختاریافتهتر ممکن باشد، یک چارچوب هشدار اضافه شد. هنگامی که توسعهدهندگان پایتون بخواهند قابلیتی را حذف کنند، آن قابلیت ابتدا در نسخه بعدی پایتون هشداری صادر میکند. پس از آن، نسخه بعدی پایتون میتواند آن قابلیت را به کلی حذف کند، و کاربران یک چرخه انتشار کامل فرصت خواهند داشت تا استفادههای خود از قابلیت قدیمی را حذف کنند.
پایتون 2.1 چارچوب هشدار را برای استفاده در این طرح اضافه میکند. این نسخه ماژول warnings را اضافه میکند که توابعی برای صدور هشدار و فیلتر کردن هشدارهایی که نمیخواهید نمایش داده شوند فراهم میکند. ماژولهای شخص ثالث نیز میتوانند از این چارچوب برای منسوخ کردن ویژگیهای قدیمی که دیگر نمیخواهند از آنها پشتیبانی کنند، استفاده کنند.
برای مثال، در پایتون 2.1 ماژول regex منسوخ شده است، بنابراین ایمپورت کردن آن باعث چاپ شدن یک هشدار میشود:
>>> import regex
__main__:1: DeprecationWarning: the regex module
is deprecated; please use the re module
>>>
میتوان هشدارها را با فراخوانی تابع warnings.warn() صادر کرد:
warnings.warn("feature X no longer supported")
پارامتر اول، پیام هشدار است؛ میتوان از پارامترهای اختیاری اضافی برای مشخص کردن دستهبندی هشدار خاصی استفاده کرد.
میتوان فیلترهایی افزود تا هشدارهای معینی غیرفعال شوند؛ به منظور سرکوب یک هشدار، میتوان یک الگوی عبارت باقاعده را روی پیام یا نام ماژول اعمال کرد. برای مثال، ممکن است برنامهای داشته باشید که از ماژول regex استفاده میکند و در حال حاضر نخواهید زمانی را برای تبدیل آن به استفاده از ماژول re صرف کنید. میتوان این هشدار را با فراخوانی زیر سرکوب کرد
import warnings
warnings.filterwarnings(action = 'ignore',
message='.*regex module is deprecated',
category=DeprecationWarning,
module = '__main__')
این کار یک فیلتر اضافه میکند که فقط به هشدارهایی از کلاس DeprecationWarning که در ماژول __main__ ایجاد شدهاند اعمال میشود، و یک عبارت باقاعده را به کار میگیرد تا فقط پیام مربوط به منسوخ شدن ماژول regex را تطبیق دهد، و باعث میشود چنین هشدارهایی نادیده گرفته شوند. هشدارها همچنین میتوانند فقط یک بار چاپ شوند، هر بار که کد مقصر اجرا میشود چاپ شوند، یا به استثناهایی تبدیل شوند که باعث توقف برنامه میشوند (البته مگر اینکه استثناها به روش معمول گرفته شوند).
توابعی نیز برای صدور هشدار به API زبان C پایتون اضافه شدند؛ برای جزئیات به PEP 230 یا مستندات API پایتون مراجعه کنید.
همچنین ملاحظه نمائید
- PEP 5 - رهنمودهایی برای تکامل زبان
نوشتهی پل پرسکاد، برای تعیین رویههایی که هنگام حذف قابلیتهای قدیمی از پایتون باید رعایت شوند. سیاست توصیفشده در این PEP رسماً پذیرفته نشده است، اما سیاست نهایی احتمالاً تفاوت زیادی با پیشنهاد پرسکاد نخواهد داشت.
- PEP 230 - چارچوب هشدار
نوشته و پیادهسازیشده توسط گیدو ونروسوم.
PEP 229: سیستم ساخت جدید¶
هنگام کامپایل پایتون، کاربر ناچار بود وارد شود و پروندهی Modules/Setup را ویرایش کند تا ماژولهای اضافی گوناگون فعال شوند؛ مجموعهی پیشفرض نسبتاً کوچک است و به ماژولهایی محدود میشود که روی بیشتر پلتفرمهای یونیکس کامپایل میشوند. این بدان معناست که روی پلتفرمهای یونیکس با ویژگیهای بسیار بیشتر (بهویژه لینوکس)، نصبهای پایتون اغلب همهی ماژولهای مفیدی را که میتوانستند داشته باشند، در بر نمیگیرند.
پایتون 2.0 مجموعهای از ماژولها به نام Distutils را برای توزیع و نصب ماژولهای توسعهای افزود. در پایتون 2.1، از Distutils برای کامپایل بخش عمدهای از کتابخانه استاندارد ماژولهای توسعهای استفاده میشود و بهطور خودکار تشخیص میدهد که کدام ماژولها روی ماشین فعلی پشتیبانی میشوند. امید است که این امر باعث شود نصب پایتون آسانتر و دارای امکانات بیشتری باشد.
بهجای اینکه برای فعالسازی ماژولها مجبور باشید پروندهی Modules/Setup را ویرایش کنید، اسکریپت setup.py در پوشهی بالایی توزیع سورس پایتون در زمان ساخت اجرا میشود و تلاش میکند با بررسی ماژولها و پروندههای سرآیند موجود در سیستم تشخیص دهد که کدام ماژولها قابل فعالسازی هستند. اگر ماژولی در Modules/Setup پیکربندی شده باشد، اسکریپت setup.py تلاشی برای کامپایل آن ماژول نمیکند و به محتوای پروندهی Modules/Setup تبعیت خواهد کرد. این، راهی برای مشخص کردن هر پرچم خط فرمان یا کتابخانهی عجیبی که برای یک پلتفرم خاص لازم است فراهم میکند.
در تغییر گستردهی دیگری در سازوکار ساخت، Neil Schemenauer ساختار را بهگونهای بازآرایی کرد که پایتون اکنون بهجای makefileهایی که در پوشهی اصلی و در هر یک از زیرپوشههای Python/، Parser/، Objects/ و Modules/ قرار داشتند، از یک makefile واحد که بازگشتی نیست استفاده میکند. این کار ساخت پایتون را سریعتر میکند و همچنین دستکاری Makefileها را روشنتر و سادهتر میکند.
همچنین ملاحظه نمائید
- PEP 229 - استفاده از Distutils برای ساخت پایتون
نوشته و پیادهسازیشده توسط A.M. Kuchling.
PEP 205: ارجاعهای ضعیف¶
ارجاعهای ضعیف، که از طریق ماژول weakref در دسترساند، نوع دادهی جدیدِ کوچک اما مفیدی در جعبهابزار برنامهنویس پایتون به شمار میروند.
ذخیرهی یک ارجاع به یک شیء (مثلاً در یک دیکشنری یا فهرست) این اثر جانبی را دارد که آن شیء برای همیشه زنده میماند. چند مورد خاص وجود دارد که این رفتار در آنها ناخواسته است؛ رایجترین آنها نهانگاههای شیء است و مورد دیگر ارجاعهای چرخهای در ساختارهای دادهای مانند درختها است.
برای مثال، تابعی بهخاطرسپار (memoizing) را در نظر بگیرید که نتایج تابع دیگر f(x) را با ذخیرهی آرگومان تابع و نتیجهی آن در یک دیکشنری، در نهانگاه نگه میدارد:
_cache = {}
def memoize(x):
if _cache.has_key(x):
return _cache[x]
retval = f(x)
# Cache the returned object
_cache[x] = retval
return retval
این نسخه برای موارد سادهای مانند اعداد صحیح کار میکند، اما یک اثر جانبی دارد؛ دیکشنری _cache ارجاعی به مقادیر بازگشتی نگه میدارد، بنابراین این مقادیر تا زمانی که فرایند پایتون خارج شود و پاکسازی کند، هرگز آزاد نمیشوند. این موضوع برای اعداد صحیح چندان محسوس نیست، اما اگر f() شیئی یا ساختار دادهای که حافظهی زیادی اشغال میکند برگرداند، این میتواند مشکلساز باشد.
ارجاعهای ضعیف راهی برای پیادهسازی نهانگاهی فراهم میکنند که اشیاء را فراتر از زمان حیاتشان زنده نگه نمیدارد. اگر یک شیء فقط از طریق ارجاعهای ضعیف دسترسیپذیر باشد، شیء تخصیصزدایی خواهد شد و ارجاعهای ضعیف از این پس نشان خواهند داد که شیءای که به آن ارجاع میدادند دیگر وجود ندارد. ارجاع ضعیف به شیء obj با فراخوانی wr = weakref.ref(obj) ساخته میشود. شیء ارجاعشده با فراخوانی ارجاع ضعیف، همچون یک تابع، بازگردانده میشود: wr(). این فراخوانی شیء ارجاعشده را بازمیگرداند، یا اگر شیء دیگر وجود نداشته باشد، None.
این کار امکان میدهد تابعی memoize() بنویسید که نهانگاهش با ذخیرهسازی ارجاعهای ضعیف در نهانگاه، اشیاء را زنده نگه نمیدارد.
_cache = {}
def memoize(x):
if _cache.has_key(x):
obj = _cache[x]()
# If weak reference object still exists,
# return it
if obj is not None: return obj
retval = f(x)
# Cache a weak reference
_cache[x] = weakref.ref(retval)
return retval
ماژول weakref همچنین اجازه میدهد اشیاء پراکسیای ایجاد کنید که مانند ارجاعهای ضعیف رفتار میکنند --- شیئی که تنها اشیاء پراکسی به آن ارجاع دارند، آزاد میشود -- اما بهجای نیاز به فراخوانی صریح برای بازیابی شیء، پراکسی تا زمانی که شیء هنوز وجود دارد، تمام عملیات را بهطور شفاف به شیء ارسال میکند. اگر شیء آزاد شده باشد، تلاش برای استفاده از یک پراکسی باعث میشود استثنای weakref.ReferenceError مطرح شود.
proxy = weakref.proxy(obj)
proxy.attr # Equivalent to obj.attr
proxy.meth() # Equivalent to obj.meth()
del obj
proxy.attr # raises weakref.ReferenceError
همچنین ملاحظه نمائید
- PEP 205 - ارجاعهای ضعیف
نوشته و پیادهسازیشده توسط Fred L. Drake, Jr.
PEP 232: ویژگیهای تابع¶
در پایتون 2.1، اکنون میتوان اطلاعات دلخواهی را به توابع الصاق کرد. افراد اغلب از رشتههای مستند برای نگهداشتن اطلاعاتی دربارهی توابع و متدها استفاده میکردند، زیرا ویژگی __doc__ تنها راه الصاق هرگونه اطلاعات به یک تابع بود. برای مثال، در سرور وباپلیکیشن Zope، توابع با داشتن یک رشته مستند، بهعنوان امن برای دسترسی عمومی علامتگذاری میشوند، و در چارچوب پارسینگ SPARK جان آیکوک، رشتههای مستند بخشهایی از گرامر BNF را که باید پارس شوند نگه میدارند. این سربارگذاری تأسفبار است، زیرا هدف رشتههای مستند در واقع نگهداشتن مستندات یک تابع است؛ برای مثال، این بدان معناست که نمیتوانید توابعی را که برای استفادهی خصوصی در Zope در نظر گرفته شدهاند، بهدرستی مستند کنید.
اکنون میتوان ویژگیهای دلخواه را روی توابع با استفاده از سینتکس معمول پایتون تنظیم و بازیابی کرد:
def f(): pass
f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"
دیکشنری حاوی ویژگیها از طریق __dict__ تابع قابل دسترسی است. برخلاف ویژگی __dict__ در نمونههای کلاس، در توابع در واقع میتوانید دیکشنری جدیدی را به __dict__ انتساب دهید، هرچند مقدار جدید محدود به یک دیکشنری معمولی پایتون است؛ نمیتوانید با زیرکی آن را برابر با نمونهای از UserDict یا هر شیء دلخواه دیگری که مانند یک نگاشت رفتار میکند قرار دهید.
همچنین ملاحظه نمائید
- PEP 232 - ویژگیهای تابع
نوشته و پیادهسازیشده توسط Barry Warsaw.
PEP 235: ایمپورت کردن ماژولها در پلتفرمهای غیرحساس به بزرگی و کوچکی حروف¶
برخی از سیستمهای عامل سامانه فایلبندیهایی دارند که به بزرگی و کوچکی حروف حساس نیستند؛ MacOS و Windows نمونههای اصلی این دستهاند. در چنین سیستمهایی، تمایز میان نام پروندههای FILE.PY و file.py ناممکن است، هرچند این سیستمها نام پرونده را با همان بزرگی و کوچکی حروف اصلی ذخیره میکنند (یعنی بزرگی و کوچکی حروف را نیز حفظ میکنند).
در پایتون 2.1، دستور import برای شبیهسازی حساسیت به بزرگی و کوچکی حروف روی پلتفرمهای غیرحساس به بزرگی و کوچکی حروف کار میکند. پایتون اکنون بهصورت پیشفرض نخستین تطبیق حساس به بزرگی و کوچکی حروف را جستوجو میکند و در صورتی که چنین پروندهای یافت نشود، یک ImportError ایجاد میکند؛ بنابراین import file ماژولی با نام FILE.PY را ایمپورت نمیکند. میتوان با تنظیم متغیر محیطی PYTHONCASEOK پیش از راهاندازی مفسر پایتون، تطبیق غیرحساس به بزرگی و کوچکی حروف را درخواست کرد.
PEP 217: قلاب نمایش تعاملی¶
هنگام استفاده تعاملی از مفسر پایتون، خروجی دستورات با استفاده از تابع توکار repr() نمایش داده میشود. در پایتون 2.1، میتوان متغیر sys.displayhook() را روی یک شیء فراخوانیپذیر تنظیم کرد که بهجای repr() فراخوانی خواهد شد. برای مثال، میتوانید آن را روی یک تابع خاص چاپ زیبا (pretty-printing) تنظیم کنید:
>>> # Create a recursive data structure
... L = [1,2,3]
>>> L.append(L)
>>> L # Show Python's default output
[1, 2, 3, [...]]
>>> # Use pprint.pprint() as the display function
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3, <Recursion on list with id=135143996>]
>>>
همچنین ملاحظه نمائید
- PEP 217 - قلاب نمایش برای استفادهی تعاملی
نوشته و پیادهسازیشده توسط موشه زادکا.
PEP 208: مدل جدید تبدیل ضمنی نوع¶
نحوهی انجام تبدیل ضمنی نوعهای عددی در سطح C بهطور قابل توجهی تغییر کرد. این تنها نویسندگان توسعههای C برای پایتون را تحت تأثیر قرار میدهد و به آنها انعطاف بیشتری در نوشتن نوعهای توسعهای که از عملیات عددی پشتیبانی میکنند میدهد.
نوعهای توسعهای اکنون میتوانند پرچم نوع Py_TPFLAGS_CHECKTYPES را در ساختار PyTypeObject خود تنظیم کنند تا نشان دهند که از مدل جدید تبدیل ضمنی نوع پشتیبانی میکنند. در اینگونه نوعهای توسعهای، توابع جایگاه عددی دیگر نمیتوانند فرض کنند که دو آرگومان از نوع یکسان به آنها پاس داده میشود؛ در عوض، ممکن است دو آرگومان از نوعهای متفاوت به آنها پاس داده شود و آنگاه میتوانند تبدیل ضمنی نوع داخلی خود را انجام دهند. اگر به تابع جایگاه نوعی پاس داده شود که نتواند آن را مدیریت کند، میتواند شکست را با بازگرداندن ارجاعی به مقدار تکنمونه Py_NotImplemented نشان دهد. سپس توابع عددی نوع دیگر امتحان میشوند و شاید بتوانند عملیات را مدیریت کنند؛ اگر نوع دیگر نیز Py_NotImplemented برگرداند، استثنای TypeError بهوجود خواهد آمد. متدهای عددی نوشتهشده در پایتون نیز میتوانند Py_NotImplemented را برگردانند که باعث میشود مفسر طوری رفتار کند که گویی متد وجود ندارد (شاید استثنای TypeError بهوجود آورد، شاید متدهای عددی شیء دیگر را امتحان کند).
همچنین ملاحظه نمائید
- PEP 208 - بازکاری مدل تبدیل ضمنی نوع
نوشته و پیادهسازیشده توسط Neil Schemenauer، و بهطور گسترده بر پایهی کارهای پیشین Marc-André Lemburg. این را بخوانید تا نکات ظریف اینکه عملیاتهای عددی از این پس چگونه در سطح C پردازش خواهند شد را درک کنید.
PEP 241: فراداده در بستههای پایتون¶
یکی از شکایات رایج کاربران پایتون این است که هیچ کاتالوگ واحدی از تمام ماژولهای موجود پایتون وجود ندارد. Vaults of Parnassus متعلق به T. Middleton در آدرس www.vex.net/parnassus/ (که در فوریه ۲۰۰۹ تعطیل شد و در Internet Archive Wayback Machine موجود است) بزرگترین کاتالوگ ماژولهای پایتون بود، اما ثبت نرمافزار در Vaults اختیاری است و بسیاری از افراد زحمت این کار را به خودشان نمیدادند.
بهعنوان نخستین گام کوچک در مسیر حل این مشکل، نرمافزارهای پایتونی که با دستور sdist در Distutils بستهبندی میشوند، پروندهای با نام PKG-INFO در بر خواهند داشت که حاوی اطلاعاتی دربارهی بسته مانند نام، نسخه و نویسندهی آن است (فراداده، در اصطلاح کاتالوگنویسی). PEP 241 فهرست کامل فیلدهایی را که میتوانند در پروندهی PKG-INFO وجود داشته باشند، در بر میگیرد. همزمان با آنکه مردم بستهبندی نرمافزارهای خود را با پایتون 2.1 آغاز کردند، شمار فزایندهای از بستهها فراداده در بر خواهند داشت، که این امر ساخت سامانههای کاتالوگنویسی خودکار و آزمایش آنها را ممکن میسازد. با تجربهی حاصل، شاید بتوان یک کاتالوگ واقعاً خوب طراحی کرد و سپس پشتیبانی از آن را در پایتون 2.2 بگنجاند. برای مثال، دستورهای sdist و bdist_* در Distutils میتوانند از گزینهی upload پشتیبانی کنند که بستهی شما را بهطور خودکار به یک سرور کاتالوگ بارگذاری کند.
شما حتی اگر از Python 2.1 استفاده نمیکنید، میتوانید ساخت بستههای حاوی PKG-INFO را آغاز کنید، زیرا نسخهی جدیدی از Distutils برای کاربران نسخههای پیشین پایتون ارائه خواهد شد. نسخهی 1.0.2 از Distutils شامل تغییرات توصیفشده در PEP 241 و همچنین رفع اشکالها و بهبودهای گوناگون است. این نسخه از طریق گروه علاقهمندی ویژهی Distutils (SIG) در نشانی https://www.python.org/community/sigs/current/distutils-sig/ دسترسپذیر خواهد بود.
ماژولهای جدید و بهبودیافته¶
کا-پینگ یی دو ماژول جدید ارائه کرد:
inspect.py، ماژولی برای دریافت اطلاعات دربارهی کد زندهی پایتون، وpydoc.py، ماژولی برای تبدیل تعاملی رشتههای مستند به HTML یا متن. نکتهی دیگر اینکهTools/scripts/pydocکه اکنون بهطور خودکار نصب میشود، ازpydoc.pyبرای نمایش مستندات بر اساس نام یک ماژول، بسته یا کلاس پایتون استفاده میکند. برای مثال،pydoc xml.domموارد زیر را نمایش میدهد:Python Library Documentation: package xml.dom in xml NAME xml.dom - W3C Document Object Model implementation for Python. FILE /usr/local/lib/python2.1/xml/dom/__init__.pyc DESCRIPTION The Python mapping of the Document Object Model is documented in the Python Library Reference in the section on the xml.dom package. This package contains the following modules: ...
pydocهمچنین شامل یک مرورگر راهنمای تعاملی مبتنی بر Tk است.pydocبهسرعت اعتیادآور میشود؛ آن را امتحان کنید!دو ماژول مختلف برای آزمون واحد به کتابخانه استاندارد اضافه شدند. ماژول
doctestکه توسط Tim Peters ارائهشده است، چارچوبی برای آزمون فراهم میکند که مبتنی بر اجرای مثالهای تعبیهشده در رشتههای مستند و مقایسهی نتایج با خروجی مورد انتظار است. PyUnit که توسط Steve Purcell ارائهشده است، چارچوبی برای آزمون واحد است که از JUnit الهام گرفته است. JUnit نیز به نوبه خود اقتباسی از چارچوب آزمون Smalltalk ساختهی Kent Beck بود. برای اطلاعات بیشتر دربارهی PyUnit به https://pyunit.sourceforge.net/ مراجعه کنید.ماژول
difflibحاوی کلاسی به نامSequenceMatcherاست که دو دنباله را مقایسه میکند و تغییرات لازم برای تبدیل یک دنباله به دنبالهی دیگر را محاسبه میکند. برای مثال، میتوان از این ماژول برای نوشتن ابزاری مشابه برنامهی diff یونیکس استفاده کرد و در واقع، برنامهی نمونهTools/scripts/ndiff.pyنشان میدهد که چگونه چنین اسکریپتی نوشته شود.curses.panel، دربرگیرندهای برای کتابخانهی panel که بخشی از ncurses و SYSV curses است، توسط Thomas Gellekum ارائه شده است. کتابخانهی panel پنجرههایی با قابلیت اضافیِ عمق فراهم میکند. پنجرهها را میتوان در ترتیب عمق، بالاتر یا پایینتر جابهجا کرد و کتابخانهی panel تشخیص میدهد که پنلها کجا همپوشانی دارند و کدام بخشها مرئی هستند.بستهی PyXML از زمان پایتون 2.0 چندین نسخه را پشت سر گذاشته است و پایتون 2.1 شامل نسخهی بهروزرسانیشدهای از بستهی
xmlاست. در میان تغییرات قابل توجه میتوان به پشتیبانی از Expat 1.2 و نسخههای بعدی، توانایی پارسرهای Expat در مدیریت پروندهها با هر کدگذاری که پایتون از آن پشتیبانی میکند، و رفع اشکالهای گوناگون در SAX، DOM و ماژولminidomاشاره کرد.پینگ همچنین قلاب دیگری برای مدیریت استثناهای گرفتهنشده ارائه کرد.
sys.excepthook()را میتوان روی یک شیء فراخوانیپذیر تنظیم کرد. وقتی استثنایی توسط هیچیک از بلوکهایtry...exceptگرفته نشود، آن استثنا بهsys.excepthook()ارسال میشود که آنگاه میتواند هر کاری که بخواهد انجام دهد. در نهمین کنفرانس پایتون، پینگ کاربردی برای این قلاب را به نمایش گذاشت: چاپ یک ردگیری توسعهیافته که نهتنها فریمهای پشته را فهرست میکند، بلکه آرگومانهای تابع و متغیرهای محلی هر فریم را نیز فهرست میکند.توابع مختلفی در ماژول
time، مانندasctime()وlocaltime()، به آرگومانی ممیز شناور نیاز دارند که زمان بر حسب ثانیه از مبدأ زمان را در بر داشته باشد. رایجترین کاربرد این توابع، کار با زمان جاری است، بنابراین آرگومان ممیز شناور اختیاری شده است؛ وقتی مقداری ارائه نشود، از زمان جاری استفاده خواهد شد. برای مثال، ورودیهای پرونده گزارش معمولاً به رشتهای شامل زمان جاری نیاز دارند؛ در پایتون 2.1 میتوان ازtime.asctime()استفاده کرد، به جای عبارت طولانیترtime.asctime(time.localtime(time.time()))که پیشتر لازم بود.این تغییر توسط Thomas Wouters پیشنهاد و پیادهسازی شد.
ماژول
ftplibاکنون بهطور پیشفرض پروندهها را در حالت منفعل بازیابی میکند، زیرا حالت منفعل به احتمال بیشتری از پشت فایروال کار میکند. این درخواست از سامانه پیگیری باگ دبیان مطرح شده است، چرا که بستههای دیگر دبیان ازftplibبرای بازیابی پروندهها استفاده میکنند و سپس از پشت فایروال کار نمیکنند. بعید دانسته میشود که این امر برای کسی مشکل ایجاد کند، زیرا Netscape بهطور پیشفرض از حالت منفعل استفاده میکند و کمتر کسی شکایت میکند، اما اگر حالت منفعل برای برنامه یا تنظیمات شبکهی شما مناسب نباشد، برای غیرفعال کردن حالت منفعل،set_pasv(0)را روی اشیاء FTP فراخوانی کنید.پشتیبانی از دسترسی به سوکت خام، که توسط گرنت ادواردز ارائه شده، به ماژول
socketاضافه شده است.ماژول
pstatsاکنون شامل یک مرورگر آمار تعاملی ساده برای نمایش پروفایلهای زمانسنجی برنامههای پایتون است که هنگام اجرای ماژول بهعنوان اسکریپت فراخوانی میشود. مشارکتشده توسط Eric S. Raymond.تابع جدیدی وابسته به پیادهسازی،
sys._getframe([depth])، افزوده شده است تا شیء فریم مشخصی را از پشته فراخوانی فعلی برگرداند.sys._getframe()فریم بالای پشته فراخوانی را برمیگرداند؛ اگر آرگومان اختیاری عدد صحیح depth ارائه شود، این تابع فریمی را برمیگرداند که depth فراخوانی پایینتر از بالای پشته قرار دارد. برای مثال،sys._getframe(1)شیء فریم فراخوانکننده را برمیگرداند.این تابع فقط در سیپایتون وجود دارد، نه در Jython یا پیادهسازی .NET. از آن برای اشکالزدایی استفاده کنید و در برابر وسوسهی قرار دادن آن در کد تولیدی مقاومت کنید.
تغییرات و اصلاحات دیگر¶
به دلیل کوتاهتر بودن چرخه انتشار، تغییرات کوچک نسبتاً کمی در پایتون 2.1 انجام شد. جستوجویی در گزارشهای تغییرات CVS نشان میدهد که ۱۱۷ وصله اعمال شده و ۱۳۶ اشکال رفع شده است؛ هر دو رقم احتمالاً دستکم گرفته شدهاند. برخی از تغییرات قابلتوجهتر عبارتاند از:
اکنون یک تخصیصدهندهی تخصصی برای اشیاء بهصورت اختیاری در دسترس است که باید سریعتر از
malloc()سیستم باشد و سربار حافظه کمتری داشته باشد. این تخصیصدهنده از تابعmalloc()زبان C برای بهدستآوردن استخرهای بزرگ حافظه استفاده میکند و سپس درخواستهای کوچکتر حافظه را از این استخرها برآورده میکند. میتوان آن را با ارائهی گزینهی--with-pymallocبه اسکریپت configure فعال کرد؛ برای جزئیات پیادهسازی بهObjects/obmalloc.cمراجعه کنید.نویسندگان ماژولهای توسعهای C باید کد خود را با فعال بودن تخصیصدهنده شیء (object allocator) آزمایش کنند، زیرا ممکن است برخی کدهای نادرست از کار بیفتند و در زمان اجرا موجب برونریزی هسته شوند. در API زبان C پایتون تعدادی تابع تخصیص حافظه وجود دارد که تا پیش از این صرفاً نامهای مستعاری برای
malloc()وfree()کتابخانه C بودهاند؛ به این معنا که اگر بهاشتباه توابع ناسازگاری را فراخوانی میکردید، خطا به چشم نمیآمد. وقتی تخصیصدهنده شیء فعال باشد، این توابع دیگر نامهای مستعاری برایmalloc()وfree()نیستند و فراخوانی تابع اشتباه برای آزاد کردن حافظه، شما را با یک برونریزی هسته روبهرو خواهد کرد. برای نمونه، اگر حافظه با استفاده ازPyMem_Newتخصیص یافته باشد، باید باPyMem_Del()آزاد شود، نه باfree(). چند ماژول از ماژولهای همراه پایتون گرفتار این موضوع شدند و باید اصلاح میشدند؛ بیتردید ماژولهای شخص ثالث بیشتری نیز هستند که همین مشکل را خواهند داشت.تخصیصدهنده شیء توسط ولادیمیر مارانگوزوف ارائه شده است.
سرعت ورودی/خروجی سطرمحور پروندهها بهبود یافته است، زیرا افراد اغلب از کندی آن شکایت دارند و اغلب بهعنوان بنچمارکی ساده از آن استفاده شده است. بنابراین متد
readline()شیءهای پرونده بازنویسی شده تا بسیار سریعتر باشد. میزان دقیق این افزایش سرعت از پلتفرمی به پلتفرم دیگر متفاوت خواهد بود و به میزان کند بودنgetc()کتابخانه C بستگی دارد، اما حدود ۶۶ درصد است و بهطور بالقوه در برخی سیستمعاملهای خاص بسیار بیشتر خواهد بود. Tim Peters که از بحثی در comp.lang.python انگیزه گرفته بود، بخش زیادی از بنچمارکگیری و کدنویسی این تغییر را انجام داد.یک ماژول و متد جدید برای اشیاء پرونده نیز اضافه شد که توسط Jeff Epler ارائه شده است. متد جدید،
xreadlines()، مشابه توکار موجودxrange()است.xreadlines()یک شیء دنبالهی مات برمیگرداند که تنها از پیمایششدن پشتیبانی میکند و در هر پیمایش یک سطر میخواند، اما برخلاف متد موجودreadlines()، کل پرونده را در حافظه نمیخواند. شما آن را به این شکل استفاده میکنید:for line in sys.stdin.xreadlines(): # ... do something for each line ... ...
برای بحث کاملتر دربارهی تغییرات ورودی/خروجی سطر، خلاصهی python-dev مربوط به ۱ تا ۱۵ ژانویه ۲۰۰۱ را در https://mail.python.org/pipermail/python-dev/2001-January/ ببینید.
متد جدیدی،
popitem()، به دیکشنریها اضافه شد تا امکان پیمایش مخرب در محتویات یک دیکشنری را فراهم کند؛ این کار میتواند برای دیکشنریهای بزرگ سریعتر باشد، زیرا نیازی به ساخت فهرستی شامل همهی کلیدها یا مقادیر نیست.D.popitem()یک جفت تصادفی(key, value)را از دیکشنریDحذف میکند و آن را بهصورت یک تاپل دوتایی برمیگرداند. این متد عمدتاً توسط Tim Peters و Guido van Rossum، پس از پیشنهاد و وصل اولیه از سوی Moshe Zadka پیادهسازی شد.ماژولها اکنون میتوانند با تعریف یک ویژگی
__all__حاوی فهرستی از نامهایی که ایمپورت خواهند شد، کنترل کنند که هنگام استفاده ازfrom module import *کدام نامها ایمپورت شوند. یک شکایت رایج این است که اگر ماژول، ماژولهای دیگری مانندsysیاstringرا ایمپورت کند،from module import *آنها را به فضای نام ماژول ایمپورتکننده اضافه میکند. برای رفع این مشکل، بهسادگی نامهای عمومی را در__all__فهرست کنید:# List public names __all__ = ['Database', 'open']
نسخهی سختگیرانهتری از این وصل نخست توسط Ben Wolfson پیشنهاد و پیادهسازی شد، اما پس از بحثهایی در python-dev، نسخهی نهاییِ ضعیفتری ثبت شد.
اعمال
repr()بر رشتهها پیشتر برای نویسههای چاپناپذیر از دنبالههای خنثیسازی مبنای هشت استفاده میکرد؛ برای مثال، نویسه سطر جدید به شکل'\012'بود. این اثری بازمانده از تبار C پایتون بود، اما امروزه مبنای هشت کاربرد عملی بسیار کمی دارد. Ka-Ping Yee پیشنهاد کرد که بهجای دنبالههای خنثیسازی مبنای هشت، از دنبالههای گریز مبنای شانزده استفاده شود و برای نویسههای مربوطه از دنبالههای خنثیسازی\n،\tو\rاستفاده شود، و این قالببندی جدید را پیادهسازی کرد.خطاهای نحوی که در زمان کامپایل تشخیص داده میشوند، اکنون میتوانند استثناهایی حاوی نام پرونده و شماره سطر خطا ایجاد کنند؛ اثری جانبی خوشایند از بازسازماندهی کامپایلر انجامشده توسط Jeremy Hylton.
افزونههای C که ماژولهای دیگر را ایمپورت میکنند، تغییر کردهاند تا از
PyImport_ImportModule()استفاده کنند، که این بدان معناست که از هر قلاب ایمپورتی که نصب شده باشد استفاده خواهند کرد. این کار برای افزونههای شخص ثالثی که نیاز به ایمپورت کردن ماژول دیگری از کد C دارند نیز توصیه میشود.اندازهی پایگاه دادهی نویسههای یونیکد به لطف فردریک لوند ۳۴۰ کیلوبایت دیگر کاهش یافت.
چند پورت جدید ارائه شد: MacOS X (توسط Steven Majewski)، Cygwin (توسط Jason Tishler)؛ RISCOS (توسط Dietmar Schwertberger)؛ Unixware 7 (توسط Billy G. Allie).
و همچنین فهرست متداول رفع اشکالات جزئی، نشتهای حافظهی کوچک، ویرایشهای رشتههای مستند و سایر تغییرات ریز نیز وجود دارد که بهدلیل طولانی بودن، ذکر تکتک آنها نمیارزد؛ اگر میخواهید، برای جزئیات کامل به گزارشهای CVS مراجعه کنید.
قدردانیها¶
نویسنده مایل است از افراد زیر برای ارائهی پیشنهادها در پیشنویسهای مختلف این مقاله تشکر کند: Graeme Cross، David Goodger، Jay Graves، Michael Hudson، Marc-André Lemburg، Fredrik Lundh، Neil Schemenauer، Thomas Wouters.