GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing python.github.io — پرسشهای متداول دربارهی طراحی و تاریخچه پرسشهای متداول دربارهی طراحی و تاریخچه¶چرا پایتون از تورفتگی برای گروهبندی دستورها استفاده میکند؟¶گیدو ون روسوم معتقد است که استفاده از تورفتگی برای گروهبندی بسیار ظریف است و سهم زیادی در وضوح برنامههای معمول پایتون دارد. بسیاری از افراد پس از مدتی به این ویژگی علاقهمند میشوند. از آنجا که هیچ براکت آغاز/پایانی وجود ندارد، هیچ ناهماهنگیای میان گروهبندی از دید پارسر و خوانندهی انسانی وجود نخواهد داشت. گاهی برنامهنویسان C با قطعهکدی مانند این مواجه میشوند: if (x <= y) x++; y--; z++; در صورت برقرار بودن شرط، تنها دستور چون براکتهای آغاز/پایان وجود ندارند، پایتون بسیار کمتر در معرض تعارضهای سبک کدنویسی است. در C روشهای مختلفی برای قرار دادن آکولادها وجود دارد. پس از آنکه به خواندن و نوشتن کد با یک سبک خاص عادت کردید، طبیعی است که هنگام خواندن (یا ملزم بودن به نوشتن) با سبکی متفاوت، تا حدی احساس ناراحتی کنید. سبکهای کدنویسی بسیاری، براکتهای begin/end را در یک خط جداگانه قرار میدهند. این کار برنامهها را بهطور قابلتوجهی طولانیتر میکند و فضای ارزشمند صفحه را هدر میدهد و در نتیجه داشتن دید کلی خوب از برنامه را دشوارتر میسازد. در حالت ایدهآل، یک تابع باید در یک صفحه جا شود (مثلاً ۲۰ تا ۳۰ خط). ۲۰ خط پایتون میتواند کار بسیار بیشتری نسبت به ۲۰ خط C انجام دهد. این موضوع تنها به دلیل نبود براکتهای begin/end نیست — نبود اعلانها و انواع داده سطح بالا نیز در آن نقش دارند — اما سینتکس مبتنی بر تورفتگی قطعاً کمک میکند. چرا هنگام انجام عملیات حسابی ساده، نتایج عجیبی دریافت میکنم؟¶پرسش بعدی را ببینید. چرا محاسبات ممیز شناور اینقدر نادقیق هستند؟¶کاربران اغلب از نتایجی مانند این شگفتزده میشوند: >>> 1.2 - 1.0 0.19999999999999996 و فکر میکنند که این یک باگ در پایتون است. اینطور نیست. این موضوع ارتباط کمی با پایتون دارد و ارتباط بسیار بیشتری با نحوهی مدیریت اعداد ممیز شناور توسط پلتفرم زیرین دارد. نوع بسیاری از اعدادی که بهراحتی میتوان آنها را در نماد دهدهی نوشت، نمیتوانند دقیقاً در قالب ممیز شناور دودویی بیان شوند. برای مثال، پس از: >>> x = 1.2 مقدار ذخیرهشده برای 1.0011001100110011001100110011001100110011001100110011 (دودویی) که دقیقاً بهصورت زیر است: 1.1999999999999999555910790149937383830547332763671875 (دهدهی) دقت معمول ۵۳ بیتی، برای اعداد اعشاری پایتون ۱۵ تا ۱۶ رقم اعشاری دقت فراهم میکند. برای توضیح کاملتر، لطفاً فصل حساب ممیز شناور در آموزش پایتون را ببینید. چرا رشتههای پایتون تغییرناپذیر هستند؟¶چندین مزیت وجود دارد. یکی از آنها کارایی است: دانستن اینکه یک رشته تغییرناپذیر است به این معناست که میتوانیم فضای آن را در زمان ایجاد تخصیص دهیم، و نیازهای ذخیرهسازی ثابت و بدون تغییر هستند. این نیز یکی از دلایل تمایز بین تاپلها و فهرستها است. مزیت دیگر این است که رشتهها در پایتون به همان اندازهی اعداد «بنیادی» محسوب میشوند. هیچ میزان فعالیتی مقدار ۸ را به چیز دیگری تغییر نخواهد داد، و در پایتون، هیچ میزان فعالیتی رشتهی "eight" را به چیز دیگری تغییر نخواهد داد. چرا باید از 'self' بهصراحت در تعاریف و فراخوانیهای متد استفاده شود؟¶این ایده از Modula-3 اقتباس شده است. به دلایل گوناگونی، بسیار مفید است. اول، آشکارتر است که شما بهجای یک متغیر محلی از یک متد یا ویژگی نمونه استفاده میکنید. خواندن دوم، این بدان معناست که اگر بخواهید بهصراحت به متدی از یک کلاس خاص ارجاع دهید یا آن را فراخوانی کنید، نیازی به سینتکس خاصی نیست. در C++، اگر بخواهید از متدی از کلاس پایه استفاده کنید که در یک کلاس مشتقشده بازنویسی شده است، باید از عملگر در نهایت، برای متغیرهای نمونه، این موضوع یک مشکل نحوی در انتساب را حل میکند: از آنجا که متغیرهای محلی در پایتون (طبق تعریف!) آن متغیرهایی هستند که مقداری در بدنه یک تابع به آنها انتساب داده میشود (و بهصراحت سراسری اعلام نشدهاند)، باید راهی وجود داشته باشد تا به مفسر بگوییم که منظور از یک انتساب، انتساب به یک متغیر نمونه است نه به یک متغیر محلی، و ترجیحاً باید نحوی باشد (به دلایل کارایی). C++ این کار را از طریق اعلانها انجام میدهد، اما پایتون اعلان ندارد و حیف است که فقط برای این هدف مجبور شویم آنها را معرفی کنیم. استفاده صریح از چرا نمیتوانم در یک عبارت از انتساب استفاده کنم؟¶از پایتون 3.8 به بعد، میتوانید! عبارات انتسابی که از عملگر والروس (walrus operator) while chunk := fp.read(200): print(chunk) برای اطلاعات بیشتر، PEP 572 را ببینید. چرا پایتون برای برخی قابلیتها از متدها استفاده میکند (مثلاً list.index()) اما برای برخی دیگر از توابع (مثلاً len(list))؟¶همانطور که گایدو گفت:
چرا join() یک متد رشته است، نه یک متد فهرست یا تاپل؟¶رشتهها از پایتون 1.6 بسیار شبیهتر به سایر انواع استاندارد شدند، زمانی که متدهایی افزوده شدند که همان عملکردی را ارائه میدهند که همواره از طریق توابع ماژول string در دسترس بوده است. بیشتر این متدهای جدید بهطور گسترده پذیرفته شدهاند، اما آن متدی که به نظر میرسد باعث ناراحتی برخی برنامهنویسان میشود، این است: ", ".join(['1', '2', '4', '8', '16']) که نتیجه زیر را میدهد: 1, 2, 4, 8, 16 دو آرگومان رایج در مخالفت با این کاربرد وجود دارد. مورد اول اینگونه است: «استفاده از یک متدِ رشتهی لفظی (ثابت رشتهای) واقعاً زشت به نظر میرسد»، پاسخ این است که شاید چنین باشد، اما یک رشتهی لفظی صرفاً یک مقدار ثابت است. اگر متدها روی نامهای مقید به رشتهها مجاز باشند، هیچ دلیل منطقی برای در دسترس نبودن آنها روی رشتههای لفظی وجود ندارد. اعتراض دوم معمولاً به این صورت بیان میشود: «من در واقع به یک دنباله میگویم که اعضای خود را با یک ثابت رشتهای به هم بپیوندد». متأسفانه، شما این کار را نمیکنید. به دلایلی، داشتن "1, 2, 4, 8, 16".split(", ") دستوری به یک رشتهی لفظی برای بازگرداندن زیررشتههایی است که با جداکنندهی دادهشده جدا شدهاند (یا بهطور پیشفرض، دنبالههای دلخواه فضای خالی).
استثناها چقدر سریع هستند؟¶یک بلوک try: value = mydict[key] except KeyError: mydict[key] = getvalue(key) value = mydict[key] این تنها زمانی منطقی بود که انتظار داشتید دیکشنری تقریباً همیشه کلید را داشته باشد. اگر اینطور نبود، آن را اینگونه کدنویسی میکردید: if key in mydict: value = mydict[key] else: value = mydict[key] = getvalue(key) برای این مورد خاص، میتوانید از چرا در پایتون دستور switch یا case وجود ندارد؟¶بهطور کلی، دستورهای switch ساختاریافته یک بلوک کد را هنگامی اجرا میکنند که یک عبارت دارای یک مقدار خاص یا مجموعهای از مقادیر باشد. از پایتون 3.10، میتوانید بهراحتی مقادیر لفظی یا ثابتهای درون یک فضای نام را با دستور برای مواردی که نیاز دارید از میان تعداد بسیار زیادی از حالتهای ممکن انتخاب کنید، میتوانید یک دیکشنری برای نگاشت مقادیر حالت به توابعی که باید فراخوانی شوند ایجاد کنید. برای مثال: functions = {'a': function_1, 'b': function_2, 'c': self.method_1} func = functions[value] func() برای فراخوانی متدها روی اشیاء، میتوانید این کار را با استفاده از تابع توکار class MyVisitor: def visit_a(self): ... def dispatch(self, value): method_name = 'visit_' + str(value) method = getattr(self, method_name) method() پیشنهاد میشود از یک پیشوند برای نام متدها استفاده کنید، مانند تقلید switch با fallthrough، مانند switch-case-default در C، امکانپذیر است، بسیار دشوارتر است و کمتر مورد نیاز است. آیا نمیتوانید به جای تکیه بر یک پیادهسازی نخ مختص سیستمعامل، نخها را در مفسر شبیهسازی کنید؟¶پاسخ ۱: متأسفانه، مفسر برای هر فریم پشتهی پایتون، حداقل یک فریم پشتهی C را روی پشته قرار میدهد. همچنین، افزونهها میتوانند در لحظاتی تقریباً تصادفی فراخوانی بازگشتی به پایتون داشته باشند. بنابراین، یک پیادهسازی کامل نخها به پشتیبانی از نخ برای C نیاز دارد. پاسخ ۲: خوشبختانه، Stackless Python وجود دارد که حلقه مفسر آن بهطور کامل بازطراحی شده است و از پشتهی C اجتناب میکند. چرا عبارتهای لامبدا نمیتوانند شامل دستورها باشند؟¶عبارتهای lambda پایتون نمیتوانند شامل دستور باشند، زیرا چارچوب نحوی پایتون نمیتواند دستورهای تودرتو درون عبارتها را مدیریت کند. با این حال، در پایتون، این مشکل جدیای نیست. برخلاف فرمهای lambda در زبانهای دیگر، که قابلیتهایی اضافه میکنند، lambdaهای پایتون تنها یک نمادگذاری خلاصه هستند، اگر حوصلهی تعریف یک تابع را نداشته باشید. توابع در پایتون از پیش اشیای درجهیک هستند و میتوانند در یک محدوده محلی تعریف شوند. بنابراین تنها مزیت استفاده از لامبدا به جای یک تابع تعریفشده بهصورت محلی این است که نیازی نیست برای تابع نامی ابداع کنید -- اما آن فقط یک متغیر محلی است که شیء تابع (که دقیقاً همان نوع شیءای است که یک عبارت لامبدا برمیگرداند) به آن انتساب داده میشود! آیا پایتون میتواند به کد ماشین، C یا زبان دیگری کامپایل شود؟¶Cython نسخهای اصلاحشده از پایتون را با حاشیهنویسیهای اختیاری به افزونههای C کامپایل میکند. Nuitka یک کامپایلر نوظهور برای کامپایل پایتون به کد C++ است که هدف آن پشتیبانی از کل زبان پایتون است. پایتون چگونه حافظه را مدیریت میکند؟¶جزئیات مدیریت حافظه پایتون به پیادهسازی بستگی دارد. پیادهسازی استاندارد پایتون، CPython، از شمارش ارجاع برای تشخیص اشیای دسترسناپذیر و از سازوکار دیگری برای جمعآوری چرخههای ارجاع استفاده میکند و بهصورت دورهای یک الگوریتم تشخیص چرخه را اجرا میکند که چرخههای دسترسناپذیر را جستجو میکند و اشیای درگیر را حذف میکند. ماژول با این حال، سایر پیادهسازیها (مانند Jython یا PyPy) میتوانند به مکانیزم متفاوتی مانند یک زبالهرو (garbage collector) کامل متکی باشند. این تفاوت میتواند در صورتی که کد پایتون شما به رفتار پیادهسازی شمارش ارجاع وابسته باشد، باعث برخی مشکلات ظریف در انتقال شود. در برخی پیادهسازیهای پایتون، کد زیر (که در CPython مشکلی ندارد) احتمالاً با اتمام توصیفگرهای پرونده مواجه میشود: for file in very_long_list_of_files: f = open(file) c = f.read(1) در واقع، با استفاده از طرحواره شمارش ارجاع و تخریبکنندهی CPython، هر انتساب جدید به اگر میخواهید کدی بنویسید که با هر پیادهسازی پایتون کار کند، باید پرونده را بهطور صریح ببندید یا از دستور for file in very_long_list_of_files: with open(file) as f: c = f.read(1) چرا CPython از یک روش زبالهروبی سنتیتر استفاده نمیکند؟¶برای نمونه، این یک ویژگی استاندارد C نیست و بنابراین قابلحمل نیست. (بله، ما در مورد کتابخانه Boehm GC میدانیم. این کتابخانه بخشهایی از کد اسمبلر را برای بیشتر سکوهای رایج دارد، نه برای همهی آنها، و اگرچه عمدتاً شفاف است، کاملاً شفاف نیست؛ برای اینکه پایتون بتواند با آن کار کند، به وصلهها نیاز است.) زبالهروبی سنتی نیز هنگامی که پایتون در برنامههای دیگر تعبیه میشود، به یک مشکل تبدیل میشود. در حالی که در یک پایتون مستقل، جایگزین کردن چرا هنگام خروج CPython، تمام حافظه آزاد نمیشود؟¶اشیایی که از فضای نام های سراسری ماژولهای پایتون به آنها ارجاع داده شدهاند، همیشه هنگام خروج پایتون آزاد نمیشوند. ممکن است این اتفاق در صورت وجود ارجاعهای چرخهای رخ دهد. همچنین بخشهایی از حافظه وجود دارند که توسط کتابخانه C تخصیص داده شدهاند و آزاد کردن آنها غیرممکن است (برای مثال، ابزاری مانند Purify دربارهی این موارد شکایت خواهد کرد). با این حال، پایتون در پاکسازی حافظه هنگام خروج بسیار جدی است و واقعاً تلاش میکند تکتک اشیاء را نابود کند. اگر میخواهید پایتون را وادار به حذف موارد مشخصی در زمان آزادسازی حافظه کنید، از ماژول چرا انواع دادهی جداگانهای برای تاپل و فهرست وجود دارند؟¶فهرستها و تاپلها، با وجود شباهتهای زیاد، معمولاً بهطور بنیادین به شیوههای متفاوتی استفاده میشوند. میتوان تاپلها را مشابه از سوی دیگر، فهرستها بیشتر به آرایهها در زبانهای دیگر شبیهاند. آنها معمولاً تعداد متغیری از شیءها را نگه میدارند که همگی نوع یکسانی دارند و یکییکی روی آنها عمل میشود. برای مثال، تاپلها تغییرناپذیر هستند، به این معنا که پس از ایجاد یک تاپل، نمیتوانید هیچیک از عناصر آن را با مقدار جدیدی جایگزین کنید. فهرستها تغییرپذیر هستند، یعنی همیشه میتوانید عناصر یک فهرست را تغییر دهید. فقط اشیاء هشپذیر میتوانند به عنوان کلیدهای دیکشنری استفاده شوند. بیشتر انواع تغییرناپذیر هشپذیر هستند، و به همین دلیل است که تاپلها (اما نه فهرستها) میتوانند به عنوان کلید استفاده شوند. با این حال، توجه داشته باشید که یک تاپل تنها زمانی هشپذیر است که تمام عناصر آن هشپذیر باشند. فهرستها در CPython چگونه پیادهسازی شدهاند؟¶فهرستهای CPython در واقع آرایههایی با طول متغیر هستند، نه فهرستهای پیوندی بهسبک Lisp. پیادهسازی از آرایهای پیوسته از ارجاعها به اشیاء دیگر استفاده میکند و یک اشارهگر به این آرایه و طول آرایه را در یک ساختار سر فهرست نگه میدارد. این باعث میشود که اندیسدهی به یک فهرست هنگامی که آیتمها افزوده یا درج میشوند، اندازهی آرایهی ارجاعها تغییر میکند. تمهیداتی به کار گرفته شده است تا عملکرد افزودن مکرر آیتمها بهبود یابد؛ هنگامی که آرایه باید بزرگ شود، مقداری فضای اضافی تخصیص داده میشود تا چند بار بعدی نیازی به تغییر اندازهی واقعی نباشد. برای هزینههای عملیاتهای مختلف فهرست، به پیچیدگی زمانی عملیاتها روی انواع توکار مراجعه کنید. دیکشنریها در CPython چگونه پیادهسازی شدهاند؟¶دیکشنریهای CPython بهصورت جدولهای هش با قابلیت تغییر اندازه پیادهسازی شدهاند. در مقایسه با درختهای B، این روش در بیشتر شرایط عملکرد بهتری برای جستجو (رایجترین عملیات با اختلاف زیاد) ارائه میدهد و پیادهسازی سادهتری دارد. دیکشنریها با محاسبهی کد هش (hash code) برای هر کلید ذخیرهشده در دیکشنری، از طریق تابع توکار برای هزینههای عملیاتهای مختلف دیکشنری، به پیچیدگی زمانی عملیاتها روی انواع توکار مراجعه کنید. چرا کلیدهای دیکشنری باید تغییرناپذیر باشند؟¶پیادهسازی جدول هش دیکشنریها از یک مقدار هش محاسبهشده از مقدار کلید برای پیدا کردن کلید استفاده میکند. اگر کلید یک شیء تغییرپذیر باشد، ممکن است مقدار آن تغییر کند و در نتیجه هش آن نیز ممکن است تغییر کند. اما از آنجا که هرکسی که شیء کلید را تغییر میدهد نمیتواند تشخیص دهد که از آن بهعنوان کلید دیکشنری استفاده میشده است، نمیتواند آیتم را در دیکشنری جابهجا کند. سپس، وقتی سعی کنید همان شیء را در دیکشنری جستجو کنید، پیدا نخواهد شد، زیرا مقدار هش آن متفاوت است. اگر سعی کنید مقدار قدیمی را جستجو کنید، آن هم پیدا نخواهد شد، زیرا مقدار شیء یافتشده در آن سطل هش (hash bin) متفاوت خواهد بود. اگر دیکشنریای میخواهید که با فهرست اندیسدهی شده باشد، کافی است ابتدا فهرست را به تاپل تبدیل کنید؛ تابع برخی راهحلهای غیرقابلقبول که پیشنهاد شدهاند:
ترفندی برای دور زدن این موضوع وجود دارد که در صورت نیاز میتوانید از آن استفاده کنید، اما با مسئولیت خودتان: میتوانید یک ساختار تغییرپذیر را درون یک نمونه کلاس بپیچید که هر دو متد class ListWrapper: def __init__(self, the_list): self.the_list = the_list def __eq__(self, other): return self.the_list == other.the_list def __hash__(self): l = self.the_list result = 98767 - len(l)*555 for i, el in enumerate(l): try: result = result + (hash(el) % 9999999) * 1001 + i except Exception: result = (result % 7777777) + i * 333 return result توجه داشته باشید که محاسبهی هش به دلیل احتمال هشناپذیر بودن برخی اعضای فهرست و نیز احتمال سرریز محاسباتی، پیچیده است. علاوه بر این، همیشه باید اگر در مورد چرا list.sort() فهرست مرتبشده را برنمیگرداند؟¶در موقعیتهایی که کارایی اهمیت دارد، ساختن یک کپی از فهرست صرفاً برای مرتبسازی آن، اتلاف منابع خواهد بود. بنابراین، اگر میخواهید یک فهرست جدید برگردانید، بهجای آن از تابع توکار for key in sorted(mydict): ... # do whatever with mydict[key]... چگونه مشخصات یک رابط را در پایتون تعیین و اعمال میکنید؟¶مشخصات رابط برای یک ماژول، همانطور که توسط زبانهایی مانند C++ و Java ارائه میشود، پیشنمونههای متدها و توابع آن ماژول را توصیف میکند. بسیاری بر این باورند که اعمال مشخصات رابط در زمان کامپایل، به ساخت برنامههای بزرگ کمک میکند. پایتون 2.6 ماژول در پایتون، بسیاری از مزایای مشخصات رابط را میتوان با نظم آزمون مناسب برای کامپوننتها به دست آورد. یک بدنه آزمون خوب برای یک ماژول میتواند هم یک آزمون رگرسیون فراهم کند و هم بهعنوان مشخصات رابط ماژول و مجموعهای از مثالها عمل کند. بسیاری از ماژولهای پایتون میتوانند بهصورت یک اسکریپت اجرا شوند تا یک «خودآزمایی» ساده فراهم کنند. حتی ماژولهایی که از رابطهای خارجی پیچیده استفاده میکنند، اغلب میتوانند با استفاده از stub ساده برای رابط خارجی، بهصورت مجزا آزمون شوند. میتوان از ماژولهای یک رویه مناسب آزمون، همانطور که داشتن مشخصات رابط کمک میکند، میتواند به ساخت برنامههای بزرگ و پیچیده در پایتون کمک کند. در واقع، میتواند بهتر باشد، زیرا مشخصات رابط نمیتواند برخی از ویژگیهای یک برنامه را آزمون کند. برای مثال، انتظار میرود متد نوشتن بدنههای آزمون بسیار مفید است، و شاید بخواهید کد خود را بهگونهای طراحی کنید که بهراحتی آزمون شود. یکی از تکنیکهایی که بهطور فزایندهای محبوب شده است، توسعه آزمونمحور است که ایجاب میکند ابتدا بخشهایی از بدنه آزمون را بنویسید، پیش از آنکه هیچیک از کد واقعی را بنویسید. البته پایتون به شما اجازه میدهد که سهلانگار باشید و اصلاً هیچ مورد آزمونی ننویسید. چرا goto وجود ندارد؟¶در دههی ۱۹۷۰، مشخص شد که goto بدون محدودیت میتوانست به کد آشفتهی «اسپاگتی» منجر شود که درک و اصلاح آن دشوار بود. در یک زبان سطح بالا نیز، تا زمانی که راههایی برای انشعاب (در پایتون، با دستورهای همچنین میتوان از استثناها برای فراهم کردن یک «goto ساختاریافته» استفاده کرد که حتی میان فراخوانیهای تابع نیز کار میکند. بسیاری بر این باورند که استثناها میتوانند بهراحتی تمام استفادههای معقول از ساختارهای class label(Exception): pass # declare a label try: ... if condition: raise label() # goto label ... except label: # where to goto pass ... این به شما اجازه نمیدهد به وسط یک حلقه بپرید، اما به هر حال چنین کاری معمولاً سوءاستفاده از چرا رشتههای خام (r-strings) نمیتوانند با بکاسلش پایان یابند؟¶دقیقتر، آنها نمیتوانند با تعداد فردی از بکاسلشها پایان یابند: بکاسلش جفتنشده در انتها، نویسهی علامت نقلقول پایانی را خنثی میکند و باعث میشود رشتهای پایاننیافته باقی بماند. رشتههای خام برای آسانتر کردن ایجاد ورودی برای پردازندههایی (عمدتاً موتورهای عبارت باقاعده) طراحی شدهاند که میخواهند پردازش خنثیسازی بکاسلش خودشان را انجام دهند. این پردازندهها در هر حال یک بکاسلش انتهایی بدون تطابق را خطا میدانند، بنابراین رشتههای خام آن را مجاز نمیشمارند. در عوض، به شما اجازه میدهند که نویسهی نقلقول رشته را با خنثی کردن آن بهوسیلهی یک بکاسلش منتقل کنید. این قوانین زمانی که رشتههای r برای هدف مورد نظرشان استفاده شوند، بهخوبی کار میکنند. اگر در حال تلاش برای ساخت مسیرهای ویندوزی هستید، توجه داشته باشید که همه فراخوانیهای سیستمی ویندوز نیز اسلشهای رو به جلو را میپذیرند: f = open("/mydir/file.txt") # بهدرستی کار میکند! اگر میخواهید یک مسیر برای دستور DOS بسازید، برای مثال یکی از موارد زیر را امتحان کنید dir = r"\this\is\my\dos\dir" "\\" dir = r"\this\is\my\dos\dir\ "[:-1] dir = "\\this\\is\\my\\dos\\dir\\" چرا پایتون یک دستور "with" برای انتساب ویژگیها ندارد؟¶پایتون یک دستور with obj: a = 1 # equivalent to obj.a = 1 total = total + 1 # obj.total = obj.total + 1 در پایتون، چنین ساختاری مبهم خواهد بود. زبانهای دیگر، مانند Object Pascal، Delphi و C++، از انواع ایستا استفاده میکنند، بنابراین میتوان بهشکلی بدون ابهام دانست که به کدام عضو انتساب صورت میگیرد. این نکته اصلی نوعدهی ایستا است — کامپایلر همیشه محدوده هر متغیر را در زمان کامپایل میداند. پایتون از انواع پویا استفاده میکند. نمیتوان از قبل دانست که در رانتایم به کدام ویژگی ارجاع داده خواهد شد. ویژگیهای عضو ممکن است در لحظه به شیءها اضافه یا از آنها حذف شوند. این موضوع باعث میشود نتوان از یک خواندن ساده فهمید که به کدام ویژگی ارجاع داده میشود: یک ویژگی محلی، یک ویژگی سراسری، یا یک ویژگی عضو؟ برای مثال، قطعهکد ناقص زیر را در نظر بگیرید: def foo(a): with a: print(x) این قطعه کد فرض میکند که با این حال، مزیت اصلی function(args).mydict[index][index].a = 21 function(args).mydict[index][index].b = 42 function(args).mydict[index][index].c = 63 این را بنویسید: ref = function(args).mydict[index][index] ref.a = 21 ref.b = 42 ref.c = 63 این موضوع همچنین اثر جانبی افزایش سرعت اجرا را دارد، زیرا پیوندهای نام (name bindings) در پایتون در رانتایم حل میشوند و نسخه دوم تنها لازم است این حل را یک بار انجام دهد. پیشنهادهای مشابهی که سینتکسی را برای کاهش بیشتر حجم کد معرفی میکردند، مانند استفاده از «نقطه آغازین»، به نفع صراحت رد شدهاند (به https://mail.python.org/pipermail/python-ideas/2016-May/040070.html مراجعه کنید). چرا تولیدگرها از دستور with پشتیبانی نمیکنند؟¶به دلایل فنی، تولیدگری که بهطور مستقیم بهعنوان مدیر زمینه استفاده شود، بهدرستی کار نخواهد کرد. هنگامی که، همانطور که رایجترین حالت است، یک تولیدگر بهعنوان پیمایشگری استفاده میشود که تا پایان اجرا میشود، نیازی به بستن نیست. هرگاه لازم باشد، آن را در دستور چرا دونقطهها برای دستورات if/while/def/class الزامی هستند؟¶دونقطه عمدتاً برای افزایش خوانایی لازم است (یکی از نتایج زبان آزمایشی ABC). این را در نظر بگیرید: if a == b print(a) در مقایسه با if a == b: print(a) توجه کنید که چگونه مورد دوم کمی آسانتر خوانده میشود. همچنین توجه کنید که چگونه یک دونقطه مثال را در این پاسخِ پرسشهای متداول جدا میکند؛ این یک کاربرد استاندارد در زبان انگلیسی است. دلیل فرعی دیگر این است که دونقطه کار را برای ویرایشگرهای دارای برجستهسازی سینتکس آسانتر میکند؛ آنها میتوانند بهدنبال دونقطهها بگردند تا تشخیص دهند چه زمانی تورفتگی باید افزایش یابد، بهجای اینکه مجبور باشند تجزیه پیچیدهتری از متن برنامه انجام دهند. چرا پایتون اجازه میدهد در انتهای فهرستها و تاپلها کاما وجود داشته باشد؟¶پایتون به شما امکان میدهد یک کامای پایانی را در انتهای فهرستها، تاپلها و دیکشنریها اضافه کنید: [1, 2, 3,] ('a', 'b', 'c',) d = { "A": [1, 5], "B": [6, 7], # last trailing comma is optional but good style } دلایل متعددی برای مجاز دانستن این وجود دارد. هنگامی که یک مقدار لفظی برای فهرست، تاپل یا دیکشنری دارید که در چند خط پخش شده است، افزودن عناصر بیشتر آسانتر است، زیرا لازم نیست به خاطر بسپارید که باید یک ویرگول به خط قبلی اضافه کنید. همچنین میتوان سطرها را بدون ایجاد خطای سینتکسی جابهجا کرد. حذف تصادفی کاما میتواند منجر به خطاهایی شود که اشکالزدایی آنها دشوار است. برای مثال: x = [ "fee", "fie" "foo", "fum" ] این فهرست به نظر میرسد چهار عنصر دارد، اما در واقع شامل سه عنصر است: "fee"، "fiefoo" و "fum". افزودن همیشگی ویرگول از این منبع خطا جلوگیری میکند. مجاز بودن کامای پایانی همچنین ممکن است تولید کد بهصورت برنامهای را آسانتر کند.
© حق نشر 2001 Python Software Foundation.
این صفحه تحت مجوز بنیاد نرمافزار پایتون نسخه ۲ منتشر شده است. مثالها، دستورالعملها، و سایر کدهای موجود در مستندات همچنین تحت مجوز بدون بند BSD منتشر شدهاند. برای اطلاعات بیشتر به تاریخچه و مجوز مراجعه کنید. بنیاد نرمافزار پایتون یک شرکت غیرانتفاعی است. لطفاً کمک مالی کنید. آخرین بهروزرسانی در نوامبر 12, 2026 (06:19 UTC). آیا اشکالی یافتید؟ ساخته شده با Sphinx 9.1.0. |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |