1. مقدمه

این راهنمای مرجع، زبان برنامه‌نویسی پایتون را شرح می‌دهد. این راهنما به‌عنوان یک آموزش در نظر گرفته نشده است.

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

افزودن جزئیات بیش‌ازحد پیاده‌سازی به یک سند مرجع زبان خطرناک است — ممکن است پیاده‌سازی تغییر کند و پیاده‌سازی‌های دیگر همان زبان به شکل متفاوتی کار کنند. از سوی دیگر، CPython تنها پیاده‌سازی پایتون است که به‌طور گسترده استفاده می‌شود (اگرچه پیاده‌سازی‌های جایگزین همچنان در حال کسب پشتیبانی هستند)، و ویژگی‌های خاص آن گاهی ارزش ذکر شدن دارند، به‌ویژه در مواردی که پیاده‌سازی محدودیت‌های اضافی تحمیل می‌کند. بنابراین، «یادداشت‌های پیاده‌سازی» کوتاهی را خواهید یافت که در سراسر متن پراکنده شده‌اند.

هر پیاده‌سازی پایتون شامل تعدادی ماژول توکار و استاندارد است. این ماژول‌ها در The Python standard library مستند شده‌اند. چند ماژول توکار نیز هنگامی ذکر شده‌اند که تعامل قابل‌توجهی با تعریف زبان دارند.

1.1. پیاده‌سازی‌های جایگزین

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

پیاده‌سازی‌های شناخته‌شده شامل موارد زیر هستند:

CPython

این پیاده‌سازی اصلی پایتون است که بیش از همه نگهداری می‌شود و به زبان C نوشته شده است. ویژگی‌های جدید زبان معمولاً ابتدا در اینجا ظاهر می‌شوند.

Jython

پایتون پیاده‌سازی‌شده به زبان جاوا. این پیاده‌سازی را می‌توان به‌عنوان زبان اسکریپت‌نویسی برای برنامه‌های جاوا استفاده کرد، یا برای ساخت برنامه‌ها با استفاده از کتابخانه‌های کلاس جاوا به کار برد. همچنین اغلب برای ساخت آزمون‌هایی برای کتابخانه‌های جاوا استفاده می‌شود. اطلاعات بیشتر را می‌توانید در وب‌سایت Jython بیابید.

پایتون برای .NET

این پیاده‌سازی در واقع از پیاده‌سازی CPython استفاده می‌کند، اما یک برنامه مدیریت‌شده .NET است و کتابخانه‌های .NET را در دسترس قرار می‌دهد. این پیاده‌سازی توسط Brian Lloyd ایجاد شد. برای اطلاعات بیشتر، صفحه خانگی Python for .NET را ببینید.

IronPython

یک پایتون جایگزین برای .NET. برخلاف Python.NET، این پیاده‌سازی کاملی از پایتون است که IL تولید می‌کند و کد پایتون را به‌طور مستقیم به اسمبلی‌های .NET کامپایل می‌کند. این پروژه توسط Jim Hugunin، خالق اصلی Jython، ایجاد شد. برای اطلاعات بیشتر، وب‌سایت IronPython را ببینید.

PyPy

یک پیاده‌سازی از پایتون که به‌طور کامل به زبان پایتون نوشته شده است. این پیاده‌سازی از چندین قابلیت پیشرفته پشتیبانی می‌کند که در سایر پیاده‌سازی‌ها یافت نمی‌شوند، مانند پشتیبانی از حالت بدون پشته (stackless support) و کامپایلر در لحظه (Just in Time compiler). یکی از اهداف این پروژه تشویق به آزمایش خود زبان با آسان‌تر کردن تغییر مفسر است (زیرا به زبان پایتون نوشته شده است). اطلاعات بیشتر در صفحه‌ی خانگی پروژه‌ی PyPy در دسترس است.

هر یک از این پیاده‌سازی‌ها به شکلی با زبان، آن‌گونه که در این راهنما مستند شده است، تفاوت دارد، یا اطلاعات خاصی را فراتر از آنچه در مستندات استاندارد پایتون پوشش داده شده است ارائه می‌کند. لطفاً به مستندات ویژه‌ی پیاده‌سازی مراجعه کنید تا تعیین کنید چه نکات دیگری لازم است درباره‌ی پیاده‌سازی مشخصی که استفاده می‌کنید بدانید.

1.2. نمادگذاری

توضیحات تحلیل واژگانی و سینتکس از یک نمادگذاری گرامری استفاده می‌کنند که ترکیبی از EBNF و PEG است. برای مثال:

name:   letter (letter | digit | "_")*
letter: "a"..."z" | "A"..."Z"
digit:  "0"..."9"

در این مثال، خط نخست بیان می‌کند که name یک letter است که به دنبال آن دنباله‌ای از صفر یا بیشتر letter، digit و زیرخط می‌آید. letter به‌نوبه‌ی خود هر یک از نویسه‌های تکی 'a' تا 'z' و A تا Z است؛ digit یک نویسه از 0 تا 9 است.

هر قاعده با یک نام آغاز می‌شود (که قاعده‌ای را که تعریف می‌شود مشخص می‌کند) و پس از آن یک دونقطه، :، می‌آید. تعریف سمت راست دونقطه از عناصر نحوی زیر استفاده می‌کند:

  • name: یک نام به قاعده‌ای دیگر ارجاع می‌دهد. در صورت امکان، پیوندی به تعریف آن قاعده است.

    • TOKEN: یک نام با حروف بزرگ به یک token ارجاع می‌دهد. برای اهداف تعاریف گرامر، توکن‌ها همان قواعد هستند.

  • "text"، 'text': متن درون علامت‌های نقل‌قول تکی یا دوتایی باید عیناً (بدون علامت‌های نقل‌قول) مطابقت داشته باشد. نوع علامت نقل‌قول با توجه به معنای text انتخاب می‌شود:

    • 'if': نامی که درون علامت نقل‌قول تکی باشد، نشان‌دهنده یک کلیدواژه است.

    • "case": نامی که در علامت نقل‌قول دوتایی قرار دارد، نشان‌دهنده‌ی یک کلیدواژه نرم است.

    • '@': یک نماد غیرحرفی درون علامت نقل‌قول تکی، بیانگر یک توکن OP است، یعنی یک جداکننده یا عملگر.

  • e1 e2: آیتم‌هایی که فقط با فضای سفید از هم جدا شده‌اند، یک دنباله را نشان می‌دهند. در اینجا، بعد از e1 باید e2 بیاید.

  • e1 | e2: از یک خط عمودی برای جدا کردن جایگزین‌ها استفاده می‌شود. این نشان‌دهنده‌ی «انتخاب ترتیبی» (ordered choice) در PEG است: اگر e1 تطابق داشته باشد، e2 در نظر گرفته نمی‌شود. در گرامرهای PEG سنتی، این به‌صورت یک اسلش، /، نوشته می‌شود، نه یک خط عمودی. برای پیشینه و جزئیات بیشتر PEP 617 را ببینید.

  • e*: یک ستاره به معنای تکرار آیتم پیشین به تعداد صفر یا بیشتر است.

  • e+: به همین ترتیب، علامت مثبت به معنای یک یا چند تکرار است.

  • [e]: عبارتی که در کروشه قرار دارد، به معنای ۰ یا ۱ رخداد است. به بیان دیگر، عبارت درون کروشه اختیاری است.

  • e?: علامت سؤال دقیقاً همان معنای کروشه‌ها را دارد: آیتم پیشین اختیاری است.

  • (e): پرانتزها برای گروه‌بندی استفاده می‌شوند.

از نمادگذاری زیر تنها در تعاریف واژگانی استفاده می‌شود.

  • "a"..."z": دو نویسه‌ی لفظی که با سه نقطه از هم جدا شده‌اند، به معنای انتخاب هر تک‌نویسه در بازه‌ی داده‌شده (شامل ابتدا و انتها) از نویسه‌های ASCII است.

  • <...>: عبارت بین علامت‌های زاویه‌ای، توصیفی غیررسمی از نماد مورد تطبیق (برای مثال، <any ASCII character except "\">) یا مخففی را ارائه می‌دهد که در متن نزدیک تعریف‌شده است (برای مثال، <Lu>).

برخی تعریف‌ها همچنین از پیش‌نگری‌ها (lookaheads) استفاده می‌کنند، که نشان می‌دهند یک عنصر باید (یا نباید) در یک موقعیت مشخص مطابقت کند، اما بدون مصرف هیچ ورودی:

  • &e: یک پیش‌نگر مثبت (positive lookahead)، یعنی e باید تطابق داشته باشد

  • !e: یک پیش‌نگری منفی (negative lookahead) است، یعنی e باید تطابق نداشته باشد

عملگرهای یک‌عملوندی (*، +، ?) تا حد ممکن محکم مقیدسازی میشوند; خط عمودی (|) سست‌ترین مقیدسازی را دارد.

فضای سفید تنها برای جداسازی توکن‌ها معنی‌دار است.

قواعد معمولاً در یک خط قرار می‌گیرند، اما قواعدی که بیش از حد طولانی هستند ممکن است شکسته شوند:

literal: stringliteral | bytesliteral
         | integer | floatnumber | imagnumber

به‌عنوان جایگزین، می‌توان قواعد را به‌گونه‌ای قالب‌بندی کرد که خط اول با دونقطه پایان یابد و هر جایگزین در خط جدیدی با یک خط عمودی آغاز شود. برای مثال:

literal:
   | stringliteral
   | bytesliteral
   | integer
   | floatnumber
   | imagnumber

این به هیچ وجه به این معنا نیست که اولین جایگزین خالی است.

1.2.1. تعاریف واژگانی و نحوی

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

تفاوت عملی میان این دو آن است که در تعاریف واژگانی، تمام فضای خالی معنادار است. تحلیل‌گر واژگانی تمام فضای خالی‌ای را که به توکن‌هایی مانند token.INDENT یا NEWLINE تبدیل نشده باشد، حذف می‌کند. سپس تعاریف نحوی به‌جای نویسه‌های منبع از این توکن‌ها استفاده می‌کنند.

این مستندات از دستور زبان BNF یکسانی برای هر دو سبک تعریف استفاده می‌کند. تمام موارد استفاده از BNF در فصل بعدی (تحلیل واژگانی) تعاریف واژگانی هستند؛ موارد استفاده در فصل‌های بعدی تعاریف نحوی هستند.