From c1c85cd569e0e6f9479d168aa03c489806acc9d1 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Fri, 11 Dec 2015 12:02:40 +0330 Subject: [PATCH 001/316] add l10 --- .../sphinx_minoo_theme/static/minoo-ltr.css | 1 + .../sphinx_minoo_theme/static/minoo-rtl.css | 5 +- _templates/sphinx_minoo_theme/static/minoo.js | 2 +- index.rst | 1 + lessons/l10.rst | 786 ++++++++++++++++++ log.rst | 13 + 6 files changed, 805 insertions(+), 3 deletions(-) create mode 100644 lessons/l10.rst diff --git a/_templates/sphinx_minoo_theme/static/minoo-ltr.css b/_templates/sphinx_minoo_theme/static/minoo-ltr.css index 09cf2c7..af564a3 100644 --- a/_templates/sphinx_minoo_theme/static/minoo-ltr.css +++ b/_templates/sphinx_minoo_theme/static/minoo-ltr.css @@ -35,6 +35,7 @@ thead{background-color:#5C6BC0;color:#FFFFFF} caption{text-align:center;color:#212121;padding:8px 24px;background-color:#E8EAF6} code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:12px} code,kbd,samp{padding:2px 6px;white-space:pre} +code{color:#212121} pre{margin:0;overflow-wrap:normal} ul,ol{padding-left:24px;font-size:16px} ul li{list-style:disc;margin-top:1px;font-size:16px} diff --git a/_templates/sphinx_minoo_theme/static/minoo-rtl.css b/_templates/sphinx_minoo_theme/static/minoo-rtl.css index 72b5c9d..642642c 100644 --- a/_templates/sphinx_minoo_theme/static/minoo-rtl.css +++ b/_templates/sphinx_minoo_theme/static/minoo-rtl.css @@ -35,6 +35,7 @@ thead{background-color:#5C6BC0;color:#FFFFFF} caption{text-align:center;color:#212121;padding:8px 24px;background-color:#E8EAF6} code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:12px} code,kbd,samp{padding:2px 6px;white-space:pre} +code{color:#212121} pre{margin:0;overflow-wrap:normal;text-align:left} ul,ol{padding-right:24px;font-size:16px} ul li{list-style:disc;font-size:16px} @@ -237,5 +238,5 @@ body{font-size:16px} .table-ltr th{text-align:center !important} .reportmenufield{background-color:#ec407a !important} .reportmenufield:hover{border-right:5px #f48fb1 solid !important} -.exercisesmenufield{background-color:#ff7043 !important} -.exercisesmenufield:hover{border-right:5px #ffab91 solid !important} +.exercisesmenufield{background-color:#ef5350 !important} +.exercisesmenufield:hover{border-right:5px #ef9a9a solid !important} diff --git a/_templates/sphinx_minoo_theme/static/minoo.js b/_templates/sphinx_minoo_theme/static/minoo.js index 41b28d6..1eea9d6 100644 --- a/_templates/sphinx_minoo_theme/static/minoo.js +++ b/_templates/sphinx_minoo_theme/static/minoo.js @@ -124,7 +124,7 @@ $( document ).ready(function() { if ($(this).text().contains("گزارش")) { $(this).addClass('reportmenufield'); } - if ($(this).text().contains("تمرین‌های")) { + if ($(this).text().contains("خودآزمایی")) { $(this).addClass('exercisesmenufield'); } }); diff --git a/index.rst b/index.rst index 15ba85d..acc806d 100644 --- a/index.rst +++ b/index.rst @@ -23,6 +23,7 @@ lessons/l07 lessons/l08 lessons/l09 + lessons/l10 log | diff --git a/lessons/l10.rst b/lessons/l10.rst new file mode 100644 index 0000000..6c7f2d5 --- /dev/null +++ b/lessons/l10.rst @@ -0,0 +1,786 @@ +.. role:: emoji-size + +.. meta:: + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس دهم ورودی و خروجی + :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, انواع شی در پایتون, انواع داده در پایتون, پایتون + + +درس ۱۰: ورودی و خروجی +======================= + +موضوع این درس به چگونگی دریافت یا خواندن داده‌ها از کاربر حالت تعاملی یا فایل‌ها و همچنین نمایش یا نوشتن در آن‌ها اختصاص یافته است؛ بر همین اساس در متن درس به بررسی شی فایل و تابع‌های آماده ``()print`` و ``()input`` در پایتون پرداخته خواهد شد. به برخی از تفاوت‌ها در پیاده‌سازی نسخه جدید پایتون (شاخه 3x) که به موضوع این درس مربوط می‌باشند نیز اشاره شده است. + + + + + +:emoji-size:`✔` سطح: مقدماتی + +---- + + +فایل‌ها +-------- + +فایل‌ها (Files) جزو منابع منطقی کامپیوتر به شمار می‌روند، توسط سیستم عامل مدیریت می‌شوند و امکانی برای نگهداری طولانی مدت از اطلاعات می‌باشند. فایل‌ها در واقع بیت‌هایی متوالی از صفر و یک هستند که بر روی دیسک ذخیره گشته‌اند و معمولا در دو قالب جداگانه: + +* «فایل‌‌ باینری» (binary file) - مانند: فایل‌های ویدئو، فایل‌های تصویر، فایل zip، فایل بایت‌کد پایتون و... +* «فایل‌ متنی» (text file) - مانند: فایل HTML، فایل ماژول پایتون و... + +شناخته می‌شوند. + +همانطور که گفته شد فایل‌ها چیزی جز مجموعه‌ای از مقدارهای باینری (یا دودویی) نیستند و فایل‌های متنی نیز در واقع یک زیر مجموعه از فایل‌های باینری است با این تفاوت که بیت‌های یک فایل متنی در کنار هم، بسته به نوع کدگذاری آن متناظر با دنباله‌ای از کاراکترهایی مشخص و قابل چاپ هستند. محتوای این نوع فایل در سطرهایی جداگانه قرار داده می‌شود و با استفاده از برنامه‌های ویرایشگر متن برای انسان خوانا می‌باشد. در یک فایل متنی با کدگذاری ASCII (اَسکی) هر هشت بیت (یک بایت) برابر یک کاراکتر می‌باشد - کدهای اسکی هفت بیتی هستند ولی در اکثر کامپیوترها برای هر کدام یک بایت در نظر گرفته می‌شود - برای نمونه کلمه Python به شکل شش بایت که هر کدام به ترتیب برابر مقدار باینری کد اسکی هر یک از این کاراکترها می‌باشد، ذخیره می‌شود. اسکی تنها از ۱۲۸ کاراکتر - از کد ۰ تا ۱۲۷ (در پایه ده) - پشتیبانی می‌کند و به همین دلیل امروزه بیشتر از کدگذاری‌های استاندارد Unicode (یونیکد) استفاده می‌گردد. در یونیکد مجموعه بسیار بزرگتری از کاراکتر نسبت به کدگذاری اسکی پشتیبانی می‌شود به گونه‌ای که اسکی را نیز در برمی‌گیرد؛ برای نمونه در کدگذاری UTF-8 از این استاندارد، ۱۲۸ کد نخست (از کد ۰ تا ۱۲۷) برابر کد همان ۱۲۸ کاراکتر اسکی می‌باشد. کدگذاری UTF-8 کاراکترهای یونیکد را در یک دنباله بایت با طول متغیر (۱ تا ۶ بایت) ارايه می‌دهد؛ در این کدگذاری برای کاراکترهای اسکی تنها یک بایت در نظر گرفته می‌شود. + +در یک فایل باینری وجود سطر مفهومی ندارد و بایت‌های آن ممکن است داده‌هایی را نمایش دهند که نمی‌توان آن‌ها را توسط هیچ یک از کدگذاری‌های کاراکتر (UTF-8 ،ASCII و...) چاپ کرد یا حتی ممکن است در صورت چاپ آن‌ها نیز حاصل برای انسان غیر قابل فهم باشد. + + + + +پایتون یک نوع شی آماده برای دستیابی فایل‌ها در برنامه ارایه می‌دهد که این شی با استفاده از تابع آماده ``(open(file, mode`` [`اسناد پایتون `__] ایجاد می‌گردد؛ آرگومان نخست یک شی رشته حاوی نام کامل فایل (نشانی + نام + پسوند) مورد نظر بر روی دیسک کامپیوتر است و آرگومان دوم نیز یک رشته با مقداری خاص است و حالتی که این فایل می‌بایست در آن باز شود را مشخص می‌سازد؛ این آرگومان اختیاری است و مقدار پیش‌فرض آن ``'r'`` می‌باشد. برای نمونه به کدهای پایین که با یکدیگر معادل هستند توجه نمایید:: + + >>> f = open('/home/saeid/Documents/sample.txt') + +:: + + >>> f = open('/home/saeid/Documents/sample.txt', 'r') + +:: + + >>> f = open('/home/saeid/Documents/sample.txt', mode='r') + +مسیر نمونه فایل بالا بر اساس سیستم فایل لینوکس درج شده است که در ویندوز برای مثال می‌تواند به یکی از دو شکل پایین درج گردد: + +.. code-block:: html + + r'C:\Users\Saeid\Documents\sample.txt' + +.. code-block:: html + + 'C:\\Users\\Saeid\\Documents\\sample.txt' + +آرگومان file را می‌توان تنها با نام خالی فایل و بدون ذکر مسیر آن مقداردهی کرد؛ در این صورت مفسر پایتون مسیر دایرکتوری جاری را برای آن در نظر می‌گیرد. با استفاده از تابع ``()getcwd`` از ماژول ``os`` [`اسناد پایتون `__] می‌توانیم مسیر دایرکتوری جاری برنامه را به دست آوریم. [در درس بعد بیشتر درباره این ماژول صحبت خواهیم کرد]:: + + >>> import os + + >>> os.getcwd() + '/home/saeid' + +آرگومان mode نیز بر حسب نیاز می‌تواند یکی از مقدارهای پایین را داشته باشد: + + +* ``'r'``: فایل در قالب متنی تنها به منظور خواندن از آن باز می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد یک خطا (یا استثنا) FileNotFoundError گزارش می‌گردد. معادل ``'rt'`` +* ``'w'``: فایل در قالب متنی تنها به منظور نوشتن در آن باز می‌شود؛ متن درون آن (در صورت وجود) پاک می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل ``'wt'`` +* ``'a'``: فایل در قالب متنی تنها به منظور افزودن متنی در انتهای متن موجود در آن باز می‌شود؛ اشاره‌گر در انتهای فایل قرار دارد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل ``'at'`` +* ``'x'``: فقط در پایتون exclusive creation) - 3x) فایل در قالب متنی ایجاد و به منظور نوشتن در آن باز می‌شود؛ چنانچه این فایل از پیش موجود باشد یک خطا (یا استثنا) FileExistsError گزارش می‌گردد. معادل ``'xt'`` +* ``'rb'`` و ``'wb'`` و ``'ab'`` و ``'xb'``: همان توضیح گزینه‌های مشابه بالا را دارند ولی با این تفاوت که برای کار با فایل‌هایی در قالب باینری استفاده می‌شوند. +* ``'+r'``: فایل در قالب متنی به منظور **خواندن و نوشتن** باز می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد یک خطا (یا استثنا) FileNotFoundError گزارش می‌گردد. توجه داشته باشید که در این حالت عمل نوشتن از همان ابتدای فایل، باعث جایگزین شدن متن جدید با متن حاضر می‌شود. معادل ``'+rt'`` یا ``'r+t'`` +* ``'+w'``: فایل در قالب متنی به منظور **نوشتن و خواندن** باز می‌شود؛ متن درون آن (در صورت وجود) پاک می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل ``'+wt'`` یا ``'w+t'`` +* ``'+a'``: فایل در قالب متنی به منظور افزودن متنی در انتهای متن موجود در آن و همچنین خواندن باز می‌شود؛ اشاره‌گر در انتهای فایل قرار دارد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل ``'+at'`` یا ``'a+t'`` +* ``'+x'``: فقط در پایتون 3x - فایل در قالب متنی ایجاد و به منظور نوشتن و خواندن باز می‌شود؛ چنانچه این فایل از پیش موجود باشد یک خطا (یا استثنا) FileExistsError گزارش می‌گردد. معادل ``'+xt'`` یا ``'x+t'`` +* ``'+rb'`` یا ``'r+b'`` و ``'+wb'`` یا ``'w+b'`` و ``'+ab'`` یا ``'a+b'`` و ``'+xb'`` یا ``'x+b'``: همان توضیح گزینه‌های مشابه بالا را دارند ولی با این تفاوت که برای کار با فایل‌هایی در قالب باینری استفاده می‌شوند. +* ``'rU'``: خواندن یک فایل متنی با پشتیبانی از Universal Newline. معادل ``'rtU'`` +* ``'rbU'``: خواندن یک فایل باینری با پشتیبانی از Universal Newline. + + +که در آن‌ها: + +* ``r``: خواندن (read) +* ``w``: نوشتن (write) +* ``a``: درج در انتها (appending) +* ``t``: تعیین قالب متنی (text) برای فایل مورد نظر؛ قالب پیش‌فرض است و نیازی به درج آن نیست +* ``b``: تعیین قالب باینری (binary) برای فایل مورد نظر +* ``+``: فایل به منظور بروز رسانی (updating) باز می‌شود +* ``U``: حالت Universal Newline + +در قرارداد سیستم‌های عامل گوناگون از رشته‌های مختلفی - که می‌تواند از یک یا چند کاراکتر تشکیل شده باشد - برای نشانه‌گذاری انتهای سطرهای یک فایل متنی استفاده شده است؛ برای نمونه در ویندوز از CRLF (یا ``'r\n\'``) و در گنولینوکس از LF (یا ``'n\'``) استفاده می‌شود. شی فایل پایتون به صورت پیش‌فرض از همان قرارداد سیستم عامل میزبان برای تعیین رشته Newline خود استفاده می‌کند؛ ولی چنانچه قصد دارید در پایتون فایلی با قرارداد سیستم عامل دیگری را به منظور خواندن باز نمایید می‌بایست این کار را در حالت Universal Newline انجام دهید. در این حالت به هنگام خواندن از یک فایل، پایتون تمام رشته‌های Newline موجود در فایل را به کاراکتر ``'n\'`` نگاشت می‌کند [`PEP 278 `_]؛ دستور ``os.linesep`` [`اسناد پایتون `__] رشته Newline سیستم عامل میزبان را برمی‌گرداند:: + + >>> import os + + >>> os.linesep # GNU/Linux + '\n' + + +باز کردن یک فایل به منظور خواندن از آن حکم یک منبع ورودی (input) و باز کردن یک فایل به منظور نوشتن در آن حکم یک منبع خروجی (output) را در برنامه دارد. + +*تابع ()open آرگومان‌های اختیاری دیگری نیز دارد که برای بررسی آن‌ها می‌توانید به اسناد پایتون مراجعه نمایید.* + +.. rubric:: متدهای شی فایل + +* ``(write(string``: یک شی از نوع ``str`` یا ``bytes`` را دریافت می‌کند و آن را درون شی فایل مورد نظر می‌نویسد:: + + >>> text = '1) Python\n2) Programming\n3) Language\n' + + >>> print(text) + 1) Python + 2) Programming + 3) Language + + >>> + + >>> type(text) + + + :: + + >>> # Python 3x + + >>> output = open('textfile.txt', 'w') + >>> output.write(text) + 37 + >>> output.close() + + *در پایتون 3x، متد write تعداد کاراکترهایی که می‌نویسد را برمی‌گرداند.* + + :: + + >>> # Python 3x + + >>> output = open('binaryfile.bin', 'wb') + >>> output.write(text) + Traceback (most recent call last): + File "", line 1, in + TypeError: a bytes-like object is required, not 'str' + + *در پایتون 3x به این دلیل که نوع رشته‌های باینری (bytes) از رشته‌های معمولی (str) جدا گشته است، نمی‌توان از شی str برای نوشتن در فایلی که در حالت باینری باز شده است استفاده کرد.* + + :: + + >>> # Python 3x + + >>> data = '1) Python\n2) Programming\n3) Language\n' + + >>> # Convert str to bytes + >>> bdata = bytes(data, 'utf-8') + + >>> bdata + b'1) Python\n2) Programming\n3) Language\n' + + >>> type(bdata) + + + + >>> output = open('binaryfile.bin', 'wb') + >>> output.write(bdata) + 37 + >>> output.close() + + در رفتار گنولینوکس تفاوتی بین حالت متنی و باینری وجود ندارد؛‌ اکنون اگر هر دو فایل textfile.txt و binaryfile.bin را (در گنولینوکس) توسط برنامه ویرایشگر متن باز نمایید، خواهید دید که محتوای این دو فایل مشابه یکدیگر نمایش داده می‌شوند. + + *در گنولینوکس، باز کردن فایل textfile.txt توسط یک برنامه ویرایشگر متن:* + + .. code-block:: html + :linenos: + + 1) Python + 2) Programming + 3) Language + + *در گنولینوکس، باز کردن فایل binaryfile.bin توسط یک برنامه ویرایشگر متن:* + + .. code-block:: html + :linenos: + + 1) Python + 2) Programming + 3) Language + + ولی در ویندوز به هنگام حالت متنی، اگر یک فایل را به منظور خواندن باز نمایید کاراکترهای ``'n\'`` موجود در آن به شکل ``'r\n\'`` برگردانده می‌شوند و اگر که یک فایل را به منظور نوشتن باز کنید، هر بار رشته ``'r\n\'`` به جای ``'n\'`` نوشته می‌شود. در حالت باینری این کارها انجام نمی‌شود. + + *اگر دستورهای یاد شده را در ویندوز اجرا نماییم؛ دو فایل مورد نظر با محتوای پایین توسط برنامه ویرایشگر متن نمایش داده خواهند شد.* + + *در ویندوز، باز کردن فایل textfile.txt:* + + .. code-block:: html + :linenos: + + 1) Python + 2) Programming + 3) Language + + *در ویندوز، باز کردن فایل binaryfile.bin:* + + .. code-block:: html + :linenos: + + 1) Python2) Programming3) Language + + + به نمونه‌ کدهای بالا در پایتون 2x نیز توجه نمایید:: + + >>> # Python 2x + + >>> output = open('textfile.txt', 'w') + >>> output.write('1) Python\n2) Programming\n3) Language\n') + >>> output.close() + + :: + + >>> # Python 2x + + >>> data = '1) Python\n2) Programming\n3) Language\n' + + >>> type(data) + + + >>> output = open('binaryfile.bin', 'wb') + >>> output.write(data) + >>> output.close() + + :: + + >>> # Python 2x + + >>> bdata = b'1) Python\n2) Programming\n3) Language\n' + + >>> type(bdata) + + + >>> output = open('binaryfile.bin', 'wb') + >>> output.write(bdata) + >>> output.close() + + +* ``()close``: پس از پایان کار با هر فایل می‌بایست که آن را ببندید؛ این متد فایل باز شده را می‌بندد. شی فایل مورد نظر پس از فراخوانی این متد، هیچ متد دیگری را نمی‌تواند فراخوانی کند. + + زمانی که شمارش ارجاع به یک شی فایل به صفر برسد یا وقتی متغیر فایل به شی فایل دیگری اشاره کند، پایتون شی قبلی را به صورت خودکار می‌بندد؛ ولی همیشه بهتر است که بستن فایل به صورت صریح توسط برنامه‌نویس انجام شود. + + همچنین برای بررسی اینکه یک فایل باز است یا اینکه بسته شده است می‌توانید از صفت ``closed`` استفاده نمایید؛ این صفت در صورتی که فایل بسته شده باشد حاوی مقدار ``True`` می‌باشد:: + + >>> f.closed + False + + >>> f.close() + + >>> f.closed + True + + +* ``()read``: تمام محتوای فایل را می‌خواند و در قالب یک شی از نوع ``str`` - برای فایل‌های متنی در هر دو شاخه پایتون و باینری در پایتون 2x - یا ``bytes`` - برای فایل‌های باینری در پایتون 3x - برمی‌گرداند:: + + >>> input = open('textfile.txt') + + >>> content = input.read() + + >>> input.close() + + >>> type(content) + + + >>> content + '1) Python\n2) Programming\n3) Language\n' + + >>> print(content) + 1) Python + 2) Programming + 3) Language + + >>> + + :: + + >>> # Python 3x, Reading a binary file + + >>> input = open('binaryfile.bin', 'rb') + + >>> content = input.read() + + >>> input.close() + + >>> type(content) + + + >>> content + b'1) Python\n2) Programming\n3) Language\n' + + >>> print(content) + b'1) Python\n2) Programming\n3) Language\n' + >>> + + :: + + >>> # Python 2x, Reading a binary file + + >>> input = open('binaryfile.bin', 'rb') + + >>> content = input.read() + + >>> input.close() + + >>> type(content) + + + >>> content + '1) Python\n2) Programming\n3) Language\n' + + >>> print content + 1) Python + 2) Programming + 3) Language + + >>> + + این متد یک آرگومان اختیاری نیز دارد؛ این آرگومان یک عدد صحیح است که تعداد کاراکتر (یا بایت) که می‌بایست از فایل خوانده و برگردانده شوند را تعیین می‌کند:: + + >>> f = open('textfile.txt') + + >>> f.read(5) + '1) Py' + + >>> f.read(5) + 'thon\n' + + >>> f.read(10) + '2) Program' + + >>> f.read(4) + 'ming' + + >>> f.read(1) + '\n' + + >>> f.close() + + به نمونه کد بالا توجه نمایید؛ هنگامی که فایل در این حالت (rt) باز شده است اشاره‌گر در ابتدای فایل قرار گرفته **و با هر میزان خواندن از فایل، موقعیت اشاره‌گر نیز به جلو حرکت داشته است.** + + | + +* ``()readline``: در هر فراخوانی یک سطر از فایل - تا رشته Newline - را برمی‌گرداند:: + + >>> f = open('textfile.txt') + + >>> f.readline() + '1) Python\n' + + >>> f.readline() + '2) Programming\n' + + >>> f.readline() + '3) Language\n' + + >>> f.readline() + '' + + >>> f.close() + + + +* ``()readlines``: تمام سطرهای یک فایل را در قالب یک شی لیست بر می‌گرداند:: + + >>> f = open('textfile.txt') + + >>> cl = f.readlines() + + >>> cl + ['1) Python\n', '2) Programming\n', '3) Language\n'] + + >>> cl[1] + '2) Programming\n' + + >>> f.close() + +* ``(writelines(list``: یک شی لیست که تمام اعضای آن از نوع str هستند را به عنوان آرگومان گرفته و اعضای آن را به ترتیب در فایل مورد نظر می‌نویسد:: + + + >>> L = ['a', 'b', 'c', 'd\n', 'e'] + + >>> f = open('tf.txt', 'w') + >>> f.writelines(L) + >>> f.close() + + *حاصل کد بالا؛ باز کردن فایل tf.txt توسط یک برنامه ویرایشگر متن:* + + .. code-block:: html + :linenos: + + abcd + e + +* ``(seek(offset``: آرگومان offset یک عدد صحیح است و این متد موقعیت اشاره‌گر فایل را به آن offset نسبت به ابتدای فایل تغییر می‌دهد:: + + >>> f = open('textfile.txt') + + >>> f.seek(3) + 3 + + >>> f.read(6) + 'Python' + + >>> f.close() + +* ``()flush``: باعث ذخیره محتوای بافر در فایل می‌شود. + + هنگامی که فایلی را به منظور نوشتن باز می‌کنید، تا پیش از زمان بستن فایل هر آنچه در آن می‌نویسید در بافر قرار داده می‌شود. فراخوانی این متد کمک می‌کند تا بدون بستن فایل، اطلاعات از بافر به فایل منتقل گردند. + +.. rubric:: دستور ``for`` + +از تابع ``()open`` نیز می‌توان در حلقه ``for`` استفاده کرد؛ در این صورت در هر بار تکرار سطرهای فایل پیمایش می‌شوند:: + + >>> for line in open('textfile.txt'): + ... print(line, end='') + ... + 1) Python + 2) Programming + 3) Language + >>> + +از آنجا که متن درون فایل خود حاوی Newline (در اینجا: ``'n\'``) است، آرگومان ``end`` تابع ``()print`` را برای جلوگیری از درج ``'n\'`` در انتهای هر سطر تغییر دادیم [در بخش print درباره آرگومان end صحبت خواهیم کرد]. + + +دستور ``with/as`` +~~~~~~~~~~~~~~~~~~~ + +یک دستور مرکب است که از اشیایی که با نوع ”Context Manager“ [`اسناد پایتون `__] در پایتون شناخته می‌شوند، پشتیبانی می‌کند [`PEP 343 `_]. برخی از اشیا در پایتون - به مانند شی فایل - قابلیتی با نام ”Context Manager“ دارند؛ برای پیاده سازی این قابلیت، کلاس شی مورد نظر می‌بایست حاوی دو متد ویژه ``()__enter__`` و ``()__exit__`` باشد که به ترتیب در زمان‌های «ورود به» و «خروج از» بدنه دستور ``with/as`` فراخوانی می‌شوند. + +دستور ``with/as`` ساختاری مشابه پایین دارد: + +.. code-block:: html + + with expression as variable: + statement(s) + + +در این ساختار، expression نماد بخشی از دستور است که یک شی از نوع Context Manager را برمی‌گرداند؛ این شی با استفاده از کلمه کلیدی ``as`` به یک متغیر ارجاع داده می‌شود. برای نمونه ساختار ``with/as`` مربوط به یک شی فایل در پایین نوشته شده است:: + + with open('textfile.txt', 'w') as output: + output.write('text') + +پس از ایجاد شی فایل، این شی می‌بایست وارد اجرای دستور ``with/as`` شود؛ ``with/as`` این کار را با فراخوانی متد ``()__enter__`` انجام می‌دهد. در واقع این متد همان شی فایل ایجاد شده را برمی‌گرداند که در ادامه توسط ``as`` به متغیر output ارجاع داده می‌شود. همچنین با استفاده از این ساختار دیگر نیازی به فراخوانی متد ``()close`` برای شی فایل نمی‌باشد؛ چرا که این کار پس از پایان دستورهای بدنه با فراخوانی شدن متد ``()__exit__`` توسط ``with/as`` به انجام می‌رسد؛ در واقع ``with/as`` بستن فایل را در پایان اجرای دستورهای بدنه خود تضمین می‌کند. همچنین در این ساختار چنانچه هنگام کار با فایل خطایی (یا استثنایی) رخ دهد، پیش از گزارش آن، ابتدا فایل بسته خواهد شد. + + +توجه داشته باشید که یک شی فایل همیشه باید بسته شود؛ در مواقعی که قصد استفاده از حلقه ``for`` برای یک شی فایل را دارید بهتر است از آن درون ساختار ``with/as`` بهره بگیرید: + +.. code-block:: python + + with open('textfile.txt') as f: + for line in f: + print(line) + +از دستور ``with/as`` می‌توان به شکل تودرتو نیز بهره گرفت: + +.. code-block:: html + + with A() as a: + with B() as b: + statements + +همچنین به نسخه‌های 2.7 و از 3.1 به بعد پایتون سینتکس جدیدی افزوده شده است که توسط آن می‌توان همزمان از چند Context Manager بهره گرفت: + +.. code-block:: html + + with A() as a, B() as b: + statements + +به مانند نمونه کد پایین که دو فایل را باز می‌کند؛ از یکی می‌خواند و برخی از سطرهای آن را در فایل دیگر می‌نویسد:: + + with open('data') as fin, open('res', 'w') as fout: + for line in fin: + if 'key' in line: + fout.write(line) + +شی فایل استاندارد +------------------- +سه نوع شی فایل توسط مفسر پایتون ایجاد می‌گردد که هر سه آن‌ها توسط ماژول ``sys`` در دسترس هستند: + +* ``sys.stdin``: ورودی استاندارد [`اسناد پایتون `__]؛ برای دستیابی تمامی ورودی‌ها در حالت تعاملی پایتون - مانند فراخوانی تابع ``()input`` - از این شی استفاده می‌گردد. +* ``sys.stdout``: خروجی استاندارد [`اسناد پایتون `__]؛ توسط ``print`` مورد استفاده قرار می‌گیرد. +* ``sys.stderr``: خطا استاندارد [`اسناد پایتون `__]؛ شی‌ای است که خطاها را دریافت می‌کند. + +نه همیشه ولی می‌توان منبع ``sys.stdin`` را صفحه‌کلید کامپیوتر و منبع ``sys.stdout`` و ``sys.stderr`` را نیز صفحه‌نمایش در نظر گرفت. + + + +تابع ()input +-------------- + +از این تابع در پایتون برای گرفتن ورودی از کاربر - در حالت تعاملی - استفاده می‌گردد که در نسخه جدید تغییراتی با نسخه قدیمی ایجاد شده است. + + +.. rubric:: پایتون 2x: + +* ``()raw_input`` +* ``()input`` + +در این شاخه از پایتون دو تابع ``()raw_input`` [`اسناد پایتون `__] و ``()input`` [`اسناد پایتون `__] برای همین منظور در دسترس است. تابع ``()raw_input`` یک سطر از کاربر را می‌خواند و در قالب یک شی از نوع ``str`` برمی‌گرداند:: + + >>> s = raw_input() + Hello Python + +با اجرا دستور سطر یکم، مفسر پایتون منتظر ورود متن می‌ماند - در این نمونه متن Hello Python نوشته می‌شود - سپس با دریافت کلید Enter تمام کاراکترهای دریافتی را در قالب یک شی رشته - نوع ``str`` - به متغیر ``s`` ارجاع می‌دهد:: + + >>> s + 'Hello Python' + >>> type(s) + + +همچنین می‌توان متنی را برای مشاهده کاربر به صورت آرگومان در فراخوانی تابع قرار داد:: + + >>> s = raw_input("What's your name? ") + What's your name? Alan + + >>> s + 'Alan' + +:: + + >>> s = raw_input("How old are you? ") + How old are you? 41 + + >>> s + '41' + >>> type(s) + + +تابع ``()input`` در پایتون 2x نیز عملکردی برابر با دستور ``(()eval(raw_input`` دارد. ``()eval`` [`اسناد پایتون `__] تابع آماده دیگری در پایتون است که یک شی رشته را دریافت و متن آن را به شکل کد پایتون تفسیر می‌کند:: + + >>> x = 1 + >>> y = eval('x + 1') + >>> y + 2 + >>> type(y) + + +به نمونه کدهای پایین نیز توجه نمایید:: + + >>> eval("9 // 2") + 4 + + >>> eval("9 /// 2") + Traceback (most recent call last): + File "", line 1, in + File "", line 1 + 9 /// 2 + ^ + SyntaxError: invalid syntax + >>> + + +:: + + >>> a = '32' + >>> type(a) + + + >>> b = eval(a) + + >>> b + 32 + >>> type(b) + + +:: + + >>> print eval("__import__('os').getcwd()") + /home/saeid + +تابع ``()__import__`` [`اسناد پایتون `__] عملکردی برابر با دستور ``import`` دارد ولی با این تفاوت که می‌توان از آن به شکلی پویا در طی اجرای برنامه برای وارد کردن ماژول‌های گوناگون استفاده نمود؛ در این حالت نام یک ماژول حتی می‌تواند به شکل یک متغیر در آرگومان تابع قرار بگیرد. + +اکنون که با عملکرد تابع ``()eval`` آشنا شده‌اید به بیان مثال‌هایی از تابع ``()input`` - در نسخه‌های 2x - می‌پردازیم:: + + >>> s = input("What's your name? ") + What's your name? Alan + + Traceback (most recent call last): + File "", line 1, in + File "", line 1, in + NameError: name 'Alen' is not defined + >>> + +در نمونه کد بالا؛ ورودی کاربر - متن Alen - با هیچ سینتکس تعریف شده‌ای در پایتون مطابقت نداشته و باعث بروز خطا گشته است:: + + >>> s = input("What's your name? ") + What's your name? "Alan" + + >>> s + 'Alan' + +:: + + >>> s = input("How old are you? ") + How old are you? 41 + + >>> s + 41 + >>> type(s) + + +و مثالی دیگر:: + + >>> a = raw_input() + 3 * 4 ** 5 + + >>> a + '3 * 4 ** 5' + + + >>> b = input() + 3 * 4 ** 5 + + >>> b + 3072 + + +.. rubric:: پایتون 3x: + +* ``()input`` + +در این شاخه از پایتون تابع ``()input`` از شاخه 2x وجود ندارد (حذف شده) و تنها تابع ``()raw_input`` باقی مانده است که آن هم به ``()input`` [`اسناد پایتون `__] تغییر نام پیدا کرده است. + +تابع ``()input`` در پایتون 3x همانند تابع ``()raw_input`` در پایتون 2x است:: + + >>> s = input("What's your name? ") + What's your name? Alan + + >>> s + 'Alan' + >>> type(s) + + + + + + +تابع ()print +-------------- + +.. rubric:: پایتون 2x: + +در این شاخه از پایتون print به شکل یک دستور ساده در پایتون پیاده‌سازی شده است [`اسناد پایتون `__]. این دستور یک یا چند شی را ابتدا به نوع ``str`` تبدیل کرده و سپس به خروجی می‌فرستد:: + + >>> s = 'Python' + + >>> print s + Python + + >>> print s, "2.x" + Python 2.x + + >>> print 4 * 5 / 2, 3 * 3 + 10 9 + +:: + + >>> print + + >>> + + + +* اشیا می‌بایست توسط یک کاما ``,`` از یکدیگر جدا شوند. +* این دستور به صورت پیش‌فرض یک حرف فاصله (یک کلید Space) در بین اشیا قرار می‌دهد. +* در صورتی که یک عبارت محاسباتی یا منطقی به این دستور داده شود، ابتدا حاصل آن محاسبه یا ارزیابی شده و سپس به نوع ``str`` تبدیل می‌گردد. +* دستور ``print`` به شکل تنها، یکی سطر خالی را ایجاد می‌کند. + +دستور print همچنین به صورت پیش‌فرض یک ``'n\'`` در انتهای هر سطر قرار می‌دهد؛ برای لغو این رفتار می‌توان در انتهای دستور یک کاما ``,`` قرار داد:: + + >>> for a in range(5): + ... print a + ... + 0 + 1 + 2 + 3 + 4 + >>> + + + >>> for a in range(5): + ... print a, + ... + 0 1 2 3 4 + >>> + +این دستور توانایی نوشتن در شی فایلی غیر از شی استاندارد را نیز دارد؛ برای این منظور می‌بایست از الگوی پایین پیروی گردد:: + + >>> text = 'Hi :)' + >>> output = open('textfile.txt', 'w') + + >>> print >> output, text + + >>> output.close() + + + + +.. rubric:: پایتون 3x: + +دستور ``print`` به شکل تابع ``()print`` در نسخه‌های 3x پایتون پیاده‌سازی شده است [`اسناد پایتون `__]؛ الگوی این تابع به شکل پایین می‌باشد:: + + print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) + +* ``objects*``: بیانگر اشیایی است می‌خواهیم در خروجی قرار بدهیم. که می‌تواند هیچ باشد - که برابر نمایش یک سطر خالی است - یا اینکه می‌تواند یک یا چند شی - که در این صورت اشیا می‌بایست توسط یک کاما ``,`` از یکدیگر جدا شوند - را در بر گیرد:: + + >>> print() + + >>> + + + :: + + >>> s = 'Python' + + >>> print(s) + Python + + >>> print(s, '3x') + Python 3x + + >>> print(4 * 5 / 2, 3 * 3) + 10.0 9 + + +* ``sep``: رشته‌ای که می‌بایست بین اشیا قرار گیرد را تعیین می‌کند. مقدار این آرگومان در حالت پیش‌فرض یک حرف فاصله (یک کلید Space) است. مقدار ارسالی به این آرگومان می‌بایست یک شی رشته یا ``None`` باشد:: + + >>> print(s, '3x', sep='-') + Python-3x + + >>> print(s, '3x', sep=None) + Python 3x + +* ``end``: رشته‌ای که می‌بایست در انتهای هر سطر قرار گیرد را تعیین می‌کند. مقدار این آرگومان در حالت پیش‌فرض ``'n\'`` است. مقدار ارسالی به این آرگومان می‌بایست یک شی رشته یا ``None`` باشد:: + + >>> for a in range(5): + ... print(a) + ... + 0 + 1 + 2 + 3 + 4 + >>> + + + >>> for a in range(5): + ... print(a, end=' ') + ... + 0 1 2 3 4 >>> + + +* ``file``: خروجی را تعیین می‌کند که می‌بایست یک شی به همراه متد ``(write(string`` درون کلاس خود، باشد. این آرگومان به صورت پیش‌فرض بر روی خروجی استاندارد مقداردهی شده است. این تابع قابلیت استفاده در حالت باینری فایل‌ها را **ندارد**:: + + >>> output = open('textfile.txt', 'w') + + >>> print('Hi :)', file=output) + + >>> output.close() + + +* ``flush``: این آرگومان از نسخه 3.3 به تابع ``()print`` پایتون افزوده شده است. هنگامی که خروجی بر روی یک فایل قرار گرفته باشد؛ با تنظیم این گزینه بر روی مقدار ``True``، عمل انتقال متن به فایل بدون اتلاف وقت انجام می‌پذیرد. + + +این تابع با استفاده از دستور import پایین در نسخه‌های 2.6 و 2.7 پایتون نیز در دسترس است [`اسناد پایتون `__]:: + + from __future__ import print_function + + + + + +| + +---- + +:emoji-size:`😊` امیدوارم مفید بوده باشه + +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ + + diff --git a/log.rst b/log.rst index 8498de5..b171957 100644 --- a/log.rst +++ b/log.rst @@ -1,3 +1,5 @@ +.. role:: emoji-size + .. meta:: :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - صفحه گزارش رویداد‌ها @@ -9,6 +11,17 @@ +.. raw:: html + +

00107 - جمعه ۲۰ آذر ۱۳۹۴

+ +درس دهم با عنوان «ورودی و خروجی» به فهرست کتاب افزوده شد. +:emoji-size:`😉` + +---- + + + .. raw:: html

00106 - دوشنبه ۲۰ مهر ۱۳۹۴

From ce2f8b264d6ea9d386a46dc737fa9b36372f0c5a Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Fri, 11 Dec 2015 13:11:03 +0330 Subject: [PATCH 002/316] add .gitignore file --- .gitignore | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05d9664 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# sphinx build folder +_build + +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store? +ehthumbs.db +Icon? +Thumbs.db + +# Editor backup files # +####################### +*~ From 1bebce46ccac8f0857d979048eca43f27b96bd3b Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Sun, 11 Dec 2016 00:48:59 +0330 Subject: [PATCH 003/316] add l11 + some change --- _templates/sphinx_minoo_theme/__init__.py | 2 +- .../sphinx_minoo_theme/includes/bottom.html | 2 +- .../static/fonts/Behdad-Regular.otf | Bin 0 -> 38632 bytes .../static/fonts/Behdad-Regular.ttf | Bin 0 -> 54792 bytes .../static/fonts/Behdad-Regular.woff | Bin 0 -> 25852 bytes .../static/fonts/Behdad-Regular.woff2 | Bin 0 -> 18672 bytes .../sphinx_minoo_theme/static/minoo-ltr.css | 4 +- .../sphinx_minoo_theme/static/minoo-rtl.css | 13 +- _templates/sphinx_minoo_theme/static/minoo.js | 7 +- index.rst | 2 + lessons/l01.rst | 18 +- lessons/l02.rst | 22 +- lessons/l03.rst | 40 +- lessons/l04.rst | 19 +- lessons/l05.rst | 6 +- lessons/l06.rst | 4 +- lessons/l11.rst | 442 ++++++++++++++++++ log.rst | 17 +- preface.rst | 15 + requirements.txt | 1 + 20 files changed, 563 insertions(+), 51 deletions(-) create mode 100644 _templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.otf create mode 100644 _templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.ttf create mode 100644 _templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.woff create mode 100644 _templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.woff2 create mode 100644 lessons/l11.rst create mode 100644 preface.rst diff --git a/_templates/sphinx_minoo_theme/__init__.py b/_templates/sphinx_minoo_theme/__init__.py index 2100e2b..50c7724 100644 --- a/_templates/sphinx_minoo_theme/__init__.py +++ b/_templates/sphinx_minoo_theme/__init__.py @@ -9,7 +9,7 @@ class MinooVersion(): major = "0" minor = "9" - micro = "5" + micro = "0" level = "Beta" release = r"2015/05/21" def info(self): diff --git a/_templates/sphinx_minoo_theme/includes/bottom.html b/_templates/sphinx_minoo_theme/includes/bottom.html index 81e5773..51703cd 100644 --- a/_templates/sphinx_minoo_theme/includes/bottom.html +++ b/_templates/sphinx_minoo_theme/includes/bottom.html @@ -45,7 +45,7 @@ {%- if show_sphinx %}

{% trans sphinx_version=sphinx_version|e %} - Created using Sphinx ({{ sphinx_version }}) with Minoo (Beta 0.9.7) theme. + Created using Sphinx ({{ sphinx_version }}) with Minoo (0.9.7) theme. {% endtrans %}

{%- endif %} diff --git a/_templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.otf b/_templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..45cd2b4dad59733db5c796c262a08d7b6256112d GIT binary patch literal 38632 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 literal 0 HcmV?d00001 diff --git a/_templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.woff b/_templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..993878ad1bb92007fcb01046f5d3f0d7363fc4c9 GIT binary patch literal 25852 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 literal 0 HcmV?d00001 diff --git a/_templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.woff2 b/_templates/sphinx_minoo_theme/static/fonts/Behdad-Regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..d84cdf1b73136b346ac27bb35442d24b7a25a54a GIT binary patch literal 18672 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 TIcl@sfHISP6ZT(S(6a>qlzoN; literal 0 HcmV?d00001 diff --git a/_templates/sphinx_minoo_theme/static/minoo-ltr.css b/_templates/sphinx_minoo_theme/static/minoo-ltr.css index af564a3..e5f66e2 100644 --- a/_templates/sphinx_minoo_theme/static/minoo-ltr.css +++ b/_templates/sphinx_minoo_theme/static/minoo-ltr.css @@ -33,9 +33,9 @@ th{text-align:left} td,th{vertical-align:top} thead{background-color:#5C6BC0;color:#FFFFFF} caption{text-align:center;color:#212121;padding:8px 24px;background-color:#E8EAF6} -code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:12px} +code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:12px;direction:ltr;font-size:12px;font-weight:600;} code,kbd,samp{padding:2px 6px;white-space:pre} -code{color:#212121} +code{color:#000} pre{margin:0;overflow-wrap:normal} ul,ol{padding-left:24px;font-size:16px} ul li{list-style:disc;margin-top:1px;font-size:16px} diff --git a/_templates/sphinx_minoo_theme/static/minoo-rtl.css b/_templates/sphinx_minoo_theme/static/minoo-rtl.css index 642642c..fd59907 100644 --- a/_templates/sphinx_minoo_theme/static/minoo-rtl.css +++ b/_templates/sphinx_minoo_theme/static/minoo-rtl.css @@ -12,7 +12,7 @@ box[note,attention[body:90CAF9,title:42A5F5]-tip,important[body:80CBC4,title:26A @font-face{font-family:"Inconsolata";font-style:normal;font-weight:400;src:local("Inconsolata"),url(fonts/Inconsolata.ttf) format("truetype")}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:700;src:local("Inconsolata Bold"),local("Inconsolata-Bold"),url(fonts/Inconsolata-Bold.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:400;src:local("Lato Regular"),local("Lato-Regular"),url(fonts/Lato-Regular.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:700;src:local("Lato Bold"),local("Lato-Bold"),url(fonts/Lato-Bold.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:local("Roboto Slab Regular"),local("RobotoSlab-Regular"),url(fonts/RobotoSlab-Regular.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:local("Roboto Slab Bold"),local("RobotoSlab-Bold"),url(fonts/RobotoSlab-Bold.ttf) format("truetype")} /* HTML elements */ -body{font-family:'IranianSans',"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#212121;min-height:100%;font-size:16px;overflow-x:hidden} +body{font-family:'Behdad',"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#212121;min-height:100%;font-size:16px;overflow-x:hidden} html{height:100%} a,ul>li>a,ol>li>a{text-decoration:none!important;color:#5C6BC0;padding:0} a:hover,ul>li>a:hover,ol>li>a:hover{color:#66BB6A} @@ -33,7 +33,7 @@ th{text-align:right} td,th{vertical-align:top} thead{background-color:#5C6BC0;color:#FFFFFF} caption{text-align:center;color:#212121;padding:8px 24px;background-color:#E8EAF6} -code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:12px} +code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:14px} code,kbd,samp{padding:2px 6px;white-space:pre} code{color:#212121} pre{margin:0;overflow-wrap:normal;text-align:left} @@ -240,3 +240,12 @@ body{font-size:16px} .reportmenufield:hover{border-right:5px #f48fb1 solid !important} .exercisesmenufield{background-color:#ef5350 !important} .exercisesmenufield:hover{border-right:5px #ef9a9a solid !important} +@font-face { + font-family: 'Behdad'; + src: url('fonts/Behdad-Regular.otf'), + url('fonts/Behdad-Regular.woff2') format('woff2'), + url('fonts/Behdad-Regular.woff') format('woff'), + url('fonts/Behdad-Regular.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} diff --git a/_templates/sphinx_minoo_theme/static/minoo.js b/_templates/sphinx_minoo_theme/static/minoo.js index 1eea9d6..dbbf7c0 100644 --- a/_templates/sphinx_minoo_theme/static/minoo.js +++ b/_templates/sphinx_minoo_theme/static/minoo.js @@ -121,10 +121,13 @@ $( document ).ready(function() { // custome function $("li[id^='wrapper-toctree-l1-'] a").each(function() { - if ($(this).text().contains("گزارش")) { + if ($(this).text().indexOf("گزارش توسعه")>=0) { $(this).addClass('reportmenufield'); } - if ($(this).text().contains("خودآزمایی")) { + if ($(this).text().indexOf("پیش‌گفتار")>=0) { + $(this).addClass('reportmenufield'); + } + if ($(this).text().indexOf("خودآزمایی") >= 0) { $(this).addClass('exercisesmenufield'); } }); diff --git a/index.rst b/index.rst index acc806d..f9eaffa 100644 --- a/index.rst +++ b/index.rst @@ -14,6 +14,7 @@ .. toctree:: :maxdepth: 6 + preface lessons/l01 lessons/l02 lessons/l03 @@ -24,6 +25,7 @@ lessons/l08 lessons/l09 lessons/l10 + lessons/l11 log | diff --git a/lessons/l01.rst b/lessons/l01.rst index 5657d1e..da232f5 100644 --- a/lessons/l01.rst +++ b/lessons/l01.rst @@ -9,7 +9,7 @@ درس ۰۱: آشنایی ================= -این درس با بیان تاریخچه ایجاد پایتون شروع و با توصیفی کوتاه و شرح ویژگی‌های آن ادامه می‌یابد؛ در شرح ویژگی‌ها سعی شده است کمی نیز توضیحات غیر پایتونی برای درک بهتر موضوعات ارایه گردد. همچنین در مورد کارایی پایتون و این موضوع که چرا در حال حاضر دو شاخه متفاوت از این زبان وجود دارد نیز صحبت شده است. هدف این درس ایجاد یک پیش زمینه‌ بدون ابهام از پایتون است! به این امید که مفید باشد و بتواند شما را به یادگیری این زبان تشویق کند :emoji-size:`😉`. +این درس با بیان تاریخچه ایجاد پایتون شروع و با توصیفی کوتاه و شرح ویژگی‌های آن ادامه می‌یابد؛ در شرح ویژگی‌ها سعی شده است کمی نیز توضیحات غیرپایتونی برای درک بهتر موضوعات ارایه گردد. همچنین در مورد کارایی پایتون و این موضوع که چرا در حال حاضر دو شاخه متفاوت از این زبان وجود دارد نیز صحبت شده است. هدف این درس ایجاد یک پیش‌زمینه‌ بدون ابهام از پایتون است! به این امید که مفید باشد و بتواند شما را به یادگیری این زبان تشویق کند :emoji-size:`😉`. :emoji-size:`✔` سطح: پایه @@ -27,15 +27,15 @@ توصیفی کوتاه -------------- -سادگی و خوانایی از ویژگی‌های بارز زبان برنامه‌نویسی پایتون است، آنچنان ساده که حتی کودکان نیز قادر به آموختن آن هستند و قدرت در کنار این سادگی و خوانایی، معجزه‌ پایتون می‌باشد. از نگاه هر برنامه‌نویسی، برنامه‌های پایتون مجموعه‌ای از کد‌های زیبا هستند، بدون هیچ آشفتگی و پیچیدگی. این زبان به جای این که برنامه‌نویس را درگیر فهم ساختارش کند، به ابزاری قدرتمند برای تحقق تمام آنچه که در فکر برنامه‌نویس است تبدیل می‌شود، اگر در اجرای نخست کدهای پایتون خود هیچ خطایی نگرفتید؛ تعجب نکنید!. این زبان به شدت دوست داشتنی است :emoji-size:`😍`. +سادگی و خوانایی از ویژگی‌های بارز زبان برنامه‌نویسی پایتون است، آنچنان ساده که حتی کودکان نیز قادر به آموختن آن هستند و قدرت در کنار این سادگی و خوانایی، معجزه‌ پایتون می‌باشد. از نگاه هر برنامه‌نویسی، برنامه‌های پایتون مجموعه‌ای از کد‌های زیبا هستند، بدون هیچ آشفتگی و پیچیدگی. این زبان به جای این که برنامه‌نویس را درگیر فهم ساختارش کند، به ابزاری قدرتمند برای تحقق تمام آنچه که در فکر برنامه‌نویس است تبدیل می‌شود، اگر در اجرای نخست کدهای پایتون خود هیچ خطایی نگرفتید؛ تعجب نکنید! و اگر هم گرفتید، خوشحال باشید!. این زبان به شدت دوست داشتنی است :emoji-size:`😍`. `ilovepython# `_ -زبان برنامه‌نویسی پایتون همانطور که اشاره شد در سال ۱۹۹۱ میلادی توسط آقای روسوم خلق شده و توسعه‌ پایتون نیز زیر نظر مستقیم اوست. آقای روسوم زاده‌ سال ۱۹۵۶ میلادی و نخستین دارنده‌ عنوان `BDFL `_ (دیکتاتور خیرخواه جاویدان)‌ می‌باشد و هم اکنون (سال ۲۰۱۵) در شرکت Dropbox مشغول به کار است. +زبان برنامه‌نویسی پایتون همانطور که اشاره شد در سال ۱۹۹۱ میلادی توسط آقای روسوم خلق شده و توسعه‌ آن نیز زیر نظر مستقیم اوست. آقای روسوم زاده‌ سال ۱۹۵۶ میلادی و نخستین دارنده‌ عنوان `BDFL `_ (دیکتاتور خیرخواه جاویدان)‌ می‌باشد و هم اکنون (سال ۲۰۱۵) در شرکت Dropbox مشغول به کار است. `(صفحه شخصی) `_ توسعه‌ پایتون با عصر توسعه و محبوبیت زبان‌های متن باز دیگری همچون Tcl ،Perl و Ruby هم‌ زمان بوده که این امر به پیشرفت و توسعه‌ آن کمک زیادی کرده است. پایتون یک جامعه‌ کاربری بسیار بزرگ و پویا به همراه خود دارد که عامل پیشرفت و توسعه‌ بسیار مهمی برای هر زبان برنامه‌نویسی به شمار می‌رود. این جامعه هر ساله با برپایی `همایش‌های گوناگون `_ در سراسر جهان به تبادل آموخته‌ها می‌پردازد. یکی از رایج‌ترین این همایش‌ها `PyCon `_ (پای‌کان) می‌باشد که خوشبختانه ‌در ایران (`PyCon Iran یا PyIran `_) نیز برگزار می‌شود. -این زبان تاکنون توسط شرکت یا سازمان‌های مطرح زیادی مورد استفاده قرار گرفته و در برنامه‌های کاربردی زیادی نیز از آن استفاده شده است که از جمله این موارد می‌توان به: Google (موتور جستجوگر و نیز سرویس یوتیوب) / Yahoo (سرویس نقشه) / IBM ،Intel ،Cisco ،Seagate (تست سخت‌افزار) / Dropbox (سرویس میزبانی ابری فایل) / EVE Online (بازی‌های آنلاین) / NASA ،Los Alamos (امور علمی) / iRobot (رباتیک) / Pixar ،Industrial Light and Magic ،Walt Disney (ساخت فیلم‌های انیمیشن) / BitTorrent (اشتراک فایل نظیر به نظیر) / CIA (وب‌سایت) / Mercurial (سیستم کنترل نسخه) / ESRI (نقشه‌برداری در برنامه GIS) و بسیاری دیگر... اشاره نمود. [#f4]_ +این زبان تاکنون توسط شرکت یا سازمان‌های مطرح زیادی مورد استفاده قرار گرفته و در برنامه‌های کاربردی زیادی نیز از آن استفاده شده است که از جمله این موارد می‌توان به: reddit ،Pinterest ،Instagram (شبکه‌های اجتماعی) / Google (موتور جستجوگر و نیز سرویس یوتیوب) / Yahoo (سرویس نقشه) / IBM ،Intel ،Cisco ،Seagate (تست سخت‌افزار) / Dropbox (سرویس میزبانی ابری فایل) / EVE Online (بازی‌های آنلاین) / NASA ،Los Alamos (امور علمی) / iRobot (رباتیک) / Pixar ،Industrial Light and Magic ،Walt Disney (ساخت فیلم‌های انیمیشن) / BitTorrent (اشتراک فایل نظیر به نظیر) / CIA (وب‌سایت) / PayPal (سیستم انتقال پول آنلاین) / Mercurial (سیستم کنترل نسخه) / ESRI (نقشه‌برداری در برنامه GIS) و بسیاری دیگر [#f4]_ اشاره نمود. `(پایتون در stackshare) `_ یک نکته مهم در مورد زبان برنامه‌نویسی پایتون، انواع پیاده‌سازی‌ (Implementation)‌ آن است. تا‌کنون از این زبان پیاده‌سازی‌های گوناگون و با اهداف متفاوتی توسعه یافته است که از این بین می‌توان به `Jython `_ (خاص ماشین مجازی جاوا)، `IronPython `_ (خاص چارچوب NET. مایکروسافت)، `PyPy `_ (با هدف سرعت اجرای بیشتر)، `Stackless `_ (با هدف اجرای بهتر برنامه‌های چند‌نخی) و البته `CPython `_ اشاره نمود. [#f5]_ @@ -45,7 +45,7 @@ CPython (سی‌پایتون) پیاده‌سازی استاندارد و اصل ویژگی‌ها --------- -**پایتون** یک زبان برنامه‌نویسی رایگان، متن باز (Open Source) و آزاد است که هم‌‌اکنون (یعنی از نسخه‌ 2.1 و جدیدتر) پروانه‌ آن توسط «بنیاد نرم‌افزار پایتون» `PSF `_ اداره می‌گردد. پروانه‌ پایتون سازگار با پروانه‌ `GPL3 `_ است، با این حال به برنامه‌نویس این اجازه را می‌دهد که بتواند برنامه‌ای با سورس بسته (Closed Source) تولید نماید. +**پایتون** یک زبان برنامه‌نویسی رایگان، متن باز (Open Source) و با بیانی کامل‌تر، **آزاد** است که هم‌‌اکنون (یعنی از نسخه‌ 2.1 و جدیدتر) پروانه‌ آن توسط «بنیاد نرم‌افزار پایتون» `PSF `_ اداره می‌گردد. پروانه‌ پایتون سازگار با پروانه‌ `GPL3 `_ است، با این حال به برنامه‌نویس این اجازه را می‌دهد که بتواند برنامه‌ای با سورس بسته (Closed Source) تولید نماید. زبان پایتون از اجزای بسته نرم‌افزاری LAMP نیز به شمار می‌رود. این بسته عبارت است از: Linux ~ سیستم عامل / Apache ~ وب سرور / MySQL یا MariaDB ~ پایگاه‌ داده / Python یا Perl یا PHP ~ زبان برنامه‌نویسی. @@ -59,7 +59,11 @@ CPython (سی‌پایتون) پیاده‌سازی استاندارد و اصل بر خلاف زبان C، در پایتون اختصاص و آزاد‌سازی حافظه (Memory) به صورت خودکار انجام می‌شود. پایتون برای آزاد‌سازی حافظه از دو روش «شمارش ارجاع» (Reference Counting) و «زباله روبی» [#f8]_ (Garbage Collection) بهره می‌گیرد. (البته فراموش نشود که صحبت در مورد پیاده‌سازی CPython است) -با اینکه پایتون یک زبان پویاست ولی در عین حال یک زبان «وابسته شدید به نوع» (Strongly Typed) نیز می‌باشد. در این نوع زبان‌ها (به مانند Java) تغییر ناگهانی و خودکار نوع داده (یا شی) انجام نمی‌شود؛ به عنوان نمونه چنانچه در پایتون عمل جمع بین یک نوع داده عددی مانند ``3`` و یک نوع داده غیر عددی مانند ``"7"`` صورت گیرد، یک خطای ``TypeError`` گزارش می‌گردد. در مقابل، زبان‌های «وابسته ضعیف به نوع» (Weak Typed) قرار دارند؛ در این زبان‌ها (به مانند Perl) نوع بر حسب موقعیت به صورت خودکار تغییر داده می‌شوند. در این مورد زبان‌های برنامه‌نویسی رفتارهای متفاوتی دارند،‌ به عنوان نمونه حاصل عبارت ``"7" + 3`` در زبان Perl با تبدیل (Convert)‌ خودکار نوع داده غیر عددی ``"7"`` به عدد (``7``)، مقدار ``10`` محاسبه می‌گردد. +با اینکه پایتون یک زبان پویاست ولی در عین حال یک زبان «وابسته شدید به نوع» (Strongly Typed) نیز می‌باشد. در این نوع زبان‌ها (به مانند Java) تغییر ناگهانی و خودکار نوع داده (یا شی) انجام نمی‌شود؛ به عنوان نمونه چنانچه در پایتون عمل جمع بین یک نوع داده عددی مانند ``3`` و یک نوع داده غیر عددی مانند ``"7"`` صورت گیرد، یک Exception یا استثنای ``TypeError`` گزارش می‌گردد. در مقابل، زبان‌های «وابسته ضعیف به نوع» (Weak Typed) قرار دارند؛ در این زبان‌ها (به مانند Perl) نوع بر حسب موقعیت به صورت خودکار تغییر داده می‌شوند. در این مورد زبان‌های برنامه‌نویسی رفتارهای متفاوتی دارند،‌ به عنوان نمونه حاصل عبارت ``"7" + 3`` در زبان Perl با تبدیل (Convert)‌ خودکار نوع داده غیر عددی ``"7"`` به عدد (``7``)، مقدار ``10`` محاسبه می‌گردد. + +.. tip:: + استثنا‌ در واقع وضعیت یا خطایی (Error) است که در برنامه پیش‌بینی شده و بروز آن‌ به مانند یک اعتراض گزارش می‌شود. از طرفی در برنامه برای هر اعتراض، چگونگی رسیدگی به آن نیز تعریف می‌شود. + **پایتون** یک زبان برنامه‌نویسی سطح بالا (High-Level) به مانند C ،Ruby ،PHP و Java است که به وسیله‌ آن عمل برنامه‌نویسی به آسانی و با سرعتی بالا انجام می‌پذیرد و بر‌خلاف زبان برنامه‌نویسی سطح پایینی (Low-Level) مانند Assembly، برنامه‌نویس را درگیر مسایل خاص موجود در این سطح به مانند کار با ثبات‌ها (Registers)، آدرس‌های حافظه و غیره... نمی‌سازد. @@ -121,7 +125,7 @@ CPython (سی‌پایتون) پیاده‌سازی استاندارد و اصل در هر پروژه‌ای بسته به چیزی که می‌خواهیم می‌بایست انتخاب نماییم. اگر مبنای کارایی برای یک پروژه در سرعت بالای اجرا باشد (مانند برنامه‌های سیستمی)؛‌ زبان C همیشه بهترین انتخاب است ولی اگر مبنا در سرعت بالای توسعه و صرفه جویی در منابع از جمله هزینه باشد انتخاب مناسب پایتون است. گاهی نیز بهترین کارایی با استفاده ترکیبی از زبان‌های متفاوت به دست می‌آید. -در بسیاری از کاربردها سرعت پایتون کاملا قابل قبول است، وجود بایت‌کد‌ موجب افزایش سرعت در اجراهای بعدی برنامه می‌شود و نکات برنامه‌نویسی زیادی برای بهبود سرعت اجرا در پایتون وجود دارد که در این کتاب به تدریج اشاره خواهد شد. نباید فراموش کرد که یکی از مهمترین عامل‌های کارایی داشتن الگوریتمی بهینه است و البته نوشتن ماژول‌ها به زبان C نیز موجب افزایش قابل توجه کارایی پایتون می‌شود - `پایتون کند است اگر اشتباه استفاده شود `_ - با این وجود در حالت عادی اگر هزار مورد وجود داشته باشد که پایتون برای آن‌ها بهترین انتخاب باشد، سرعت یکی از آن‌ها نخواهد بود و برای توسعه برنامه‌هایی که سرعت اجرا نقش تعیین کننده‌ دارد باید از زبان‌های دیگری استفاده نمایید. +در بسیاری از کاربردها سرعت پایتون کاملا قابل قبول است، وجود بایت‌کد‌ موجب افزایش سرعت در اجراهای بعدی برنامه می‌شود و نکات برنامه‌نویسی زیادی برای بهبود سرعت اجرا در پایتون وجود دارد که در این کتاب به تدریج اشاره خواهد شد. نباید فراموش کرد که یکی از مهمترین عامل‌های کارایی داشتن الگوریتمی بهینه است و البته نوشتن ماژول‌ها به زبان C نیز موجب افزایش قابل توجه کارایی پایتون می‌شود - `پایتون کند است اگر اشتباه استفاده شود `_ - با این وجود در حالت عادی اگر هزار مورد وجود داشته باشد که پایتون برای آن‌ها بهترین انتخاب باشد، سرعت یکی از آن‌ها نخواهد بود و برای توسعه برنامه‌هایی که سرعت اجرا نقش بسیار تعیین کننده‌‌ای دارد باید از زبان‌های دیگری استفاده نمایید. لازم است به این نکته هم توجه داشته باشیم که تمام این صحبت‌ها در مورد پیاده‌سازی CPython از زبان پایتون بوده و پیاده‌سازی‌های دیگری نیز از زبان پایتون با هدف سرعت بالای اجرا (به مانند `PyPy `_) توسعه یافته است. diff --git a/lessons/l02.rst b/lessons/l02.rst index 2b8cde8..254cc2b 100644 --- a/lessons/l02.rst +++ b/lessons/l02.rst @@ -32,7 +32,7 @@ .. note:: امکان نصب نسخه‌های متفاوت پایتون (حتی از یک شاخه) در کنار یکدیگر وجود دارد. -در هنگام تهیه‌ این کتاب دو نسخه‌ 2.7.9 و 3.4.2 جدیدترین نسخه‌های منتشر یافته‌ پایتون هستند. برای دسترسی به جدید‌ترین ویژگی‌ها، پیشنهاد می‌شود همیشه جدیدترین نسخه‌ موجود از پایتون را دانلود نمایید. +در هنگام نگارش این درس دو نسخه‌ 2.7.9 و 3.4.2 جدیدترین نسخه‌های منتشر یافته‌ پایتون هستند. برای دسترسی به جدید‌ترین ویژگی‌ها، پیشنهاد می‌شود همیشه جدیدترین نسخه‌ موجود از پایتون را دانلود نمایید. نصب در ویندوز --------------- @@ -143,13 +143,13 @@ user> cd Python-3.4.2/ -در پایان با استفاده از دستور ``su`` به سطح دسترسی root رسیده و دستورات پایین را به ترتیب وارد نمایید: +در پایان دستورات پایین را به ترتیب وارد نمایید: .. code:: - root> ./configure - root> make - root> make install + user> sudo ./configure + user> sudo make + user> sudo make install اگر پیش از این نسخه‌ای از شاخه 3x پایتون نصب باشد (مانند 3.3)، دستور سطر سوم موجب جایگزین شدن نسخه‌ جدید (3.4) با آن می‌شود؛ این دستور در مواقع ارتقا نسخه پایتون مفید است. چنانچه قصد دارید همچنان به نسخه‌ پیشین نیز دسترسی داشته باشید، دستور ``make altinstall`` را جایگزین ``make install`` نمایید. به عنوان نمونه وضعیت نسخه‌ 3x پایتون، در زمان‌ قبل و بعد از نصب نسخه‌ جدید به همراه مسیر نصب آن در Fedora 20 آورده شده است. به تفاوت عملکرد دو دستور ``make altinstall`` و ``make install`` توجه نمایید: @@ -203,9 +203,9 @@ .. code:: - root> ./configure --prefix=/opt/python3.4 - root> make - root> make install + user> sudo ./configure --prefix=/opt/python3.4 + user> sudo make + user> sudo make install .. caution:: @@ -344,6 +344,12 @@ pip از زمان انتشار نسخه‌ 3.4 به بسته‌ نصبی پای user> pip show SomePackage +* نصب تمام بسته‌هایی که درون یک فایل متنی به مانند requirements.txt مشخص شده است (`فایل نمونه `__):: + + root> pip install -r requirements.txt + + + | diff --git a/lessons/l03.rst b/lessons/l03.rst index 7d39f32..53a3f70 100644 --- a/lessons/l03.rst +++ b/lessons/l03.rst @@ -16,7 +16,7 @@ ساختار پروژه -------------- -نخستین گام در توسعه‌ یک برنامه پایتون ایجاد یک پروژه است که پس از آن نوشتن کدها یا تهیه سورس کد (`Source code `_) برنامه آغاز می‌شود. +نخستین گام در توسعه‌ یک برنامه پایتون ایجاد یک پروژه است که پس از آن نوشتن کدها یا ایجاد سورس کد (`Source code `_) برنامه آغاز می‌شود. سورس کد یک پروژه به زبان پایتون در قالب یک یا چند «ماژول» (Module) توسعه می‌یابد که در سورس کدهایی با بیش از یک ماژول بهتر است ماژول‌هایی که از نظر منطقی با یکدیگر مرتبط هستند را درون دایرکتوری‌هایی مجزا قرار دهیم که به این نوع دایرکتوری‌ها در زبان پایتون «بسته» (Package) گفته می‌شود. @@ -56,7 +56,9 @@ .. tip:: [`PEP 8 `_]: در نام‌گذاری ماژول‌ها تنها از حروف کوچک استفاده می‌شود و در صورت نیاز می‌توان از کاراکتر خط زیرین (``_``) نیز استفاده نمود. نام بسته‌ها کوتاه بوده و از حروف کوچک تشکیل می‌گردد؛ استفاده از ``_`` در نام بسته پیشنهاد نمی‌شود. -اکنون اطلاعات کافی برای شرع یک پروژه از پایتون را دارید ولی چنانچه می‌خواهید پروژه خود را برای استفاده افراد دیگر از طریق PyPI یا سرویس‌هایی نظیر github.com منتشر نمایید (مانند یک کتابخانه کاربردی)، جدا از سورس کد لازم است موارد دیگری را نیز در ساختار آن در نظر بگیرید. به ساختار پایین توجه نمایید: +اکنون اطلاعات کافی برای شروع یک پروژه از پایتون را دارید ولی چنانچه می‌خواهید با ساختار مناسب پروژه‌ای که قرار است برای استفاده افراد دیگر از طریق PyPI یا سرویس‌هایی نظیر github.com منتشر شود (مانند یک کتابخانه کاربردی) آشنا شوید، ادامه این بخش را نیز مطالعه نمایید. در غیر این صورت می‌توانید به بخش بعدی از همین درس `پرش <#id7>`_ نمایید. + +جدا از سورس کد لازم است موارد دیگری نیز در ساختار این نوع پروژه‌ها در نظر گرفته شود؛ به ساختار پایین توجه نمایید: .. code:: @@ -80,7 +82,8 @@ ├── setup.cfg └── setup.py -ساختار پیش تنها شامل سورس کد می‌بود ولی در این ساختار تمام سورس کد در قالب یک بسته پایتون بخشی از مجموعه بزرگتری است که در آن یک سری فایل به مانند requirements.txt ،README.rst و setup.py به همراه دو دایرکتوری docs و test افزوده شده است. در ادامه کمی از کاربرد این موارد توضیح داده می‌شود ولی در حال حاضر نیازی به رعایت این ساختار نیست و در انتهای کتاب با ایجاد یک پروژه عملی و قرار دادن آن بر روی github.com و PyPI به صورت کاربردی با آن‌ها آشنا خواهید شد. [برای کسب اطلاعات بیشتر می‌توانید از `اسناد پایتون `_ استفاده نمایید] +ساختار ابتدایی تنها شامل سورس کد می‌بود ولی در این ساختار تمام سورس کد در قالب یک بسته پایتون بخشی از مجموعه بزرگتری است که در آن یک سری فایل به مانند requirements.txt ،README.rst و setup.py به همراه دو دایرکتوری docs و test افزوده شده است. +در ادامه کمی از کاربرد این موارد توضیح داده می‌شود ولی تاکید می‌شود که در حال حاضر نیازی به رعایت این ساختار نیست و در انتهای کتاب با ایجاد یک پروژه عملی و قرار دادن آن بر روی github.com و PyPI به صورت کاربردی با آن‌ها آشنا خواهید شد. [برای کسب اطلاعات بیشتر می‌توانید از `اسناد پایتون `_ استفاده نمایید] **setup.py**: این فایل مهم دو کارکرد دارد: ۱- پیکربندی پروژه که از طریق آرگومان‌های تابع آماده ``()setup`` درون این فایل صورت می‌پذیرد. @@ -94,7 +97,7 @@ **MANIFEST.in**: معمولا از این فایل برای معرفی فایل‌های غیر پایتونی موجود در پروژه استفاده می‌شود. زمانی که قصد ایجاد «سورس توزیع» یا sdist از پروژه را داشته باشید (دستوری مشابه: ``python setup.py sdist``) تنها `فایل‌های مشخصی `_ از پروژه شناسایی می‌شوند و شناساندن باقی فایل‌ها (در صورت وجود) می‌بایست توسط این فایل (البته با `الگویی خاص `_) انجام گیرد. -**requirements.txt**: از این فایل برای معرفی کتابخانه‌های خاصی که در پروژه استفاده شده‌اند و در زمان نصب یا اجرای سورس کد ضروری هستند استفاده می‌گردد. +**requirements.txt**: از این فایل برای معرفی کتابخانه‌های خاصی که در پروژه استفاده شده‌اند و در زمان نصب یا اجرای سورس کد، وجود یا نصب بودن آن‌ها نیز ضروری است، استفاده می‌گردد. **LICENSE.txt**: این فایل پروانه‌ انتشار پروژه را شامل می‌شود و اغلب حاوی یک کپی از متن پروانه‌های متن باز رایج به مانند `MIT `_ ،`GPL `_ یا `BSD `_ می‌باشد. @@ -158,7 +161,7 @@ بر همین اساس کدگذاری اسکریپت first_script_2x.py را به دلیل استفاده از کاراکترهایی خارج از مجموعه ASCII (÷ و ×) به UTF-8 تغییر داده‌ایم. **پایتون 3x به صورت پیش‌فرض از استاندارد یونیکد پشتیبانی می‌کند.** -در زبان پایتون هر متنی که بعد از کاراکتر ”Number sign“ یا # (در همان سطر) قرار بگیرد توسط مفسر پایتون نادیده گرفته می‌شود و تاثیری در روند ترجمه و اجرای کدها ندارد، به این نوع متن‌ «توضیح» (کامنت Comment) گفته می‌شود و از آن برای مستندسازی (Documentation) ماژول یعنی ارایه توضیح در مورد بخشی از کد استفاده می‌گردد. ارایه توضیح نقش زیادی در خوانایی ماژول دارد و کمک می‌کند تا شما (در آینده!) و سایر افراد دیگر بتوانند عملکرد کدهای ماژول (یا اسکریپت) شما را بفهمند. +در زبان پایتون هر متنی که بعد از کاراکتر ”Number sign“ یا # (در همان سطر) قرار بگیرد توسط مفسر پایتون نادیده گرفته می‌شود و تاثیری در روند ترجمه و اجرای کدها ندارد، به این نوع متن‌ «توضیح» (کامنت Comment) گفته می‌شود و از آن برای مستندسازی (Documentation) ماژول یعنی ارایه توضیح در مورد بخشی از کد استفاده می‌گردد. ارایه توضیح نقش زیادی در خوانایی ماژول دارد و کمک می‌کند تا افراد دیگر - حتی خودتان - بتوانند عملکرد کدهای ماژول (یا اسکریپت) شما را بفهمند. .. note:: کاراکتر نخست عبارت تعیین کدگذاری نیز # است ولی این سطر کامنت نبوده و درک آن برای مفسر با ارزش می‌باشد. @@ -265,6 +268,23 @@ .. note:: نباید نماد !# (`shebang `_) را با نماد کامنت در پایتون (#) اشتباه گرفت. + +| + +ایجاد اسکریپت پایتون و اجرای آن همان‌طور که مشاهده کردید بسیار ساده است و وابسته به وجود هیچ ابزار خاصی نمی‌باشد ولی برای پایتون نیز مانند هر زبان پر کاربرد دیگری تعداد زیادی `IDE `_ توسعه داده شده است که در ادامه به معرفی چند نمونه مطرح‌تر از این دست ابزار خواهیم پرداخت. + +* `PyDev `_: یک IDE کامل، متن باز و رایگان است که برای پلتفرم `Eclipse `_ ارایه می‌شود. + +* `PyCharm `_: محصولی از شرکت فوق‌العاده JetBrains است که البته نسخه کامل آن فروشی است ولی نسخه کامیونیتی (Community) آن رایگان و متن باز می‌باشد که از بسیاری ویژگی‌ها و امکانات ویژه برخوردار است. (`مقایسه نسخه‌ها `_) + +* `NetBeans `_: یک IDE کامل، متن باز و رایگان است که طرفداران بسیاری دارد. NetBeans به صورت پیش‌فرض از پایتون پشتیبانی نمی‌کند و باید پلاگین مربوط به آن نصب گردد. (`صفحه راهنمای نصب `_) + + + +.. tip:: + IDE یا Integrated development environment به ابزارهایی گفته می‌شود که علاوه‌بر یک ویرایشگر متن پیشرفته، امکانات بسیار کاربردی دیگری را نیز به مانند دیباگر (`Debugger `__) در اختیار برنامه‌نویس قرار می‌دهد. + + پشت صحنه اجرا --------------- زمانی که اقدام به اجرای یک اسکریپت می‌کنید؛ ابتدا، اسکریپت و تمام ماژول‌های وارد شده در آن به بایت‌کد کامپایل و سپس بایت‌کد‌های حاصل جهت تفسیر به زبان ماشین و اجرا، به ماشین مجازی فرستاده می‌شوند. آنچه ما از آن به عنوان مفسر پایتون (پیاده‌سازی CPython) یاد می‌کنیم در واقع ترکیبی از یک کامپایلر و یک ماشین مجازی است. تصویر پایین به خوبی روند اجرای کدهای پایتون را نمایش می‌دهد. @@ -299,23 +319,21 @@ virtualenv در اینجا برای نصب `virtualenv `_ (ویرچوال اِنو) از pip استفاده می‌کنیم. [`برای اطلاعات بیشتر به درس پیش مراجعه نمایید `_] - پیش از شروع هر نصبی بهتر است pip را آپدیت نماییم؛ این مراحل را در سیستم عامل گنو لینوکس به صورت پایین دنبال می‌کنیم:: - user> su - - root> pip install -U pip + user> sudo pip install -U pip [...] Successfully installed pip[...] - root> + user> *نصب virtualenv:* :: - root> pip install virtualenv + user> sudo pip install virtualenv [...] Successfully installed virtualenv[...] - root> + user> .. note:: چنانچه بر روی سیستم عاملی هر دو نسخه 2x یا 3x نصب است؛ این موضوع که virtualenv را توسط pip کدام نسخه نصب نمایید، اهمیت چندانی ندارد. چرا که امکان استفاده از آن برای دیگر نسخه‌ها نیز وجود دارد. diff --git a/lessons/l04.rst b/lessons/l04.rst index 19de507..32a8ea6 100644 --- a/lessons/l04.rst +++ b/lessons/l04.rst @@ -43,7 +43,7 @@ پس از ورود یک پیغام نمایش داده می‌شود؛ در این پیغام ضمن ارایه اطلاعات پایه در مورد مفسر پایتون و سیستم عامل، پیشنهاد می‌شود که جهت یافتن اطلاعات بیشتر در مورد زبان برنامه‌نویسی پایتون از دستورهای ویژه‌ایی استفاده نمایید: -* ``()license``: باعث نمایش چندین صفحه مرتبط با تاریخ توسعه و پروانه‌های پایتون می‌گردد که البته از طریق - صفحه `تاریخچه و پروانه پایتون `_ - نیز قابل مشاهده است. برای مرور از کلید Enter و خروج از کلید q صفحه کلید استفاده نمایید. +* ``()license``: باعث نمایش چندین صفحه مرتبط با تاریخ توسعه و پروانه‌های پایتون می‌گردد که البته از طریق - صفحه `تاریخچه و پروانه پایتون `_ - نیز قابل مشاهده است. برای مرور از کلید Enter و خروج از کلید q صفحه کلید استفاده نمایید. * ``credits``: فهرستی از سازمان‌ها و شرکت‌های مشارکت کننده در توسعه زبان پایتون را نمایش می‌دهد. @@ -53,7 +53,7 @@ در حالت تعاملی پایتون، به صورت پیش‌فرض هر سطر توسط نماد ``<<<`` مشخص می‌شود و از آنجا که امکان وارد کردن دستورهای چند سطری (مانند تابع‌ها) نیز وجود دارد؛ سطرهای مربوط با بدنه یک دستور توسط نماد ``...`` مشخص می‌گردند. -پس از درج هر سطر و با فشردن کلید Enter، مفسر آن سطر را پردازش کرده و در صورت لزوم نتیجه یا گزارش خطا مربوط را نمایش می‌دهد. در واقع پس از فشردن کلید Enter دیگر امکان بازگشت و اصلاح سطر وارد شده وجود نخواهد داشت و می‌بایست آن سطر از نو وارد گردد. بدیهی است که بروز اشتباه در دستورهای چند سطری به معنی لزوم وارد کردن دوباره تمام دستور می‌باشد!. +پس از درج هر سطر و با فشردن کلید Enter، مفسر آن سطر را پردازش کرده و در صورت لزوم نتیجه یا گزارش بروز استثنا مربوط را نمایش می‌دهد. در واقع پس از فشردن کلید Enter دیگر امکان بازگشت و اصلاح سطر وارد شده وجود نخواهد داشت و می‌بایست آن سطر از نو وارد گردد. بدیهی است که بروز اشتباه در دستورهای چند سطری به معنی لزوم وارد کردن دوباره تمام دستور می‌باشد!. .. code-block:: python @@ -101,7 +101,7 @@ 5.0 -مثالی دیگر - در کاربرد ریاضی، برخی تابع‌ها توسط ماژول ``math`` از کتابخانه استاندارد پایتون در دسترس هستند [`اسناد پایتون 3.4 `_]: +مثالی دیگر - در کاربرد ریاضی، برخی تابع‌ها توسط ماژول ``math`` از کتابخانه استاندارد پایتون در دسترس هستند [`اسناد پایتون `_]: .. code-block:: python @@ -121,7 +121,7 @@ *برای وارد کردن یک ماژول به اسکریپت (یا ماژولی دیگر) از دستور import استفاده می‌گردد. در یک درس جداگانه به صورت کامل صحبت خواهد شد ولی برای ادامه این درس تا همین حد بدانید که برای فراخوانی تابع‌های موجود در یک ماژول import شده از الگوی «نام ماژول + نقطه + نام تابع مورد نظر» استفاده می‌گردد - در دستور import پسوند ماژول نوشته نمی‌شود.* -مثالی دیگر - ``sys`` یکی از ماژول‌های مهم پایتون است؛ این ماژول امکان دسترسی به برخی از متغیرهای مورد استفاده مفسر (در زمان اجرا) و تابع‌هایی که با مفسر در ارتباط هستند را فراهم می‌آورد [`اسناد پایتون 3.4 `__]: +مثالی دیگر - ``sys`` یکی از ماژول‌های مهم پایتون است؛ این ماژول امکان دسترسی به برخی از متغیرهای مورد استفاده مفسر (در زمان اجرا) و همچنین تابع‌هایی که با مفسر در ارتباط هستند را فراهم می‌آورد [`اسناد پایتون `__]: .. code-block:: python @@ -151,7 +151,7 @@ دریافت راهنمایی ----------------- -یک از دستورهای پیشنهادی در پیغام ابتدایی حالت تعاملی ``help`` بود که با وارد کردن آن، متن پایین نمایش داده می‌شود:: +یکی از دستورهای پیشنهادی در پیغام ابتدایی حالت تعاملی، ``help`` بود که با وارد کردن آن متن پایین نمایش داده می‌شود:: >>> help Type help() for interactive help, or help(object) for help about object. @@ -159,7 +159,7 @@ به دو روش می‌توان از امکان راهنمایی استفاده کرد که در ادامه بررسی می‌شود. .. note:: - در هر دو روش برای مرور توضیحات طولانی از کلیدهای Enter (سطر به سطر) و Space (صفحه به صفحه) بهره بگیرید و برای خروج از توضیحات نیز از کلید q صفحه کلید استفاده نمایید؛ انتهای توضیحات توسط عبارت ``(END)`` مشخص می‌شود. + در هر دو روش برای مرور توضیحات طولانی از کلیدهای Enter (سطر به سطر) و Space (صفحه به صفحه) بهره بگیرید و برای خروج از توضیحات نیز از کلید q صفحه کلید استفاده نمایید؛ انتهای توضیحات نیز توسط عبارت ``(END)`` مشخص می‌شود. .. rubric:: روش یکم: رفتن به حالت راهنمای تعاملی @@ -170,7 +170,7 @@ Welcome to Python 3.4's help utility! If this is your first time using Python, you should definitely check out - the tutorial on the Internet at http://docs.python.org/3.4/tutorial/. + the tutorial on the Internet at http://docs.python.org/3/tutorial/. Enter the name of any module, keyword, or topic to get help on writing Python programs and using Python modules. To quit this help utility and @@ -408,9 +408,8 @@ می‌توانید با نوشتن مسیر دایرکتوری‌های دلخواه خود درون یک فایل متنی با پسوند ``pth.`` و قرار دادن آن درون دایرکتوری site-packages، این دایرکتوری‌ها را نیز به ``sys.path`` بیافزایید. برای نمونه فایل mypath.pth را (در سیستم عامل گنولینوکس) ایجاد می‌نماییم:: user> cd /usr/local/lib/python3.4/site-packages - user> su - root> touch mypath.pth - root> chmod 777 mypath.pth + user> sudo touch mypath.pth + user> sudo chmod 777 mypath.pth فایل mypath.pth را با یک ویرایشگر متن باز کرده و مشابه پایین فهرست دایرکتوری‌های مورد نظر خود را در آن وارد می‌نماییم:: diff --git a/lessons/l05.rst b/lessons/l05.rst index 360110d..b6ad7c2 100644 --- a/lessons/l05.rst +++ b/lessons/l05.rst @@ -86,7 +86,9 @@ اشیا در پایتون ---------------- -علاوه‌بر اینکه پایتون یک زبان برنامه‌نویسی شی‌گراست، ساختار آن نیز بر مبنای شی‌گرایی توسعه یافته است و اینطور بیان می‌شود که **هر چیزی در پایتون یک شی است**. اشیا، انتزاعِ پایتون برای ارایه «انواع داده‌» (Data Types) هستند. به بیان دیگر تمام داده‌های یک برنامه پایتونی یا به صورت مستقیم یک شی است یا از روابط بین اشیا ایجاد می‌گردد. برای نمونه: ``56``، ``"!Hello World"``، توابع و... حتی خود کلاس‌ها نیز توسط یک نوع شی ارایه می‌شوند. هر شی در پایتون حاوی یک «**شناسه**» (identity)، یک «**نوع**» (type) و یک «**مقدار**» (value) است. +علاوه‌بر اینکه پایتون یک زبان برنامه‌نویسی شی‌گراست، ساختار آن نیز بر مبنای شی‌گرایی توسعه یافته است و اینطور بیان می‌شود که **هر چیزی در پایتون یک شی است**. اشیا، انتزاعِ پایتون برای ارایه «انواع داده‌» (Data Types) هستند. به بیان دیگر تمام داده‌های یک برنامه پایتونی یا به صورت مستقیم یک شی است یا از روابط بین اشیا ایجاد می‌گردد. برای نمونه: ``56``، ``"!Hello World"``، توابع و... حتی خود کلاس‌ها نیز توسط یک نوع شی ارایه می‌شوند. + +هر شی در پایتون حاوی یک «**شناسه**» (identity)، یک «**نوع**» (type) و یک «**مقدار**» (value) است. * «شناسه» در زمان ایجاد شی به آن اختصاص می‌یابد و غیر قابل تغییر است. تابع ``()id`` شناسه شی را به صورت یک عدد صحیح برمی‌گرداند که این مقدار در CPython بیانگر نشانی (Address) شی در حافظه (Memory) است:: @@ -125,7 +127,7 @@ از نسخه 2.2 طراحی کلاس‌ها در پایتون تغییر کرد [`New-style Classes `_] که البته ساختار قدیمی همچنان در نسخه 2x باقی مانده است. [مبنای آموزش در این کتاب طراحی جدید می‌باشد.] -در ساختار جدید مفهوم ”type“ برابر مفهوم ”class“ طراحی شده است. در این ساختار هر کلاس، یک شی از کلاسی به نام ”type“ می‌باشد و تمام کلاس‌ها از کلاسی به نام ”object“ ارث‌بری دارند:: +در ساختار جدید مفهوم ”type“ برابر مفهوم ”class“ طراحی شده است. در این ساختار هر کلاس خود یک شی از کلاسی به نام ”type“ می‌باشد و همچنین تمامی کلاس‌ها از کلاسی به نام ”object“ ارث‌بری دارند:: >>> # Python 3.x diff --git a/lessons/l06.rst b/lessons/l06.rst index 9086342..24a04ca 100644 --- a/lessons/l06.rst +++ b/lessons/l06.rst @@ -10,7 +10,7 @@ در این درس به معرفی اجزای پایه در برنامه‌نویسی پایتون پرداخته شده و اینکه چه هستند، چه گرامری دارند، چه کاری انجام می‌دهند یا... مورد بررسی قرار گرفته است. همچنین در موارد بسیاری نکته‌هایی از شیوه استاندارد پایتون‌نویسی که توسط سند `PEP 8 `__ به برنامه‌نویسان پایتون پیشنهاد می‌شود نیز آورده شده است؛ رعایت این اصول به یکدستی کدهای جامعه پایتون کمک می‌کند. -سینتکس (`Syntax `_ یا دستور زبان) مجموعه‌ای از قواعد است که چگونگی برنامه‌نویسی به یک زبان مشخص را تعریف می‌کند؛ برای نمونه اینکه یک متن چطور نوشته شود که توسط مفسر پایتون به عنوان توضیح در نظر گرفته شود یا یک شی رشته به رعایت سینتکس تعریف شده در پایتون بستگی دارد و چنانچه مفسر نتواند متن را با هیچ قاعده‌ تعریف شده‌ای مطابقت دهد یک خطا گزارش خواهد شد. سینتکس پایتون تنها محدود به این درس نیست و موارد بسیار دیگری به مانند چگونگی تعریف اشیا گوناگون را در طی درس‌های آتی مشاهده خواهید کرد. +سینتکس (`Syntax `_ یا دستور زبان) مجموعه‌ای از قواعد است که چگونگی برنامه‌نویسی به یک زبان مشخص را تعریف می‌کند؛ برای نمونه اینکه یک متن چطور نوشته شود که توسط مفسر پایتون به عنوان توضیح در نظر گرفته شود یا یک شی رشته به رعایت سینتکس تعریف شده در پایتون بستگی دارد و چنانچه مفسر نتواند متن را با هیچ قاعده‌ تعریف شده‌ای مطابقت دهد یک استثنا گزارش خواهد شد. سینتکس پایتون تنها محدود به این درس نیست و موارد بسیار دیگری به مانند چگونگی تعریف اشیا گوناگون را در طی درس‌های آتی مشاهده خواهید کرد. :emoji-size:`✔` سطح: مقدماتی @@ -427,7 +427,7 @@ Docstring باید به عنوان دستور نخست درج گردد و این هر شی شامل یک «**شمارنده ارجاع**» (Reference Counter) نیز هست؛ به این صورت که در هر لحظه تعداد ارجاع‌ها به آن شی را نشان می‌دهد و با هر ارجاع جدید به شی، یک واحد به آن اضافه می‌شود و با حذف هر ارجاع نیز یک واحد کاهش می‌یابد. چنانچه مقدار آن به صفر برسد، شی آن توسط تکنیک ”**Garbage Collection**“ پاک می‌گردد و مقدار حافظه‌ای که توسط شی مصرف شده بود آزاد می‌گردد. برای مشاهده تعداد ارجاع‌ها به یک شی می‌توان از تابع ``()getrefcount`` درون ماژول ``sys`` استفاده کرد [`اسناد پایتون `__]. - ولی مفسر پایتون اعداد صحیح و رشته‌های کوچک را پس از اینکه مقدار شمارنده ارجاع‌ آن‌ها به صفر برسد از حافظه پاک نمی‌کند. هدف از این کار صرفه جویی در هزینه ایجاد این اشیا برای استفاده در آینده است. بنابراین در پاسخ به سوال بالا باید گفت که: شی ``1`` در حافظه باقی می‌ماند. + البته مفسر پایتون اعداد صحیح و رشته‌های کوچک را پس از اینکه مقدار شمارنده ارجاع‌ آن‌ها به صفر برسد از حافظه پاک نمی‌کند. هدف از این کار صرفه جویی در هزینه ایجاد این اشیا برای استفاده در آینده است. بنابراین در پاسخ به سوال بالا باید گفت که: شی ``1`` در حافظه باقی می‌ماند. :: diff --git a/lessons/l11.rst b/lessons/l11.rst new file mode 100644 index 0000000..7992638 --- /dev/null +++ b/lessons/l11.rst @@ -0,0 +1,442 @@ +.. role:: emoji-size + +.. meta:: + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس یازدهم کتابخانه استاندارد + :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, پایتون + + +درس ۱۱: کتابخانه استاندارد (بخش ۱) +==================================== + +کتابخانه استاندارد پایتون مجموعه‌ وسیعی از امکانات آماده است که با نصب پایتون در اختیار قرار می‌گیرد. فهرست کامل این امکانات را می‌توانید از نشانی‌های `(پایتون 2x) `_ و `(پایتون 3x) `_ مشاهده نمایید. لازم به یادآوری است که بخشی بزرگی از قدرت پایتون به دلیل وجود کتابخانه‌های فراوان و قدرتمند آن است که تعداد زیادی از آن‌ها خارج کتابخانه استاندارد پایتون و درون جامعه کاربری آن در حال توسعه هستند که فهرست تقریبا کاملی از آن‌ها نیز توسط `PyPI `_ قابل جستجو و دریافت هستند. + +این درس به عنوان آخرین درس از سطح مقدماتی کتاب به بررسی بخشی از امکان‌های کاربردی این کتابخانه اختصاص یافته است که البته ممکن است در طول درس‌های گذشته از آن‌ها استفاده کرده باشیم!. + + + + + + +:emoji-size:`✔` سطح: مقدماتی + +---- + + +math +------ +این ماژول حاوی ثابت‌ها (Constants) و تابع‌های ریاضی است [`اسناد پایتون `__] که برخی از آن‌ها به شرح پایین است: + +* ``math.pi``: ثابتی حاوی عدد π (`ویکی‌پدیا `__) است [`اسناد پایتون `__]:: + + >>> import math + + >>> math.pi + 3.141592653589793 + >>> + +* ``math.e``: ثابتی حاوی عدد e (`ویکی‌پدیا `__) است [`اسناد پایتون `__]:: + + >>> import math + + >>> math.e + 2.718281828459045 + >>> + +* ``math.inf``: از نسخه 3.5 به بعد - ثابتی حاوی مقدار مثبت بی‌نهایت (Positive infinity) است که این مقدار برابر با خروجی تابع ``('float('inf`` می‌باشد. ``math.inf-`` نیز برابر منفی بی‌نهایت است [`اسناد پایتون `__]. + + برای بررسی inf بودن (مثبت یا منفی) از تابع ``(math.isinf(x`` [`اسناد پایتون `__] استفاده می‌شود:: + + >>> import math + + >>> a = math.inf + >>> b = 10 + >>> a > b + True + + >>> math.isinf(a) + True + >>> math.isinf(b) + False + >>> + +* ``math.nan``: از نسخه 3.5 به بعد - ثابتی حاوی مقدار «تعریف نشده» یا NaN - اختصار Not a Number (`ویکی‌پدیا `__) - می‌باشد که این مقدار برابر با خروجی تابع ``('float('nan`` است [`اسناد پایتون `__]. + + برای بررسی nan بودن از تابع ``(math.isnan(x`` [`اسناد پایتون `__] استفاده می‌شود:: + + >>> import math + + >>> a = math.nan + >>> a + nan + + >>> math.isnan(a) + True + >>> + + +* ``(math.ceil(x``: کوچکترین عدد صحیحی که بزرگتر یا مساوی با عدد ``x`` باشد را برمی‌گرداند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.ceil(4) + 4 + >>> math.ceil(-4.17) + -4 + >>> math.ceil(4.17) + 5 + >>> + +* ``(math.floor(x``: بزرگترین عدد صحیحی که کوچکتر یا مساوی با عدد ``x`` باشد را برمی‌گرداند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.floor(4) + 4 + >>> math.floor(-4.17) + -5 + >>> math.floor(4.17) + 4 + >>> + +* ``(math.fabs(x``: همانند تابع آماده ``()abs`` [`اسناد پایتون `__] مقدار قدر مطلق (`ویکی‌پدیا `__) عدد ``x`` را برمی‌گرداند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.fabs(-4.17) + 4.17 + >>> math.fabs(-4) + 4.0 + >>> math.fabs(4) + 4.0 + >>> + +* ``(math.factorial(x``: مقدار فاکتوریل (`ویکی‌پدیا `__) عدد x را برمی‌گرداند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.factorial(5) + 120 + >>> + +* ``(math.exp(x``: حاصل ``e**x`` (`ویکی‌پدیا `__) را برمی‌گرداند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.exp(3) + 20.085536923187668 + >>> + +* ``(math.log(x[, base]``: حاصل لگاریتم (Logarithm) عدد x در پایه base را برمی‌گرداند؛ آرگومان base اختیاری است و چنانچه ذکر نگردد به صورت پیش‌فرض حاصل لگاریتم عدد x در پایه عدد e یا همان لگاریتم طبیعی (`ویکی‌پدیا `__) برگردانده می‌شود [`اسناد پایتون `__]:: + + >>> import math + + >>> math.log(math.e) # ln e == 1 + 1.0 + >>> math.log(1) # ln 1 == 0 + 0.0 + >>> + + :: + + >>> math.log(8, 2) # 2**3 == 8 + 3.0 + >>> math.log(100, 10) # 10**2 == 100 + 2.0 + >>> math.log(81, 3) # 3**4 == 81 + 4.0 + >>> math.log(2, 10) + 0.30102999566398114 + >>> + + برای سادگی استفاده در محاسبه‌های ریاضی دو تابع ``(log10(x`` [`اسناد پایتون `__] - محاسبه لگاریتم عدد x در پایه عدد 10 - و ``(log2(x`` [`اسناد پایتون `__] - محاسبه لگاریتم عدد x در پایه عدد 2؛ که از نسخه 3.3 به بعد اضافه شده است - نیز در دسترس هستند:: + + >>> math.log10(100) + 2.0 + >>> math.log2(8) + 3.0 + >>> + + +* ``(math.sqrt(x``: ریشه دوم (Square root) یا همان جذر (`ویکی‌پدیا `__)‌ عدد x را برمی‌گرداند [`اسناد پایتون `__]:: + + + >>> import math + + >>> math.sqrt(4) + 2.0 + >>> + +* ``(math.pow(x, y``: عدد x را به توان عدد y می‌رساند و حاصل را برمی‌گرداند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.pow(3, 2) + 9.0 + + این تابع هر دو آرگومان خود را به نوع float تبدیل می‌کند؛ چنانچه می‌خواهید با اعداد صحیح کار کنید، از عملگر ``**`` یا تابع آماده ``()pow`` [`اسناد پایتون `__] استفاده نمایید:: + + >>> 3**2 + 9 + >>> pow(3, 2) + 9 + + +* توابع مثلثاتی (Trigonometric functions) [`اسناد پایتون `__]: ``(cos(x`` و ``(sin(x`` و ``(tan(x`` و ``(acos(x`` و ``(asin(x`` و ``(atan(x`` که در تمام آن‌ها زاویه x بر حسب **رادیان (Radian)** است:: + + >>> import math + + >>> math.cos(0) + 1.0 + >>> math.sin(0) + 0.0 + >>> math.tan(0) + 0.0 + >>> + +* ``(math.degrees(x``: زاویه x را از رادیان به **درجه** تبدیل می‌کند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.degrees(0) + 0.0 + +* ``(math.radians(x``: زاویه x را از درجه به **رادیان** تبدیل می‌کند [`اسناد پایتون `__]:: + + >>> import math + + >>> math.degrees(0) + 0.0 + >>> math.radians(30) + 0.5235987755982988 + + :: + + >>> math.sin(math.radians(90)) + 1.0 + +* توابع هذلولی (Hyperbolic functions) [`اسناد پایتون `__]: ``(cosh(x`` و ``(sinh(x`` و ``(tanh(x`` و ``(acosh(x`` و ``(asinh(x`` و ``(atanh(x``. + + +os +----- +این ماژول امکان استفاده از برخی قابلیت‌های وابسته به سیستم عامل را فراهم می‌آورد؛ مانند گرفتن مسیر دایرکتوری برنامه [`اسناد پایتون `_]. برخی از تابع‌های موجود در این ماژول به شرح پایین است: + +* ``os.environ``: یک شی از نوع نگاشت - مانند نوع دیکشنری [به درس هشتم رجوع شود] - است که حاوی متغیرهای محیطی سیستم عامل می‌باشد [`اسناد پایتون `__] + + باید توجه داشت که مقدار این دستور متناسب با لحظه‌ای از سیستم عامل است که ماژول ``os`` به اسکریپت import شده است و شامل متغیرهایی که پس از این لحظه ایجاد شده باشند نمی‌شود. + + :: + + + >>> # Python 3.x, GNU/Linux + + >>> import os + >>> os.environ + environ({'LOGNAME': 'saeid', 'PWD': '/home/saeid', '_': '/usr/bin/python3', 'LANG': 'en_US.UTF-8', 'PATH': '/usr/local/sbin:/usr/local/bin:/usr/bin', 'ZSH': '/home/saeid/.oh-my-zsh'}) + >>> + + :: + + >>> os.environ['PATH'] + '/usr/local/sbin:/usr/local/bin:/usr/bin' + + >>> os.environ['LANG'] + 'en_US.UTF-8' + + +* ``()os.getcwd``: مسیر دایرکتوری جاری (Current Working Directory)‌ را برمی‌گرداند. خروجی این تابع برابر با دستور ``pwd`` در خط فرمان گنولینوکس یا ``%echo %CD`` در خط فرمان ویندوز می‌باشد. [`اسناد پایتون `__]:: + + # Python 3.x, GNU/Linux + + ~ pwd + /home/saeid + + :: + + >>> python3 -q + >>> import os + >>> os.getcwd() + '/home/saeid' + >>> + + +* ``(os.chdir(path``: مسیر دایرکتوری جاری را به مسیر آرگومان دریافتی path تغییر می‌دهد. عملکرد این تابع برابر با دستور ``cd`` در خط فرمان‌های گنولینوکس و ویندوز است. [`اسناد پایتون `__]:: + + >>> import os + + >>> os.getcwd() + '/home/saeid' + + >>> os.chdir('/etc') + + >>> os.getcwd() + '/etc' + +* ``(os.listdir(path``: یک شی لیست که شامل محتویات درون دایرکتوری path است را برمی‌گرداند. چنانچه آرگومان path ارسال نشود به صورت پیش‌فرض مسیر دایرکتوری جاری در نظر گرفته می‌شود. [`اسناد پایتون `__] :: + + >>> import os + >>> os.listdir('/home/saeid/Pictures') + ['scan0001.jpg', 'smplayer_screenshots', 'GNU.png', 'Wallpapers'] + + +* ``(os.mkdir(path``: یک دایرکتوری که نام کامل آن توسط آرگومان path تعیین شده است را ایجاد می‌کند. در صورتی که این دایرکتوری از قبل موجود باشد یک استثنا ``FileExistsError`` رخ می‌دهد. [`اسناد پایتون `__]:: + + >>> import os + >>> os.mkdir('dir1') + + در نمونه کد بالا از آنجا که مسیر دایرکتوری ذکر نشده است؛ دایرکتوری dir1 به صورت پبش فرض در مسیر دایرکتوری جاری (که در اینجا: ``/home/saeid/`` است) ایجاد می‌گردد؛ همین امر باعث بروز استثنا با اجرای دستور پایین می‌شود:: + + >>> os.mkdir('/home/saeid/dir1') + Traceback (most recent call last): + File "", line 1, in + FileExistsError: [Errno 17] File exists: '/home/saeid/dir1' + + + + :: + + >>> os.mkdir('/home/saeid/Documents/dir2') + + *نمونه کد بالا موجب ایجاد دایرکتوری dir2 درون مسیر دایرکتوری Documents می‌شود.* + + مسیر دایرکتوری می‌بایست به صورت صحیح وارد شود؛ در نمونه کد پایین نیز به همین دلیل که دایرکتوری dir3 وجود ندارد، استثنایی رخ داده است. + + :: + + >>> os.mkdir('/home/saeid/Documents/dir3/dir4') + Traceback (most recent call last): + File "", line 1, in + FileNotFoundError: [Errno 2] No such file or directory: '/home/saeid/Documents/dir3/dir4' + + +* ``(os.makedirs(path``: همانند ``(os.mkdir(path`` است ولی با این تفاوت که تمامی دایرکتوری‌های میانی مورد نیاز را هم ایجاد می‌کند. [`اسناد پایتون `__] + + *در نمونه کد پایین برای ایجاد دایرکتوری dir5 دایرکتوری‌های dir3 و dir4 - که البته وجود ندارند - نیز ایجاد می‌گردند.* + + :: + + >>> import os + >>> os.makedirs('/home/saeid/Documents/dir3/dir4/dir5') + +* ``(os.rmdir(path``: دایرکتوری مشخص شده توسط آرگومان path را حذف می‌کند. این دایرکتوری می‌بایست خالی باشد در غیر این صورت یک استثنا ``OSError`` رخ می‌دهد. [`اسناد پایتون `__] + + + همچنین برای حذف کامل یک دایرکتوری به همراه تمام محتویات آن می‌توانید از تابع ``(rmtree(path`` درون ماژول ``shutil`` [`اسناد پایتون `__] استفاده نمایید:: + + >>> import shutil + >>> shutil.rmtree("/home/saeid/Documents/dir1") + + +* ``(os.removedirs(path``: همانند ``(os.rmdir(path`` است ولی با این تفاوت که عملکردی بازگشتی دارد و تا زمانی که خطایی رخ نداده دایرکتوری‌های مشخص شده در آرگومان path را یکی یکی حذف می‌کند. [`اسناد پایتون `__] :: + + >>> import os + >>> os.removedirs('/home/dir1/dir2/dir3') + + در نمونه کد بالا ابتدا دایرکتوری dir3 (با مسیر ``'home/dir1/dir2/dir3/'``) حذف می‌شود - البته اگر خالی باشد - و بعد از آن برای حذف دایرکتوری dir2 (با مسیر ``'home/dir1/dir2/'``) تلاش می‌شود که اگر آن‌هم خالی باشد و حذف گردد، روند حذف به همین شکل برای باقی مسیر ادامه می‌یابد. + +* ``(os.rename(src, dst``: این تابع برای تغییر نام یک فایل یا دایرکتوری کاربرد دارد. آرگومان ``src`` نام اصلی و آرگومان ``dst`` نیز نام جدید برای فایل یا دایرکتوری مورد نظر می‌باشند [`اسناد پایتون `__]:: + + >>> import os + >>> os.getcwd() + '/home/saeid/Documents/dir' + >>> os.listdir(os.getcwd()) + ['fontsdir', 'index.html', 'style.css'] + + >>> os.rename("fontsdir", "_fonts") + + >>> os.listdir(os.getcwd()) + ['index.html', 'style.css', '_fonts'] + + توجه داشته باشید چنانچه فایل یا دایرکتوری موردنظر در مسیری دیگری از مسیر دایرکتوری جاری باشد؛ لازم است نام به شکل کامل (همراه با مسیر) ذکر گردد. همچنین بدیهی است که تغییر مسیر در آرگومان ``dst`` موجب عمل انتقال (Move) می‌شود:: + + >>> import os + >>> os.getcwd() + '/home/saeid/Documents/dir/dir1' + >>> os.listdir(os.getcwd()) + ['index.html', 'style.css', '_fonts'] + + >>> os.rename("_fonts", "/home/saeid/Documents/dir/dir2/_fonts") + + >>> os.listdir(os.getcwd()) + ['index.html', 'style.css'] + + >>> os.chdir('/home/saeid/Documents/dir/dir2') + >>> os.listdir(os.getcwd()) + ['_fonts'] + + در گنولینوکس چنانچه بخواهیم نام فایلی به یک نام از پیش موجود تغییر داده شود؛‌ [در صورتی که کاربر نیز اجازه دسترسی (Permission) لازم را داشته باشد] یک عمل جایگزینی (Replace) صورت می‌گیرد، ولی برای چنین مواقعی در سیستم عامل ویندوز یک خطای ``OSError`` رخ خواهد داد. رویداد این ماجرا در هنگام تغییر نام یک دایرکتوری، باعث بروز خطای ``OSError`` در هر دو سیستم عامل می‌شود. + + +* ``(os.renames(old, new``: عملکردی مشابه با تابع ``()rename`` دارد با این تفاوت که اگر دایرکتورهای میانی از مسیر آرگومان ``new``، وجود نداشته باشند، آن‌ها را نیز ایجاد می‌کند [`اسناد پایتون `__]:: + + >>> import os + >>> os.getcwd() + '/home/saeid/Documents/dir' + >>> os.listdir(os.getcwd()) + ['index.html', 'style.css', '_fonts', 'js'] + + >>> os.renames("style.css", "css/style.css") + + >>> os.listdir(os.getcwd()) + ['index.html', 'css', '_fonts', 'js'] + + +* ``(os.walk(rootdirpath``: مسیر یک دایرکتوری را به عنوان دایرکتوری ریشه پیمایش می‌کند و مسیر هر دایرکتوری را که می‌بیند به همراه نام دایرکتوری‌ها و فایل‌های درون آن برمی‌گرداند. [`اسناد پایتون `__]:: + + dir1 + ├── dir2 + │   └── file21 + ├── file11 + └── file12 + + :: + + >>> import os + + >>> tuple(os.walk('/home/saeid/Documents/dir1')) + (('/home/saeid/Documents/dir1', ['dir2'], ['file12', 'file11']), ('/home/saeid/Documents/dir1/dir2', [], ['file21'])) + + + :: + + >>> import os + + >>> for root, dirs, files in os.walk('/home/saeid/Documents/dir1'): + ... print('Found directory: {}'.format(root)) + ... for filename in files: + ... print('\t{}'.format(filename)) + ... + Found directory: /home/saeid/Documents/dir1 + file12 + file11 + Found directory: /home/saeid/Documents/dir1/dir2 + file21 + >>> + + جهت پیمایش دایرکتوری‌ها به صورت پیش‌فرض از بالا (دایرکتوری ریشه) به پایین است که می‌توان با ``False`` قرار دادن آرگومان اختیاری ``topdown`` آن را معکوس نمود:: + + >>> for root, dirs, files in os.walk('/home/saeid/Documents/dir1', topdown=False): + ... print('Found directory: {}'.format(root)) + ... for filename in files: + ... print('\t{}'.format(filename)) + ... + Found directory: /home/saeid/Documents/dir1/dir2 + file21 + Found directory: /home/saeid/Documents/dir1 + file12 + file11 + >>> + + + + + +| + +---- + +:emoji-size:`😊` امیدوارم مفید بوده باشه + +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ + + diff --git a/log.rst b/log.rst index b171957..9386328 100644 --- a/log.rst +++ b/log.rst @@ -2,13 +2,24 @@ .. meta:: - :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - صفحه گزارش رویداد‌ها + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - صفحه گزارش توسعه :keywords: پایتون, آموزش, آموزش برنامه نویسی, آموزش پایتون, برنامه نویسی, کتاب آموزش, آموزش فارسی, کتاب آزاد -گزارش رویداد‌ها -================ +گزارش توسعه +============= +.. raw:: html + +

00108 - یک‌شنبه ۲۱ آذر ۱۳۹۵

+ +ببخشید؛ بابت تاخیر بسیار طولانی در بروزرسانی کتاب. درس یازدهم با عنوان «کتابخانه استاندارد (بخش ۱)» به فهرست کتاب افزوده شد. + +* بخش پیش‌گفتار ایجاد گردید. +* پاراگراف‌هایی از دروس گذشته اصلاح گردید. +* فونت قالب به «بهداد» تغییر داده شد. + +---- .. raw:: html diff --git a/preface.rst b/preface.rst new file mode 100644 index 0000000..cf875d2 --- /dev/null +++ b/preface.rst @@ -0,0 +1,15 @@ +پیش‌گفتار +========== + +آنچه در این کتاب نوشته می‌شود حاصل یادگیری‌های شخصی از منابع مختلف در دسترس مرتبط با آموزش پایتون می‌باشد؛ یک یادداشت شخصی ولی منسجم! که سعی می‌شه منطبق با مستندات اصلی زبان برنامه‌نویسی پایتون باشد. + +---- + +زیربنا: + +* `Python `_ +* `Sphinx `_ +* `Minoo Theme `_ +* `Behdad Font `_ +* `Read the Docs `_ + diff --git a/requirements.txt b/requirements.txt index e69de29..6e197f9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1 @@ +khayyam From 6e253b9e655ac05570962d16c07203202ffe2501 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Mon, 16 Jan 2017 21:44:37 +0330 Subject: [PATCH 004/316] set iwmf link --- index.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/index.rst b/index.rst index f9eaffa..23f5a9d 100644 --- a/index.rst +++ b/index.rst @@ -35,5 +35,20 @@ +.. raw:: html + + + لوگوی جشنواره وب و موبایل ایران + + + + From d10bc08585d8448038fecf58852b03881b009a9a Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Mon, 16 Jan 2017 22:17:33 +0330 Subject: [PATCH 005/316] add donate link --- .../sphinx_minoo_theme/includes/top.html | 5 + .../sphinx_minoo_theme/static/minoo-ltr.css~ | 224 ----------------- .../sphinx_minoo_theme/static/minoo-rtl.css | 4 +- .../sphinx_minoo_theme/static/minoo-rtl.css~ | 235 ------------------ index.rst | 13 +- requirements.txt | 1 - 6 files changed, 20 insertions(+), 462 deletions(-) delete mode 100644 _templates/sphinx_minoo_theme/static/minoo-ltr.css~ delete mode 100644 _templates/sphinx_minoo_theme/static/minoo-rtl.css~ diff --git a/_templates/sphinx_minoo_theme/includes/top.html b/_templates/sphinx_minoo_theme/includes/top.html index 09dda2d..e6a862e 100644 --- a/_templates/sphinx_minoo_theme/includes/top.html +++ b/_templates/sphinx_minoo_theme/includes/top.html @@ -24,3 +24,8 @@ {% endif %} {% endif %} + diff --git a/_templates/sphinx_minoo_theme/static/minoo-ltr.css~ b/_templates/sphinx_minoo_theme/static/minoo-ltr.css~ deleted file mode 100644 index 18b5cf1..0000000 --- a/_templates/sphinx_minoo_theme/static/minoo-ltr.css~ +++ /dev/null @@ -1,224 +0,0 @@ - -/* colors guide: -theme[first:5C6BC0,second:E8EAF6,hover:66BB6A] -font[main:212121,title:FFFFFF,footnote:616161,headers:000000] -code[background:424242,text:FAFAFA] -highlighted[background:FDD835,text:212121] -list[purple:[title:AB47BC,sub:CE93D8]-green:[title:66BB6A,sub:A5D6A7]-blue[title:5C6BC0,sub:9FA8DA]] -box[note,attention[body:90CAF9,title:42A5F5]-tip,important[body:80CBC4,title:26A69A]-hint,warning[body:FFAB91,title:FF7043]-error,danger[body:EF9A9A,title:EF5350]-caution[body:C5E1A5,title:9CCC65]-admonition[body:B0BEC5,title:78909C]] -*/ - -/* sphinx_rtd_theme fonts */ -@font-face{font-family:"Inconsolata";font-style:normal;font-weight:400;src:local("Inconsolata"),url(fonts/Inconsolata.ttf) format("truetype")}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:700;src:local("Inconsolata Bold"),local("Inconsolata-Bold"),url(fonts/Inconsolata-Bold.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:400;src:local("Lato Regular"),local("Lato-Regular"),url(fonts/Lato-Regular.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:700;src:local("Lato Bold"),local("Lato-Bold"),url(fonts/Lato-Bold.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:local("Roboto Slab Regular"),local("RobotoSlab-Regular"),url(fonts/RobotoSlab-Regular.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:local("Roboto Slab Bold"),local("RobotoSlab-Bold"),url(fonts/RobotoSlab-Bold.ttf) format("truetype")} - -/* HTML elements */ -body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#212121;min-height:100%;font-size:16px;overflow-x:hidden} -html{height:100%} -a,ul>li>a,ol>li>a{text-decoration:none!important;color:#5C6BC0;padding:0} -a:hover,ul>li>a:hover,ol>li>a:hover{color:#66BB6A} -i{vertical-align:middle} -h1,h2,h3,h4,h5,h6{font-weight:bold;color:#000000;display:inline-block} -h1,h2{padding:10px 0 10px 15px} -h1{background-color:#5C6BC0;color:#FFFFFF;line-height:26px;border-left:5px #E8EAF6 solid} -p{line-height:24px;margin:0;font-size:16px} -h1{font-size:175%} -h2{font-size:150%} -h3{font-size:125%} -h4{font-size:115%} -h5{font-size:110%} -h6{font-size:100%} -hr{margin-top:0;border-top:1px #E8EAF6 solid} -blockquote{border-left:none;padding:0;margin:0 0 0 24px} -th{text-align:left} -td,th{vertical-align:top} -thead{background-color:#5C6BC0;color:#FFFFFF} -caption{text-align:center;color:#212121;padding:8px 24px;background-color:#E8EAF6} -code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:12px} -code,kbd,samp{padding:2px 6px;white-space:pre} -pre{margin:0;overflow-wrap:normal} -ul,ol{padding-left:24px} -ul li{list-style:disc;margin-top:1px} -dl dt{font-weight:bold} -dl dd{margin:0 0 12px 24px} - -/* theme */ -#page{padding:0;margin:0;height:100%} -#page.toggled{padding-left:300px} -#page-body{width:100%;position:relative;padding-left:32px;visibility:visible} -@media(min-width:768px){#page.toggled #page-body{position:relative;padding-left:0}} -@media(max-width:768px){#page.toggled #page-body{visibility:hidden}#page.toggled{padding-left:0}#page.toggled .back-to-top{display:none !important}} -#page-sidebar{width:300px;min-height:100%;background-color:#5C6BC0;overflow:hidden;float:left} -#wrapper-page-sidebar{z-index:1000;position:fixed;width:300px;min-height:100%;background-color:#5C6BC0;left:-300px;} -#sidebar-top{width:300px;top:0!important;left:-300px;position:fixed;z-index:1000;background-color:#5C6BC0} -#page.toggled #sidebar-top,#page.toggled #wrapper-sidebar-bottom,#page.toggled #wrapper-page-sidebar{left:0} -#page,#wrapper-page-sidebar,#page-sidebar,#sidebar-top,#sidebar-bottom-versions,#wrapper-sidebar-bottom,#sidebar-bottom-versions{-webkit-transition:all 0.5s ease;-moz-transition:all 0.5s ease;-o-transition:all 0.5s ease;-ms-transition:all 0.5s ease;transition:all 0.5s ease} -#sidebar-top-image{width:300px;height:96px;display:block;text-align:center} -#sidebar-top-image>span{width:86px;height:86px;background-repeat:no-repeat;background-size:cover;border:4px solid #E8EAF6;display:inline-block;margin-top:5px;-webkit-box-shadow:0 0 0 1px rgba(232,234,246,1);-moz-box-shadow:0 0 0 1px rgba(232,234,246,1);box-shadow:0 0 0 1px rgba(232,234,246,1)} -#sidebar-top-links{width:300px;height:34px;display:block;text-align:center} -#sidebar-top-links>a{display:inline-block;color: #E8EAF6} -#sidebar-top-links>a:hover{color:#66BB6A} -#sidebar-navigation{width:332px;height:52px;background-color:#5C6BC0;display:block;line-height:28px} -#page.toggled #sidebar-navigation{background-color:#E8EAF6;width:300px} -#navigation-toggle{width:32px;height:52px;color:#FFFFFF;cursor:pointer;float:right;padding:0 8px;display:inline-block;background-color:#5C6BC0} -#navigation-toggle>i{margin-top:12px} -#page.toggled #navigation-toggle{background-color:#66BB6A} -#navigation-search{width:268px;position:absolute;padding:2px 8px;display:inline-block;right:32px} -#input-search{width:100%;background-color:transparent;padding:3px 10px;font-size:13px;color:#212121;border:none;box-shadow:inset 0 -1px 0 #5C6BC0} -#input-search:focus{outline:0;box-shadow:inset 0 -1px 0 #66BB6A} -#sidebar-top-title{width:300px;height:auto;text-align:center;padding:10px;display:inline-block} -#sidebar-top-title>a{color:#E8EAF6;font-weight:bold} -#sidebar-top-title>a:hover{color:#66BB6A} -#sidebar-bottom{width:300px;padding:0 10px;display:inline-block;background-color:#5C6BC0;overflow-y:auto;overflow-x:hidden} -#sidebar-bottom-list{width:100%;display:inline-block;min-height:100%;clear:both} -#wrapper-sidebar-bottom{left:-300px;position:fixed;z-index:1000;min-height:100%;width:300px;background-color:#5C6BC0} -#body-content{margin-right:auto;margin-left:auto;} -#body-top{width:100%;height:auto;padding:10px 0;display:inline-block;color:#5C6BC0;border-bottom:3px #E8EAF6 solid;margin-bottom:24px} -#body-top>a{display:inline-block;height:auto;vertical-align:bottom;height:28px} -#body-top>a:hover{color:#66BB6A} -#body-top>span{width:auto;height:28px;line-height:16px;display:inline-block;vertical-align:bottom} -#body-top>a>i,#body-top>span>i{display:inline-block} -#top-src{float:right} -.top-src{float:right;margin-left:24px} -@media(max-width:768px){#top-src{display:none!important}} -#body-btn{width:100%;height:100px;padding:28px 0;border-top:3px #E8EAF6 solid;line-height:30px;display:block} -#body-btn>a{width:auto;height:auto;display:inline-block;padding:5px 8px;color:#FFFFFF;background-color:#5C6BC0} -#body-btn>a:hover{background-color:#66BB6A} -#body-btn>a>i{height:22px;display:inline-block;vertical-align:middle} -#body-footer{width:100%;height:auto;padding:10px 0;background-color:#E8EAF6;line-height:30px;display:block;margin:0 0 24px 0} -#body-footer>p{text-align:center;margin-bottom:0} -.back-to-top{margin:10px;position:fixed;bottom:0;right:0;width:28px;height:28px;z-index:100;display:none;color:#66BB6A;cursor:pointer;opacity:0.7} -.back-to-top:hover{opacity:1} -.back-to-top>i{font-size:32px;line-height:28px;vertical-align:top} -@media print{a[href^="http://"]:after,a[href^="https://"]:after{content:""}pre{overflow-wrap:break-word}#page-sidebar,.back-to-top,#body-footer,#body-btn,#top-src,#wrapper-page-sidebar{display:none;}pre,blockquote,tr,img,p.caption,h2,h3{page-break-inside:avoid}thead{display:table-header-group}img{max-width:100%!important}@page{margin:0.5cm}p,h2,h3,p.caption{orphans:3;widows:3}} - -/* common */ -.fa{font-size:19px} -.admonition,.figure,.h-scroll,.highlight,.table-responsive,table.field-list,dl,img,h1,h2,h3,h4,h5,h6,p,hr,ol,ul,ul.search>li,.contents.topic,.line-block,blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child,blockquote,table.hlist,table.docutils.footnote,table.docutils.citation,ol ol,ol ul,ul ol,ul ul{margin-bottom:24px} -.margin-b-z,ul li p:last-child,.figure img,.table,.last .highlight,.hlist ul,div[class^='highlight'] .table-responsive{margin-bottom:0} -.table{display:inline-block;width:auto;max-width:none;white-space:nowrap} -.code{width:100%} -p.caption,h1,h2,h3,h4,h5,h6,table{margin-top:0} -.align-left{text-align:left} -.align-center{text-align:center} -.align-right{text-align:right} -.table-striped>tbody>tr:nth-of-type(odd){background-color:#E8EAF6} -.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #E8EAF6} -.table-bordered{border:0} -.alert,.btn{border-radius:0} -.img-responsive{display:inline} - -/* reST */ -.line-block{margin-left:24px} -.toc-backref{color:#000000} -.highlighttable{direction:ltr;overflow:hidden} -div[class^='highlight']{overflow-x:auto;direction:ltr} -div[class^='highlight'] td.code{width:100%} -div[class^='highlight-'] .highlight,div[class^='last highlight-'] .highlight{margin-bottom:0} -a.headerlink{visibility:hidden;content:none} -h3:hover a.headerlink:before,caption:hover a.headerlink:before{font-family:FontAwesome;visibility:visible;display:inline-block;content:"\f13d";font-size:13px;color:#66BB6A;margin-left:5px;height:10px} -h1:hover a.headerlink:before,h2:hover a.headerlink:before{font-family:FontAwesome;visibility:visible;display:inline-block;content:"\f13d";font-size:13px;color:#FFFFFF;margin-left:5px;height:10px} -p.rubric{margin-bottom:12px;font-weight:bold} -.container{padding-right:0;padding-left:0;margin:0 0 24px 0;width:100%} -.linenodiv pre{border-left:0;background-color:#5C6BC0;color:#FFFFFF} -.linenos{margin-bottom:24px;vertical-align:top} -.topic-title{font-weight:bold;margin-bottom:12px} -.highlighted{background:#FDD835;display:inline-block;font-weight:bold;padding:0 4px;color:#212121} -table.field-list{border:none;white-space:normal} -table.field-list .field-name{padding-right:0;text-align:left} -table.field-list .field-body{padding-left:0;text-align:left} -table.field-list th,table.field-list td{width:auto!important} -.footnote-reference,.citation-reference{vertical-align:super;font-size:90%} -.table.docutils.footnote tr,.table.docutils.citation tr{background:none;color:#616161} -table.docutils.citation tr td,table.docutils.footnote tr td{border:none} -table.docutils.footnote td,table.docutils.footnote th,table.docutils.citation td,table.docutils.citation th,table.field-list th,table.field-list td{margin:0;padding:3px 6px!important;font-size:90%;overflow:visible;width:100%} -table.docutils.footnote{white-space:normal} -.toctree-wrapper li,.contents.topic ul li,#sidebar-bottom-list #tree-toc ul li{list-style:none} -.toctree-wrapper li>ul{padding:0;margin:0 0 0 24px} -.toctree-wrapper li>a{background-color:#AB47BC;color:#FFFFFF;line-height:26px;border-left:0} -.toctree-wrapper li>ul>li>a{background-color:#CE93D8} -.toctree-wrapper li>a:hover{border-left:5px #CE93D8 solid} -.toctree-wrapper li>ul>li>a:hover{border-left:5px #AB47BC solid} -.toctree-wrapper li>a:hover,.contents.topic li>a:hover{color:#FFFFFF} -.contents.topic li>a{background-color:#5C6BC0;color:#FFFFFF;padding:3px 10px;line-height:26px;border-left:0} -.contents.topic li>ul>li>a{background-color:#9FA8DA} -.contents.topic li>a:hover{border-left:5px #9FA8DA solid} -.contents.topic li>ul>li>a:hover{border-left:5px #5C6BC0 solid} -#sidebar-bottom-list #tree-toc{margin-top:10px;margin-bottom:20px;width:280px;min-height:100%} -#sidebar-bottom-list #tree-toc ul{padding:0;margin:0 0 0 24px} -#sidebar-bottom-list #tree-toc ul li>a,#sidebar-bottom-list #tree-toc ul li.current>a{line-height:26px;border-left:0} -#sidebar-bottom-list #tree-toc ul li>a{color:#212121;background-color:#E8EAF6} -#sidebar-bottom-list #tree-toc ul li.current>a,h2{color:#FFFFFF;background-color:#66BB6A} -h2{border-left:5px #E8EAF6 solid !important} -#sidebar-bottom-list #tree-toc ul li>ul>li>a{color:#FFFFFF;background-color:#A5D6A7} -#sidebar-bottom-list #tree-toc ul li>a:hover{border-left:5px #66BB6A solid;color:#212121} -#sidebar-bottom-list #tree-toc ul li.current>a:hover{border-left:5px #E8EAF6 solid;color:#FFFFFF} -#sidebar-bottom-list #tree-toc ul li>ul>li>a:hover{border-left:5px #E8EAF6 solid;color:#FFFFFF} -#sidebar-bottom-list #tree-toc ul li.current>ul>li>a:hover{color:#FFFFFF} -#sidebar-bottom-list #tree-toc li a,.toctree-wrapper li>a,.contents.topic li>a{display:inline-block;margin:0;padding:2px 10px} -#sidebar-bottom-list #tree-toc li,.toctree-wrapper li,.contents.topic li{margin-top:1px} -#sidebar-bottom-list #tree-toc li.toctree-l1 i,.toctree-wrapper li.toctree-l1 i{margin-left:-24px; margin-right:9px;display:inline-block;vertical-align:top;padding-top:5px;cursor:pointer;color:#E8EAF6} -.toctree-wrapper li.toctree-l1 i{color:#CE93D8!important} -#sidebar-bottom-list #tree-toc li.toctree-l1 i:hover{color:#66BB6A} -.toctree-wrapper li.toctree-l1 i:hover{color:#AB47BC!important} -.admonition{display:inline-block;width:100%;padding:12px} -.admonition-title{color:#FFFFFF;margin:-12px;padding:6px 12px} -.note .admonition-title,.tip .admonition-title,.hint .admonition-title,.attention .admonition-title,.important .admonitionpri-title,.warning .admonition-title,.error .admonition-title,.danger .admonition-title,.caution .admonition-title,.admonition .admonition-title{font-weight:bold;margin-bottom:12px} -.note .admonition-title:before,.tip .admonition-title:before,.hint .admonition-title:before,.attention .admonition-title:before,.important .admonition-title:before,.warning .admonition-title:before,.error .admonition-title:before,.danger .admonition-title:before,.caution .admonition-title:before,.admonition .admonition-title:before{margin-right:5px} -.admonition.note,.admonition.attention{background-color:#90CAF9} -.admonition.note .admonition-title,.admonition.attention .admonition-title{background-color:#42A5F5} -.admonition.note .admonition-title:before{font-family:FontAwesome;content:"\f12a"} -.admonition.attention .admonition-title:before{font-family:FontAwesome;content:"\f0e7"} -.admonition.tip,.admonition.important{background-color:#80CBC4} -.admonition.tip .admonition-title,.admonition.important .admonition-title{background-color:#26A69A} -.admonition.tip .admonition-title:before{font-family:FontAwesome;content:"\f0eb"} -.admonition.important .admonition-title:before{font-family:FontAwesome;content:"\f0a3"} -.admonition.hint,.admonition.warning{background-color:#FFAB91} -.admonition.hint .admonition-title,.admonition.warning .admonition-title{background-color:#FF7043} -.admonition.hint .admonition-title:before{font-family:FontAwesome;content:"\f075"} -.admonition.warning .admonition-title:before{font-family:FontAwesome;content:"\f071"} -.admonition.error,.admonition.danger{background-color:#EF9A9A} -.admonition.error .admonition-title,.admonition.danger .admonition-title{background-color:#EF5350} -.admonition.error .admonition-title:before{font-family:FontAwesome;content:"\f05e"} -.admonition.danger .admonition-title:before{font-family:FontAwesome;content:"\f1e2"} -.admonition.caution{background-color:#C5E1A5} -.admonition.caution .admonition-title{background-color:#9CCC65} -.admonition.caution .admonition-title:before{font-family:FontAwesome;content:"\f06e"} -.admonition{background-color:#B0BEC5} -.admonition .admonition-title{background-color:#78909C} -.admonition .admonition-title:before{font-family:FontAwesome;content:"\f040"} -img.align-left,.figure.align-left,object.align-left{clear:left;float:left;margin-right:1em} -img.align-right,.figure.align-right,object.align-right{clear:right;float:right;margin-left:1em} -img.align-center,.figure.align-center,object.align-center{display:block;margin-left:auto;margin-right:auto} -img.math{vertical-align:middle} -div.body div.math p{text-align:center} -span.eqno{float:right} -.sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background-color:#FFFFFF;border:1px #E8EAF6 solid} -.sidebar p,.sidebar ul,.sidebar dl{font-size:90%} -.sidebar .last,.admonition .last,table.highlighttable{margin-bottom:0} -.sidebar .sidebar-title{display:block;font-weight:bold;background-color:#5C6BC0;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%;color:#FFFFFF;} -#sidebar-bottom-versions{display:block;position:fixed;bottom:20px;height:38px;left:-300px;bottom:0;width:300px;;background-color:#424242;cursor:pointer} -#page.toggled #sidebar-bottom-versions{left:0} -#current-version{padding:8px;margin:0;display:block;color:#66BB6A} -#ReadtheDocs{padding:8px;margin:0;display:inline-block;color:#E8EAF6;float:left;font-size:13px;line-height:24px} -#current-version i{margin-left:5px} -#versions{float:right;direction:ltr} -#other-versions{display:none;position:relative;cursor:default} -#other-versions.toggled{display:block;position:fixed;bottom:38px;width:300px;height:auto;background-color:#424242;z-index:2000;padding:10px;font-size:90%;border-bottom:1px #212121 solid;left:0} -#other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px #212121 solid} -#other-versions dd{display:inline-block;margin:0} -#other-versions dd a{display:inline-block;padding:6px;color:#FAFAFA} -.hlist td{padding:0 8px 0 0} -table.docutils.footnote,table.docutils.citation{word-break:break-all;white-space:normal;display:table} -table.docutils.footnote td{word-break:normal;text-align:justify} -table.docutils.citation tr td.label, table.docutils.footnote tr td.label{display:-moz-groupbox} -@media screen and (max-width: 767px){ -.sidebar{width:100%} -div[class^='highlight']{width:100%;display:inline-block} -.table-responsive{border:1px solid #E8EAF6;border-top:none} -.table{display:table;width:100%}} -::selection{background-color:#5C6BC0;color:#E8EAF6} -td{font-size:14px} -tr.row-even{background-color:#F5F5F5;} - -/* custome style */ - diff --git a/_templates/sphinx_minoo_theme/static/minoo-rtl.css b/_templates/sphinx_minoo_theme/static/minoo-rtl.css index fd59907..0546f35 100644 --- a/_templates/sphinx_minoo_theme/static/minoo-rtl.css +++ b/_templates/sphinx_minoo_theme/static/minoo-rtl.css @@ -75,7 +75,9 @@ box-shadow: 0px 0px 1px 1px rgba(66,66,66,1);} #sidebar-bottom-list{width:100%;display:inline-block;min-height:100%;clear:both} #wrapper-sidebar-bottom{right:-300px;position:fixed;z-index:1000;min-height:100%;width:300px;background-color:#5C6BC0} #body-content{margin-right:auto;margin-left:auto;} -#body-top{width:100%;height:auto;padding:10px 0;display:inline-block;color:#5C6BC0;border-bottom:3px #E8EAF6 solid;margin-bottom:24px} +#body-top{width:100%;height:auto;padding:10px 0;display:inline-block;color:#5C6BC0;border-bottom:3px #E8EAF6 solid;} +#body-donate{width:100%;height:auto;display:inline-block;color:#EC407A;border-top:3px #FCE4EC solid;margin-bottom:24px;margin-top:2px;position:relative;} +.donate-box{display:inline-block;background-color:#FCE4EC;float:left;height:32px;width:auto;padding:2px 10px;cursor:pointer;color:#EC407A;} #body-top>a{display:inline-block;height:auto;vertical-align:bottom;height:auto} #body-top>a:hover{color:#66BB6A} #body-top>span{width:auto;height:28px;line-height:16px;display:inline-block;vertical-align:bottom} diff --git a/_templates/sphinx_minoo_theme/static/minoo-rtl.css~ b/_templates/sphinx_minoo_theme/static/minoo-rtl.css~ deleted file mode 100644 index 36ab6b5..0000000 --- a/_templates/sphinx_minoo_theme/static/minoo-rtl.css~ +++ /dev/null @@ -1,235 +0,0 @@ - -/* colors guide: -theme[first:5C6BC0,second:E8EAF6,hover:66BB6A] -font[main:212121,title:FFFFFF,footnote:616161,headers:000000] -code[background:424242,text:FAFAFA] -highlighted[background:FDD835,text:212121] -list[purple:[title:AB47BC,sub:CE93D8]-green:[title:66BB6A,sub:A5D6A7]-blue[title:5C6BC0,sub:9FA8DA]] -box[note,attention[body:90CAF9,title:42A5F5]-tip,important[body:80CBC4,title:26A69A]-hint,warning[body:FFAB91,title:FF7043]-error,danger[body:EF9A9A,title:EF5350]-caution[body:C5E1A5,title:9CCC65]-admonition[body:B0BEC5,title:78909C]] -*/ - -/* sphinx_rtd_theme fonts */ -@font-face{font-family:"Inconsolata";font-style:normal;font-weight:400;src:local("Inconsolata"),url(fonts/Inconsolata.ttf) format("truetype")}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:700;src:local("Inconsolata Bold"),local("Inconsolata-Bold"),url(fonts/Inconsolata-Bold.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:400;src:local("Lato Regular"),local("Lato-Regular"),url(fonts/Lato-Regular.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:700;src:local("Lato Bold"),local("Lato-Bold"),url(fonts/Lato-Bold.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:local("Roboto Slab Regular"),local("RobotoSlab-Regular"),url(fonts/RobotoSlab-Regular.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:local("Roboto Slab Bold"),local("RobotoSlab-Bold"),url(fonts/RobotoSlab-Bold.ttf) format("truetype")} - -/* HTML elements */ -body{font-family:'IranianSans',"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#212121;min-height:100%;font-size:16px;overflow-x:hidden} -html{height:100%} -a,ul>li>a,ol>li>a{text-decoration:none!important;color:#5C6BC0;padding:0} -a:hover,ul>li>a:hover,ol>li>a:hover{color:#66BB6A} -i{vertical-align:middle} -h1,h2,h3,h4,h5,h6{font-weight:bold;color:#000000;display:inline-block} -h1,h2{padding:10px 15px 10px 0} -h1{background-color:#5C6BC0;color:#FFFFFF;line-height:26px;border-right:5px #E8EAF6 solid} -p{line-height:24px;margin:0;font-size:16px} -h1{font-size:175%} -h2{font-size:150%} -h3{font-size:125%} -h4{font-size:115%} -h5{font-size:110%} -h6{font-size:100%} -hr{margin-top:0;border-top:1px #E8EAF6 solid} -blockquote{border-left:none;border-right:none;padding:0;margin:0 24px 0 0} -th{text-align:right} -td,th{vertical-align:top} -thead{background-color:#5C6BC0;color:#FFFFFF} -caption{text-align:center;color:#212121;padding:8px 24px;background-color:#E8EAF6} -code,kbd,pre,samp{background-color:#E8EAF6;border-radius:0;border:none;direction:ltr;font-size:12px} -code,kbd,samp{padding:2px 6px;white-space:pre} -pre{margin:0;overflow-wrap:normal;text-align:left} -ul,ol{padding-right:24px} -ul li{list-style:disc} -dl dt{font-weight:bold} -dl dd{margin:0 24px 12px 0} - -/* theme */ -#page{padding:0;margin:0;height:100%} -#page.toggled{padding-right:300px} -#page-body{width:100%;position:relative;padding-right:32px;visibility:visible} -@media(min-width:768px){#page.toggled #page-body{position:relative;padding-right:0}} -@media(max-width:768px){#page.toggled #page-body{visibility:hidden}#page.toggled{padding-right:0}#page.toggled .back-to-top{display:none !important}} -#page-sidebar{width:300px;min-height:100%;background-color:#5C6BC0;overflow:hidden;float:right} -#wrapper-page-sidebar{z-index:1000;position:fixed;width:300px;min-height:100%;background-color:#5C6BC0;right:-300px} -#sidebar-top{width:300px;top:0!important;right:-300px;position:fixed;z-index:1000;background-color:#5C6BC0} -#page.toggled #sidebar-top,#page.toggled #wrapper-sidebar-bottom,#page.toggled #wrapper-page-sidebar{right:0} -#page,#wrapper-page-sidebar,#page-sidebar,#sidebar-top,#sidebar-bottom-versions,#wrapper-sidebar-bottom,#sidebar-bottom-versions{-webkit-transition:all 0.5s ease;-moz-transition:all 0.5s ease;-o-transition:all 0.5s ease;-ms-transition:all 0.5s ease;transition:all 0.5s ease} -#sidebar-top-image{width:300px;height:96px;display:block;text-align:center} -#sidebar-top-image>span{width:86px;height:86px;background-repeat:no-repeat;background-size:cover;border:4px solid #E8EAF6;display:inline-block;margin-top:5px;-webkit-box-shadow: 0px 0px 1px 1px rgba(66,66,66,1); --moz-box-shadow: 0px 0px 1px 1px rgba(66,66,66,1); -box-shadow: 0px 0px 1px 1px rgba(66,66,66,1);} -#sidebar-top-links{width:300px;height:34px;display:block;text-align:center} -#sidebar-top-links>a{display:inline-block;color: #E8EAF6} -#sidebar-top-links>a:hover{color:#66BB6A} -#sidebar-navigation{width:332px;height:52px;background-color:#5C6BC0;display:block;line-height:28px} -#page.toggled #sidebar-navigation{background-color:#E8EAF6;width:300px} -#navigation-toggle{width:32px;height:52px;color:#FFFFFF;cursor:pointer;float:left;padding:0 8px;display:inline-block;background-color:#5C6BC0} -#page.toggled #navigation-toggle{background-color:#66BB6A} -#navigation-search{width:268px;position:absolute;padding:2px 8px;display:inline-block;left:32px} -#input-search{width:100%;background-color:transparent;padding:3px 10px;font-size:13px;color:#212121;border:none;box-shadow:inset 0 -1px 0 #5C6BC0} -#input-search:focus{outline:0;box-shadow:inset 0 -1px 0 #66BB6A} -#navigation-toggle>i{margin-top:12px} -#sidebar-top-title{width:300px;height:auto;text-align:center;padding:10px;display:inline-block} -#sidebar-top-title>a{color:#E8EAF6;font-weight:bold} -#sidebar-top-title>a:hover{color:#66BB6A} -#sidebar-bottom{width:300px;padding:0 10px;display:inline-block;background-color:#5C6BC0;overflow-y:auto;overflow-x:hidden} -#sidebar-bottom-list{width:100%;display:inline-block;min-height:100%;clear:both} -#wrapper-sidebar-bottom{right:-300px;position:fixed;z-index:1000;min-height:100%;width:300px;background-color:#5C6BC0} -#body-content{margin-right:auto;margin-left:auto;} -#body-top{width:100%;height:auto;padding:10px 0;display:inline-block;color:#5C6BC0;border-bottom:3px #E8EAF6 solid;margin-bottom:24px} -#body-top>a{display:inline-block;height:auto;vertical-align:bottom;height:28px} -#body-top>a:hover{color:#66BB6A} -#body-top>span{width:auto;height:28px;line-height:16px;display:inline-block;vertical-align:bottom} -#body-top>a>i,#body-top>span>i{display:inline-block} -#top-src{float:left} -.top-src{float:left;margin-right:24px} -@media(max-width:768px){#top-src{display:none!important}} -#body-btn{width:100%;height:100px;padding:28px 0;border-top:3px #E8EAF6 solid;line-height:30px;display:block} -#body-btn>a{width:auto;height:auto;display:inline-block;padding:5px 8px;color:#FFFFFF;background-color:#5C6BC0} -#body-btn>a:hover{background-color:#66BB6A} -#body-btn>a>i{height:22px;display:inline-block;vertical-align:middle} -#body-footer{direction:ltr;width:100%;height:auto;padding:10px 0;background-color:#E8EAF6;line-height:30px;display:block;margin:0 0 24px 0} -#body-footer>p{text-align:center;margin-bottom:0} -.back-to-top{margin:10px;position:fixed;bottom:0;left:0;width:28px;height:28px;z-index:100;display:none;color:#66BB6A;cursor:pointer;opacity:0.7} -.back-to-top:hover{opacity:1} -.back-to-top>i{font-size:32px;line-height:28px;vertical-align:top} -@media print{a[href^="http://"]:after,a[href^="https://"]:after{content:""}pre{overflow-wrap:break-word}#page-sidebar,.back-to-top,#body-footer,#body-btn,#top-src,#wrapper-page-sidebar{display:none;}pre,blockquote,tr,img,p.caption,h2,h3{page-break-inside:avoid}thead{display:table-header-group}img{max-width:100%!important}@page{margin:0.5cm}p,h2,h3,p.caption{orphans:3;widows:3}} - - -/* common */ -.fa{font-size:19px} -.table{display:inline-block;width:auto;max-width:none;white-space:nowrap} -.admonition,.figure,.h-scroll,.highlight,.table-responsive,table.field-list,dl,img,h1,h2,h3,h4,h5,h6,p,hr,ol,ul,ul.search>li,.contents.topic,.line-blockack,blockquote,blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child,table.hlist,table.docutils.footnote,table.docutils.citation,ol ol,ol ul,ul ol,ul ul{margin-bottom:24px} -.margin-b-z,ul li p:last-child,.figure img,.table,.last .highlight,.hlist ul,div[class^='highlight'] .table-responsive{margin-bottom:0}/**/ -.code{width:100%} -p.caption,h1,h2,h3,h4,h5,h6,table{margin-top:0} -.align-left{text-align:left} -.align-center{text-align:center} -.align-right{text-align:right} -.table-striped>tbody>tr:nth-of-type(odd){background-color:#E8EAF6} -.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #E8EAF6} -.table-bordered{border:0} -.alert,.btn{border-radius:0} -.img-responsive{display:inline} - -/* reST */ -.line-block{margin-right:24px} -.toc-backref{color:#000000} -.highlighttable{direction:ltr;overflow:hidden} -div[class^='highlight']{overflow-x:auto;direction:ltr} -div[class^='highlight'] td.code{width:100%} -div[class^='highlight-'] .highlight,div[class^='last highlight-'] .highlight{margin-bottom:0} -a.headerlink{visibility:hidden;content:none} -h3:hover a.headerlink:before,caption:hover a.headerlink:before{font-family:FontAwesome;visibility:visible;display:inline-block;content:"\f13d";font-size:13px;color:#66BB6A;margin-right:5px;height:10px} -h1:hover a.headerlink:before,h2:hover a.headerlink:before{font-family:FontAwesome;visibility:visible;display:inline-block;content:"\f13d";font-size:13px;color:#FFFFFF;margin-right:5px;height:10px} -p.rubric{margin-bottom:12px;font-weight:bold} -.container{padding-right:0;padding-left:0;margin:0 0 24px 0;width:100%} -.linenodiv pre{border-right:0;background-color:#5C6BC0;color:#FFFFFF} -.linenos{margin-bottom:24px;vertical-align:top} -.topic-title{font-weight:bold;margin-bottom:12px} -.highlighted{background:#FDD835;display:inline-block;font-weight:bold;padding:0 4px;color:#212121} -table.field-list{border:none;white-space:normal} -table.field-list .field-name{padding-left:0;text-align:right} -table.field-list .field-body{padding-right:0;text-align:right} -table.field-list th,table.field-list td{width:auto!important} -.footnote-reference,.citation-reference{vertical-align:super;font-size:90%} -.table.docutils.footnote tr,.table.docutils.citation tr{background:none;color:#616161} -table.docutils.citation tr td,table.docutils.footnote tr td{border:none} -table.docutils.footnote td,table.docutils.footnote th,table.docutils.citation td,table.docutils.citation th,table.field-list th,table.field-list td{margin:0;padding:3px 6px!important;font-size:90%;overflow:visible;width:100%} -table.docutils.footnote{white-space:normal} -.toctree-wrapper li,#sidebar-bottom-list #tree-toc ul li,.contents.topic ul li{list-style:none} -.toctree-wrapper li>ul{padding:0;margin:0 24px 0 0} -.toctree-wrapper li>a{background-color:#AB47BC;color:#FFFFFF;line-height:26px;border-right:0} -.toctree-wrapper li>ul>li>a{background-color:#CE93D8} -.toctree-wrapper li>a:hover{border-right:5px #CE93D8 solid} -.toctree-wrapper li>ul>li>a:hover{border-right:5px #AB47BC solid} -.toctree-wrapper li>a:hover,.contents.topic li>a:hover{color:#FFFFFF} -.contents.topic li>a{background-color:#5C6BC0;color:#FFFFFF;padding:3px 10px;line-height:26px;border-right:0} -.contents.topic li>ul>li>a{background-color:#9FA8DA} -.contents.topic li>a:hover{border-right:5px #9FA8DA solid} -.contents.topic li>ul>li>a:hover{border-right:5px #5C6BC0 solid} -#sidebar-bottom-list #tree-toc{margin-top:10px;margin-bottom:20px;width:280px;min-height:100%} -#sidebar-bottom-list #tree-toc ul{padding:0;margin:0 24px 0 0} -#sidebar-bottom-list #tree-toc ul li>a,#sidebar-bottom-list #tree-toc ul li.current>a{line-height:26px;border-right:0} -#sidebar-bottom-list #tree-toc ul li>a{color:#212121;background-color:#E8EAF6} -#sidebar-bottom-list #tree-toc ul li.current>a, h2{color:#FFFFFF;background-color:#66BB6A} -h2{border-right:5px #E8EAF6 solid !important} -#sidebar-bottom-list #tree-toc ul li>ul>li>a{color:#FFFFFF;background-color:#A5D6A7} -#sidebar-bottom-list #tree-toc ul li>a:hover{border-right:5px #66BB6A solid;color:#212121} -#sidebar-bottom-list #tree-toc ul li.current>a:hover{border-right:5px #E8EAF6 solid;color:#FFFFFF} -#sidebar-bottom-list #tree-toc ul li>ul>li>a:hover{border-right:5px #E8EAF6 solid;color:#FFFFFF} -#sidebar-bottom-list #tree-toc ul li.current>ul>li>a:hover{color:#FFFFFF} -#sidebar-bottom-list #tree-toc li a,.toctree-wrapper li>a,.contents.topic li>a{display:inline-block;margin:0;padding:2px 10px} -#sidebar-bottom-list #tree-toc li,.toctree-wrapper li,.contents.topic li{margin-top:1px} -#sidebar-bottom-list #tree-toc li.toctree-l1 i,.toctree-wrapper li.toctree-l1 i{margin-right:-24px; margin-left:9px;display:inline-block;vertical-align:top;padding-top:5px;cursor:pointer;color:#E8EAF6} -.toctree-wrapper li.toctree-l1 i{color:#CE93D8!important} -#sidebar-bottom-list #tree-toc li.toctree-l1 i:hover{color:#66BB6A} -.toctree-wrapper li.toctree-l1 i:hover{color:#AB47BC!important} -.admonition{display:inline-block;width:100%;padding:12px} -.admonition-title{color:#FFFFFF;margin:-12px;padding:6px 12px} -.note .admonition-title,.tip .admonition-title,.hint .admonition-title,.attention .admonition-title,.important .admonitionpri-title,.warning .admonition-title,.error .admonition-title,.danger .admonition-title,.caution .admonition-title,.admonition .admonition-title{font-weight:bold;margin-bottom:12px} -.note .admonition-title:before,.tip .admonition-title:before,.hint .admonition-title:before,.attention .admonition-title:before,.important .admonition-title:before,.warning .admonition-title:before,.error .admonition-title:before,.danger .admonition-title:before,.caution .admonition-title:before,.admonition .admonition-title:before{margin-left:5px} -.admonition.note,.admonition.attention{background-color:#90CAF9} -.admonition.note .admonition-title,.admonition.attention .admonition-title{background-color:#42A5F5} -.admonition.note .admonition-title:before{font-family:FontAwesome;content:"\f12a"} -.admonition.attention .admonition-title:before{font-family:FontAwesome;content:"\f0e7"} -.admonition.tip,.admonition.important{background-color:#80CBC4} -.admonition.tip .admonition-title,.admonition.important .admonition-title{background-color:#26A69A} -.admonition.tip .admonition-title:before{font-family:FontAwesome;content:"\f0eb"} -.admonition.important .admonition-title:before{font-family:FontAwesome;content:"\f0a3"} -.admonition.hint,.admonition.warning{background-color:#FFAB91} -.admonition.hint .admonition-title,.admonition.warning .admonition-title{background-color:#FF7043} -.admonition.hint .admonition-title:before{font-family:FontAwesome;content:"\f075"} -.admonition.warning .admonition-title:before{font-family:FontAwesome;content:"\f071"} -.admonition.error,.admonition.danger{background-color:#EF9A9A} -.admonition.error .admonition-title,.admonition.danger .admonition-title{background-color:#EF5350} -.admonition.error .admonition-title:before{font-family:FontAwesome;content:"\f05e"} -.admonition.danger .admonition-title:before{font-family:FontAwesome;content:"\f1e2"} -.admonition.caution{background-color:#C5E1A5} -.admonition.caution .admonition-title{background-color:#9CCC65} -.admonition.caution .admonition-title:before{font-family:FontAwesome;content:"\f06e"} -.admonition{background-color:#B0BEC5} -.admonition .admonition-title{background-color:#78909C} -.admonition .admonition-title:before{font-family:FontAwesome;content:"\f040"} -img.align-left,.figure.align-left,object.align-left{clear:left;float:left;margin-right:1em} -img.align-right,.figure.align-right,object.align-right{clear:right;float:right;margin-left:1em} -img.align-center,.figure.align-center,object.align-center{display:block;margin-left:auto;margin-right:auto} -img.math{vertical-align:middle} -div.body div.math p{text-align:center} -span.eqno{float:right} -.sidebar{float:left;width:40%;display:block;margin:0 24px 24px 0;padding:24px;background-color:#FFFFFF;border:1px #E8EAF6 solid} -.sidebar p,.sidebar ul,.sidebar dl{font-size:90%} -.sidebar .last,.admonition .last,table.highlighttable{margin-bottom:0} -.sidebar .sidebar-title{display:block;font-weight:bold;background-color:#5C6BC0;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%;color:#FFFFFF;} -#sidebar-bottom-versions{display:block;position:fixed;bottom:20px;height:38px;right:-300px;bottom:0;width:300px;;background-color:#424242;cursor:pointer} -#page.toggled #sidebar-bottom-versions{right:0} -#current-version{padding:8px;margin:0;display:block;color:#66BB6A} -#ReadtheDocs{padding:8px;margin:0;display:inline-block;color:#E8EAF6;float:right;font-size:13px;line-height:24px} -#current-version i{margin-left:5px} -#versions{float:left;direction:ltr} -#other-versions{display:none;position:relative;cursor:default} -#other-versions.toggled{display:block;position:fixed;bottom:38px;right:0;width:300px;height:auto;background-color:#424242;z-index:2000;padding:10px;font-size:90%;border-bottom:1px #212121 solid} -#other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px #212121 solid} -#other-versions dd{display:inline-block;margin:0} -#other-versions dd a{display:inline-block;padding:6px;color:#FAFAFA} -.hlist td{padding:0 0 0 8px} -table.docutils.footnote,table.docutils.citation{word-break:break-all;white-space:normal;display:table} -table.docutils.footnote td{word-break:normal;text-align:justify} -table.docutils.citation tr td.label, table.docutils.footnote tr td.label{display:-moz-groupbox} -@media screen and (max-width: 767px){ -.sidebar{width:100%} -div[class^='highlight']{width:100%;display:inline-block} -.table-responsive{border:1px solid #E8EAF6;border-top:none} -.table{display:table;width:100%}} -::selection{background-color:#5C6BC0;color:#E8EAF6} -td{font-size:14px} -tr.row-even{background-color:#F5F5F5;} - - -/* custome style */ -ul li{text-align:justify} -.red{color:#E65100} -.emoji-size{font-size:20px;color:#E65100} -p,blockquote{text-align:justify} -body{font-size:16px} -@font-face{font-family:'IranianSans';src:url('fonts/IranianSansWeb-Regular.woff');font-weight:normal;font-style:normal} -.table-ltr{direction:ltr !important;text-align:center;margin-bottom: -24px !important;} -.table-ltr th{text-align:center !important} diff --git a/index.rst b/index.rst index f9eaffa..d59f455 100644 --- a/index.rst +++ b/index.rst @@ -34,6 +34,17 @@ کتاب در حال تکمیل است!. - +.. raw:: html + + + لوگوی جشنواره وب و موبایل ایران + diff --git a/requirements.txt b/requirements.txt index 6e197f9..e69de29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +0,0 @@ -khayyam From 021ab718fea1270ef540677f746668237df21d36 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Mon, 16 Jan 2017 22:21:01 +0330 Subject: [PATCH 006/316] add iwmf link --- index.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/index.rst b/index.rst index 028fe0f..d59f455 100644 --- a/index.rst +++ b/index.rst @@ -34,3 +34,17 @@ کتاب در حال تکمیل است!. +.. raw:: html + + + لوگوی جشنواره وب و موبایل ایران + + + From 198958f94eebba61b4f37eee364c3335cb16de53 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Tue, 17 Jan 2017 12:16:30 +0330 Subject: [PATCH 007/316] change iwmf link position --- _templates/sphinx_minoo_theme/includes/top.html | 11 +++++++++++ index.rst | 13 ------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/_templates/sphinx_minoo_theme/includes/top.html b/_templates/sphinx_minoo_theme/includes/top.html index e6a862e..16d53b2 100644 --- a/_templates/sphinx_minoo_theme/includes/top.html +++ b/_templates/sphinx_minoo_theme/includes/top.html @@ -29,3 +29,14 @@ درگاه پرداخت هدیه :) + + + لوگوی جشنواره وب و موبایل ایران + diff --git a/index.rst b/index.rst index d59f455..f1f3e2b 100644 --- a/index.rst +++ b/index.rst @@ -34,17 +34,4 @@ کتاب در حال تکمیل است!. -.. raw:: html - - - لوگوی جشنواره وب و موبایل ایران - - From ad80ad208cb2a35df9565c5d5823ab95680fbe2c Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Tue, 16 May 2017 21:08:43 +0430 Subject: [PATCH 008/316] l11 completed --- .../sphinx_minoo_theme/static/minoo-rtl.css | 1 + lessons/l11.rst | 403 +++++++++++++++++- 2 files changed, 399 insertions(+), 5 deletions(-) diff --git a/_templates/sphinx_minoo_theme/static/minoo-rtl.css b/_templates/sphinx_minoo_theme/static/minoo-rtl.css index 0546f35..79cec5f 100644 --- a/_templates/sphinx_minoo_theme/static/minoo-rtl.css +++ b/_templates/sphinx_minoo_theme/static/minoo-rtl.css @@ -251,3 +251,4 @@ body{font-size:16px} font-weight: normal; font-style: normal; } +h1 a.toc-backref, h2 a.toc-backref{color:#fff !important} diff --git a/lessons/l11.rst b/lessons/l11.rst index 7992638..29da135 100644 --- a/lessons/l11.rst +++ b/lessons/l11.rst @@ -8,7 +8,7 @@ درس ۱۱: کتابخانه استاندارد (بخش ۱) ==================================== -کتابخانه استاندارد پایتون مجموعه‌ وسیعی از امکانات آماده است که با نصب پایتون در اختیار قرار می‌گیرد. فهرست کامل این امکانات را می‌توانید از نشانی‌های `(پایتون 2x) `_ و `(پایتون 3x) `_ مشاهده نمایید. لازم به یادآوری است که بخشی بزرگی از قدرت پایتون به دلیل وجود کتابخانه‌های فراوان و قدرتمند آن است که تعداد زیادی از آن‌ها خارج کتابخانه استاندارد پایتون و درون جامعه کاربری آن در حال توسعه هستند که فهرست تقریبا کاملی از آن‌ها نیز توسط `PyPI `_ قابل جستجو و دریافت هستند. +کتابخانه استاندارد پایتون مجموعه‌ وسیعی از امکانات آماده است که با نصب پایتون در اختیار قرار می‌گیرد. فهرست کامل این امکانات را می‌توانید از نشانی‌های `(پایتون 2x) `_ و `(پایتون 3x) `_ مشاهده نمایید. لازم به یادآوری است که بخشی بزرگی از قدرت پایتون به دلیل وجود کتابخانه‌های فراوان و قدرتمند آن است که تعداد زیادی از آن‌ها خارج کتابخانه استاندارد پایتون و درون جامعه کاربری در حال توسعه هستند که فهرست تقریبا کاملی از آن‌ها نیز توسط `PyPI `_ قابل جستجو و دریافت هستند. این درس به عنوان آخرین درس از سطح مقدماتی کتاب به بررسی بخشی از امکان‌های کاربردی این کتابخانه اختصاص یافته است که البته ممکن است در طول درس‌های گذشته از آن‌ها استفاده کرده باشیم!. @@ -22,6 +22,13 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + + math ------ این ماژول حاوی ثابت‌ها (Constants) و تابع‌های ریاضی است [`اسناد پایتون `__] که برخی از آن‌ها به شرح پایین است: @@ -42,7 +49,7 @@ math 2.718281828459045 >>> -* ``math.inf``: از نسخه 3.5 به بعد - ثابتی حاوی مقدار مثبت بی‌نهایت (Positive infinity) است که این مقدار برابر با خروجی تابع ``('float('inf`` می‌باشد. ``math.inf-`` نیز برابر منفی بی‌نهایت است [`اسناد پایتون `__]. +* ``math.inf``: (از نسخه 3.5 به بعد) - ثابتی حاوی مقدار مثبت بی‌نهایت (Positive infinity) است که این مقدار برابر با خروجی تابع ``('float('inf`` می‌باشد. ``math.inf -`` نیز برابر منفی بی‌نهایت است [`اسناد پایتون `__]. برای بررسی inf بودن (مثبت یا منفی) از تابع ``(math.isinf(x`` [`اسناد پایتون `__] استفاده می‌شود:: @@ -53,6 +60,17 @@ math >>> a > b True + >>> math.inf + math.inf + inf + >>> 1 / math.inf + 0.0 + >>> math.inf / 2 + inf + >>> 3 * math.inf + inf + >>> -3 * math.inf + -inf + >>> math.isinf(a) True >>> math.isinf(b) @@ -69,6 +87,11 @@ math >>> a nan + >>> 0 * math.inf + nan + >>> math.inf - math.inf + nan + >>> math.isnan(a) True >>> @@ -253,7 +276,7 @@ os :: - >>> python3 -q + ~ python3 -q >>> import os >>> os.getcwd() '/home/saeid' @@ -321,7 +344,7 @@ os * ``(os.rmdir(path``: دایرکتوری مشخص شده توسط آرگومان path را حذف می‌کند. این دایرکتوری می‌بایست خالی باشد در غیر این صورت یک استثنا ``OSError`` رخ می‌دهد. [`اسناد پایتون `__] - همچنین برای حذف کامل یک دایرکتوری به همراه تمام محتویات آن می‌توانید از تابع ``(rmtree(path`` درون ماژول ``shutil`` [`اسناد پایتون `__] استفاده نمایید:: + البته برای حذف کامل یک دایرکتوری به همراه تمام محتویات آن می‌توانید از تابع ``(rmtree(path`` درون ماژول ``shutil`` [`اسناد پایتون `__] استفاده نمایید:: >>> import shutil >>> shutil.rmtree("/home/saeid/Documents/dir1") @@ -364,7 +387,7 @@ os >>> os.listdir(os.getcwd()) ['_fonts'] - در گنولینوکس چنانچه بخواهیم نام فایلی به یک نام از پیش موجود تغییر داده شود؛‌ [در صورتی که کاربر نیز اجازه دسترسی (Permission) لازم را داشته باشد] یک عمل جایگزینی (Replace) صورت می‌گیرد، ولی برای چنین مواقعی در سیستم عامل ویندوز یک خطای ``OSError`` رخ خواهد داد. رویداد این ماجرا در هنگام تغییر نام یک دایرکتوری، باعث بروز خطای ``OSError`` در هر دو سیستم عامل می‌شود. + در گنولینوکس چنانچه بخواهیم نام **فایلی** به یک نام از پیش موجود تغییر داده شود؛‌ [در صورتی که کاربر نیز اجازه دسترسی (Permission) لازم را داشته باشد] یک عمل جایگزینی (Replace) صورت می‌گیرد، ولی برای چنین مواقعی در سیستم عامل ویندوز یک خطای ``OSError`` رخ خواهد داد. رویداد این ماجرا در هنگام تغییر نام یک **دایرکتوری**، باعث بروز خطای ``OSError`` در هر دو سیستم عامل می‌شود. * ``(os.renames(old, new``: عملکردی مشابه با تابع ``()rename`` دارد با این تفاوت که اگر دایرکتورهای میانی از مسیر آرگومان ``new``، وجود نداشته باشند، آن‌ها را نیز ایجاد می‌کند [`اسناد پایتون `__]:: @@ -428,6 +451,376 @@ os >>> +* ``os.sep``: این متغیر حاوی کاراکتری می‌باشد که سیستم‌عامل از آن برای جدا سازی اجزای یک مسیر استفاده می‌کند. مانند: ``/`` در گنولینوکس یا ``\\`` در ویندوز [`اسناد پایتون `__] + + +* ``os.extsep``: این متغیر حاوی کاراکتری می‌باشد که در سیستم‌عامل جاری از آن برای جدا سازی نام فایل از پسوند آن استفاده می‌گردد. مانند: ``.`` (نام فایل: script.py) [`اسناد پایتون `__] + + +* ``os.pardir``: حاوی مقداری است که در سیستم‌عامل جاری از آن برای اشاره به یک دایرکتوری بالاتر از دایرکتوری جاری استفاده می‌گردد (Parent Directory). مانند: ``..`` در گنولینوکس و ویندوز [`اسناد پایتون `__]:: + + # GNU/Linux + + ~ pwd + /home/saeid/Documents + + ~ cd .. + + ~ pwd + /home/saeid + + +* ``os.curdir``: حاوی مقداری است که در سیستم‌عامل جاری از آن برای اشاره به دایرکتوری جاری استفاده می‌گردد (Current Directory). مانند: ``.`` در گنولینوکس و ویندوز [`اسناد پایتون `__]:: + + + # GNU/Linux + + ~ pwd + /home/saeid + + ~ cd . + + ~ pwd + /home/saeid + + ~ cd ./.. + + ~ pwd + /home + + + +os.path +-------- + +این ماژول توابعی مفیدی برای کار با مسیر فایل‌ها و دایرکتوری‌ها پیاده‌سازی کرده است [`اسناد پایتون `__]. + + +.. caution:: + برای خواندن و نوشتن فایل‌ها از ``()open`` و برای دسترسی به سیستم‌فایل از ماژول ``os`` استفاده نمایید. + + + +* ``(os.path.split(path``: مسیر path دریافتی را به یک تاپل (dirname, basename) تجزیه می‌کند که در آن **basename** آخرین بخش از مسیر path و **dirname** نیز هر آنچه قبل از basename باشد، خواهند بود [`اسناد پایتون `__]:: + + + >>> import os.path + + >>> for path in [ '/one/two/three', + ... '/one/two/three/', + ... '/', + ... '.', + ... '']: + ... print ('"%s" : "%s"' % (path, os.path.split(path))) + ... + "/one/two/three" : "('/one/two', 'three')" + "/one/two/three/" : "('/one/two/three', '')" + "/" : "('/', '')" + "." : "('', '.')" + "" : "('', '')" + >>> + + +* ``(os.path.basename(path``: مقداری برابر با **بخش دوم** از تاپل خروجی تابع ``(os.path.split(path`` را برمی‌گرداند [`اسناد پایتون `__]:: + + + >>> import os.path + >>> + >>> for path in [ '/one/two/three', + ... '/one/two/three/', + ... '/', + ... '.', + ... '']: + ... print ('"%s" : "%s"' % (path, os.path.basename(path))) + ... + "/one/two/three" : "three" + "/one/two/three/" : "" + "/" : "" + "." : "." + "" : "" + >>> + + +* ``(os.path.dirname(path``: مقداری برابر با **بخش یکم** از تاپل خروجی تابع ``(os.path.split(path`` را برمی‌گرداند [`اسناد پایتون `__]:: + + >>> import os.path + >>> + >>> for path in [ '/one/two/three', + ... '/one/two/three/', + ... '/', + ... '.', + ... '']: + ... print ('"%s" : "%s"' % (path, os.path.dirname(path))) + ... + "/one/two/three" : "/one/two" + "/one/two/three/" : "/one/two/three" + "/" : "/" + "." : "" + "" : "" + >>> + + + +* ``(os.path.splitext(path``: مشابه تابع ``(os.path.split(path`` است با این تفاوت که پسوند را از path جدا کرده و نتیجه را به شکل تاپل بر می‌گرداند [`اسناد پایتون `__]:: + + >>> import os.path + >>> + >>> for path in [ 'filename.txt', + ... 'filename', + ... '/path/to/filename.txt', + ... '/', + ... '.', + ... '']: + ... print ('"%s" : "%s"' % (path, os.path.splitext(path))) + ... + "filename.txt" : "('filename', '.txt')" + "filename" : "('filename', '')" + "/path/to/filename.txt" : "('/path/to/filename', '.txt')" + "/" : "('/', '')" + "." : "('.', '')" + "" : "('', '')" + >>> + + +* ``(os.path.join(*paths``: اجزای یک مسیر را به یکدیگر متصل می‌کند [`اسناد پایتون `__]:: + + # GNU/Linux + + import os + + >>> os.path.join('one', 'two', 'three') + 'one/two/three' + + >>> os.path.join(os.sep, 'one', 'two', 'three') + '/one/two/three' + + :: + + # Windows + + import os + + >>> os.path.join('one', 'two', 'three') + 'one\\two\\three' + + >>> os.path.join(os.sep, 'one', 'two', 'three') + '\\one\\two\\three' + + همچنین برای ایجاد چندین مسیر به صورت همزمان، می‌توان اجزای هر مسیر را به صورت یک تاپل (یا لیست) درون یک لیست قرار داد و سپس با استفاده از حلقه ``for``، اجزای هر مسیر را جداگانه به تابع ``join`` ارسال نمود. البته باید توجه داشت که می‌بایست پارامتر مشخص شده در تعریف تابع ``join`` با یک ستاره مشخص شده باشد؛ در این حالت اجزای درون یک تاپل (یا لیست) به صورت پارامترهای جدا تابع در نظر گرفته می‌شوند، چیزی مانند نمونه کد بالا - در درس تابع دوباره به این شیوه ارسال پارامتر اشاره خواهد شد - به نمونه کد پایین توجه نمایید:: + + >>> import os + + >>> for parts in [ ('one', 'two', 'three'), + ... ('/', 'one', 'two', 'three'), + ... ('/one', 'two', '/three', 'four'), + ... ]: + ... print (parts, ':', os.path.join(*parts)) + ... + ('one', 'two', 'three') : one/two/three + ('/', 'one', 'two', 'three') : /one/two/three + ('/one', 'two', '/three', 'four') : '/three/four' + >>> + + .. note:: + هر مسیر می‌بایست دقیقا شامل یک کاراکتر جدا کننده دایرکتوری (``os.sep``) باشد در غیر این صورت اجزا فقط از آخرین نمونه به بعد در نظر گرفته می‌شوند. این اتفاق در تاپل سوم ``('one', 'two', '/three', 'four/')`` از نمونه کد بالا رخ داده است. + + +* ``(os.path.expanduser(path``: این تابع تنها یک پارامتر با ترکیب ``user~`` می‌پذیرد و کاراکتر ``~`` را به مسیر دایرکتوری کاربر user در سیستم عامل تبدیل می‌کند [`اسناد پایتون `__]:: + + # GNU/Linux + + >>> os.path.expanduser('~saeid') + '/home/saeid' + + :: + + # Windows + + >>> os.path.expanduser('~saeid') + 'C:\\Documents and Settings\\saeid' + + + :: + + # GNU/Linux + + >>> for user in [ '', 'saeid', 'www-data', 'postgres' ]: + ... lookup = '~' + user + ... print (lookup, ':', os.path.expanduser(lookup)) + ... + ~ : /home/saeid + ~saeid : /home/saeid + ~www-data : /var/www + ~postgres : /var/lib/postgresql + >>> + + +* ``(os.path.expandvars(path``: این تابع مقدار متغیرهای محیطی موجود در پارامتر دریافتی را جایگزین کرده و حاصل را برمی‌گرداند. نام متغیرها می‌بایست با الگوی ``name$`` داخل پارامتر ذکر گردند. [`اسناد پایتون `__]:: + + + >>> import os + + >>> os.environ['MYVAR'] = 'VALUE' + >>> os.path.expandvars('/path/to/$MYVAR') + '/path/to/VALUE' + + +* ``(os.path.normpath(path``: مسیر را نرمال‌سازی می‌کند. در این راه تمام مسیرهایی که به یکی از اشکال ``A//B`` ``A/B/`` ``A/./B`` ``A/foo/../B`` هستند، به صورت ``A/B`` ارزیابی می‌شوند. همچنین در سیستم عامل ویندوز کاراکتر جداکننده دایرکتوری گنولینوکس (``/``) را به ``\`` تبدیل می‌کند [`اسناد پایتون `__]:: + + + >>> for path in [ 'one//two//three', + ... 'one/./two/./three', + ... 'one/../one/two/three', + ... ]: + ... print (path, ':', os.path.normpath(path)) + ... + one//two//three : one/two/three + one/./two/./three : one/two/three + one/../one/two/three : one/two/three + >>> + + + :: + + # Windows + + >>> for path in [ 'one/two/three', + ... + ... 'one\\two\\three', + ... 'one\\.\\two\\.\\three', + ... 'one\\..\\one\\two\\three', + ... ]: + ... print (path, ':', os.path.normpath(path)) + ... + one/two/three : one\two\three + one\two\three : one\two\three + one\.\two\.\three : one\two\three + one\..\one\two\three : one\two\three + + +* ``(os.path.abspath(path``: مسیر نسبی را نرمال‌سازی کرده و به مسیر مطلق (Absolute - مسیری از ابتدا یا همان روت سیستم فایل - در گنولینوکس: مسیری که با ``/`` شروع شده باشد - در ویندوز: مسیری که با نام یک درایو شروع شده باشد) تبدیل می‌کند. حاصل این تابع برابر با حاصل ``(os.path.normpath(os.path.join(os.getcwd(), path)`` می‌باشد. [`اسناد پایتون `__]: + + + .. code:: python + + >>> import os + + >>> os.getcwd() + '/mnt/Data/WorkSpace/PythonPersianTutorial' + + >>> for path in [ '.', + ... '..', + ... './one/two/three', + ... '../one/two/three']: + ... print ('"%s" : "%s"' % (path, os.path.abspath(path))) + ... + "." : "/mnt/Data/WorkSpace/PythonPersianTutorial" + ".." : "/mnt/Data/WorkSpace" + "./one/two/three" : "/mnt/Data/WorkSpace/PythonPersianTutorial/one/two/three" + "../one/two/three" : "/mnt/Data/WorkSpace/one/two/three" + >>> + + + .. code:: python + + # Windows + + >>> import os + + >>> os.getcwd() + 'C:\\Python34' + + >>> for path in [ '.', + ... '..', + ... './one/two/three', + ... '../one/two/three']: + ... print ('"%s" : "%s"' % (path, os.path.abspath(path))) + ... + "." : "C:\Python34" + ".." : "C:\" + "./one/two/three" : "C:\Python34\one\two\three" + "../one/two/three" : "C:\one\two\three" + >>> + + +* گاهی لازم است که یک مسیر بررسی شود که آیا مربوط به یک فایل است یا دایرکتوری یا لینک نمادین (`Symbolic link `__)، مسیر مطلق (Absolute) است یا خیر، اصلا وجود دارد یا خیر و ... برای این منظور می‌توان از توابع پایین استفاده کرد: + + ``isabs(path)``: چنانچه مسیر مطلق باشد ``True`` برمی‌گرداند [`اسناد پایتون `__] + + ``isfile(path)``: چنانچه مسیر مربوط به یک فایل که موجود نیز هست باشد ``True`` برمی‌گرداند. این تابع لینک‌های به فایل را نیز دنبال می‌کند، پس این تابع می‌تواند همراه با تابع ``islink`` برای یک مسیر مشخص مقدار ``True`` را برگرداند. [`اسناد پایتون `__] + + ``isdir(path)``: چنانچه مسیر مربوط به یک دایرکتوری که موجود نیز هست باشد ``True`` برمی‌گرداند. این تابع لینک‌های به دایرکتوری را نیز دنبال می‌کند، پس این تابع می‌تواند همراه با تابع ``islink`` برای یک مسیر مشخص مقدار ``True`` را برگرداند. [`اسناد پایتون `__] + + + ``islink(path)``: چنانچه مسیر مربوط به یک لینک نمادین باشد ``True`` برمی‌گرداند. [`اسناد پایتون `__] + + ``exists(path)``: چنانچه مسیر دریافتی صرف نظر از اینکه مربوط به یک فایل است یا دایرکتوری، موجود باشد ``True`` برمی‌گرداند. [`اسناد پایتون `__] + + + ``lexists(path)``:چنانچه مسیر لینک نمادین دریافتی موجود باشد ``True`` برمی گرداند. این تابع لینک را دنبال نمی‌کند و بررسی نمی‌کند که لینک سالم هست یا خیر. [`اسناد پایتون `__] + + .. code-block:: python + :linenos: + + # Python 3.x + # File Name: file_script.py + + import os + + for path in [ __file__, os.path.dirname(__file__), '/', '/var/www/html/wordpress']: + print ('Path :', path) + print ('Absolute :', os.path.isabs(path)) + print ('Is File? :', os.path.isfile(path)) + print ('Is Directory? :', os.path.isdir(path)) + print ('Is Link? :', os.path.islink(path)) + print ('Is Mount point? :', os.path.ismount(path)) + print ('Exists? :', os.path.exists(path)) + print ('Link Exists? :', os.path.lexists(path)) + print () + + + :: + + Path : /home/saeid/Desktop/file_script.py + Absolute : True + Is File? : True + Is Directory? : False + Is Link? : False + Is Mount point? : False + Exists? : True + Link Exists? : True + + Path : /home/saeid/Desktop + Absolute : True + Is File? : False + Is Directory? : True + Is Link? : False + Is Mount point? : False + Exists? : True + Link Exists? : True + + Path : / + Absolute : True + Is File? : False + Is Directory? : True + Is Link? : False + Is Mount point? : True + Exists? : True + Link Exists? : True + + Path : /var/www/html/wordpress + Absolute : True + Is File? : False + Is Directory? : True + Is Link? : True + Is Mount point? : False + Exists? : True + Link Exists? : True + + + متغیر ``__file__`` در هر اسکریپتی به نام کامل آن اسکریپت اشاره دارد. + + مسیر چهارم در نمونه کد بالا در واقع مسیر لینکی است به یک دایرکتوری دیگر. From 039f82277175220e78d8df48e8c20bb8fea2fe91 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Tue, 16 May 2017 21:11:09 +0430 Subject: [PATCH 009/316] remove iwmf link --- _templates/sphinx_minoo_theme/includes/top.html | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/_templates/sphinx_minoo_theme/includes/top.html b/_templates/sphinx_minoo_theme/includes/top.html index 16d53b2..e6a862e 100644 --- a/_templates/sphinx_minoo_theme/includes/top.html +++ b/_templates/sphinx_minoo_theme/includes/top.html @@ -29,14 +29,3 @@ درگاه پرداخت هدیه :) - - - لوگوی جشنواره وب و موبایل ایران - From 6bbc8c7a0aa9ba658f242d8958866e9e72710978 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Tue, 16 May 2017 21:19:49 +0430 Subject: [PATCH 010/316] set log for l11 --- log.rst | 11 +++++++++++ preface.rst | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/log.rst b/log.rst index 9386328..fd9e58c 100644 --- a/log.rst +++ b/log.rst @@ -9,6 +9,17 @@ گزارش توسعه ============= + +.. raw:: html + +

00109 - سه‌شنبه ۲۶ اردیبهشت ۱۳۹۶

+ +درس یازدهم کامل شد. +:emoji-size:`😉` + +---- + + .. raw:: html

00108 - یک‌شنبه ۲۱ آذر ۱۳۹۵

diff --git a/preface.rst b/preface.rst index cf875d2..26249b2 100644 --- a/preface.rst +++ b/preface.rst @@ -1,7 +1,7 @@ پیش‌گفتار ========== -آنچه در این کتاب نوشته می‌شود حاصل یادگیری‌های شخصی از منابع مختلف در دسترس مرتبط با آموزش پایتون می‌باشد؛ یک یادداشت شخصی ولی منسجم! که سعی می‌شه منطبق با مستندات اصلی زبان برنامه‌نویسی پایتون باشد. +آنچه در این کتاب نوشته می‌شود حاصل یادگیری‌های شخصی از منابع مختلف در دسترس مرتبط با آموزش پایتون می‌باشد؛ یک یادداشت شخصی ولی منسجم! که سعی می‌شود منطبق با مستندات اصلی زبان برنامه‌نویسی پایتون باشد. ---- From e21f33d90d34d9115b166bf2fd4eced994e3376c Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Tue, 16 May 2017 21:40:23 +0430 Subject: [PATCH 011/316] add headlines to lessons --- lessons/l01.rst | 5 +++++ lessons/l02.rst | 5 +++++ lessons/l03.rst | 5 +++++ lessons/l04.rst | 5 +++++ lessons/l05.rst | 6 ++++++ lessons/l06.rst | 8 +++++++- lessons/l07.rst | 9 ++++++++- lessons/l08.rst | 6 ++++++ lessons/l09.rst | 5 +++++ lessons/l10.rst | 4 ++++ 10 files changed, 56 insertions(+), 2 deletions(-) diff --git a/lessons/l01.rst b/lessons/l01.rst index da232f5..a899dbc 100644 --- a/lessons/l01.rst +++ b/lessons/l01.rst @@ -15,6 +15,11 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + تاریخچه --------- داستان [#f1]_ پایتون از اواخر سال ۱۹۸۲ میلادی آغاز می‌شود، سالی که آقای `روسوم `_ پس از پایان دانشگاه به عنوان یک برنامه‌نویس وارد تیم توسعه‌ زبان ABC در مرکز `CWI `_ واقع در آمستردام هلند می‌شود. `ABC `_ یک زبان برنامه‌نویسی تفسیر‌شده (Interpreted) با اهداف آموزشی است که از اواخر دهه هفتاد میلادی، تحت پروژه‌ای در این مرکز آغاز شده بود. وی چهار یا پنج سال بعد، زمانی که از پروژه‌ زبان ABC نتیجه‌ مطلوب حاصل نمی‌گردد از آن خارج و به تیم توسعه‌ `سیستم عامل آمیب `_ می‌پیوندد. این موضوع از آن جهت دارای اهمیت است که در هنگام کار بر روی این سیستم عامل بود که آقای روسوم به فکر ایجاد یک زبان اسکریپتی (Scripting Language) جدید می‌افتد. diff --git a/lessons/l02.rst b/lessons/l02.rst index 254cc2b..440b724 100644 --- a/lessons/l02.rst +++ b/lessons/l02.rst @@ -14,6 +14,11 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + دانلود -------- برای ترجمه و اجرای سورس کد ایجاد شده به زبان پایتون لازم است «بسته نصبی پایتون» (همان CPython یا اگر ساده بگوییم: پایتون) که شامل مفسر، کتابخانه استاندارد، برنامه `IDLE `_ (ویرایشگر پیش‌فرض پایتون) و... است را دانلود و بر روی سیستم عامل نصب نماییم. diff --git a/lessons/l03.rst b/lessons/l03.rst index 53a3f70..15b2ac6 100644 --- a/lessons/l03.rst +++ b/lessons/l03.rst @@ -12,6 +12,11 @@ :emoji-size:`✔` سطح: پایه +---- + +.. contents:: سرفصل‌ها + :depth: 2 + ---- ساختار پروژه diff --git a/lessons/l04.rst b/lessons/l04.rst index 32a8ea6..89d887d 100644 --- a/lessons/l04.rst +++ b/lessons/l04.rst @@ -14,6 +14,11 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + حالت تعاملی ------------- از درس پیش به خاطر داریم که کدهای پایتون را می‌توان به دو روش اجرا نمود: ۱- ایجاد اسکریپت و معرفی آن به مفسر پایتون که در همان درس بررسی شد ۲- به شکل تعاملی با مفسر پایتون که موضوع همین درس است. diff --git a/lessons/l05.rst b/lessons/l05.rst index b6ad7c2..40cdd90 100644 --- a/lessons/l05.rst +++ b/lessons/l05.rst @@ -14,6 +14,12 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + برنامه‌نویسی شی‌گرا -------------------- «برنامه‌نویسی شی‌گرا» (`Object-Oriented Programming `_) یا به اختصار OOP یک الگو یا شیوه تفکر در برنامه‌نویسی است که برگرفته از دنیای واقعی بوده و از دهه ۱۹۶۰ میلادی مطرح گشته است. به زبانی که از این الگو پشتیبانی کند، «زبان شی‌گرا» گفته می‌شود؛ `Simula 67 `_ و `Smalltalk `_ نخستین زبان‌های برنامه‌نویسی شی‌گرا هستند. ایده شی‌گرایی در پاسخ به برخی از نیازها که الگوهای موجود پاسخ‌گو آن‌ها نبودند به وجود آمد؛ نیازهایی مانند: توانایی حل تمامی مسائل پیچیده (Complex)، «پنهان‌سازی داده» (Data Hiding)، «قابلیت استفاده مجدد» (Reusability) بیشتر، وابستگی کمتر به توابع، انعطاف بالا و... diff --git a/lessons/l06.rst b/lessons/l06.rst index 24a04ca..12b088b 100644 --- a/lessons/l06.rst +++ b/lessons/l06.rst @@ -10,13 +10,19 @@ در این درس به معرفی اجزای پایه در برنامه‌نویسی پایتون پرداخته شده و اینکه چه هستند، چه گرامری دارند، چه کاری انجام می‌دهند یا... مورد بررسی قرار گرفته است. همچنین در موارد بسیاری نکته‌هایی از شیوه استاندارد پایتون‌نویسی که توسط سند `PEP 8 `__ به برنامه‌نویسان پایتون پیشنهاد می‌شود نیز آورده شده است؛ رعایت این اصول به یکدستی کدهای جامعه پایتون کمک می‌کند. -سینتکس (`Syntax `_ یا دستور زبان) مجموعه‌ای از قواعد است که چگونگی برنامه‌نویسی به یک زبان مشخص را تعریف می‌کند؛ برای نمونه اینکه یک متن چطور نوشته شود که توسط مفسر پایتون به عنوان توضیح در نظر گرفته شود یا یک شی رشته به رعایت سینتکس تعریف شده در پایتون بستگی دارد و چنانچه مفسر نتواند متن را با هیچ قاعده‌ تعریف شده‌ای مطابقت دهد یک استثنا گزارش خواهد شد. سینتکس پایتون تنها محدود به این درس نیست و موارد بسیار دیگری به مانند چگونگی تعریف اشیا گوناگون را در طی درس‌های آتی مشاهده خواهید کرد. +سینتکس (`Syntax `_ یا دستور زبان) مجموعه‌ای از قواعد است که چگونگی برنامه‌نویسی به یک زبان مشخص را تعریف می‌کند؛ برای نمونه اینکه یک متن چطور نوشته شود که توسط مفسر پایتون به عنوان توضیح در نظر گرفته شود یا یک شی رشته، به رعایت سینتکس تعریف شده در پایتون بستگی دارد و چنانچه مفسر نتواند متن را با هیچ قاعده‌ تعریف شده‌ای مطابقت دهد یک استثنا گزارش خواهد شد. سینتکس پایتون تنها محدود به این درس نیست و موارد بسیار دیگری به مانند چگونگی تعریف اشیا گوناگون را در طی درس‌های آتی مشاهده خواهید کرد. :emoji-size:`✔` سطح: مقدماتی ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + سطرها ------ diff --git a/lessons/l07.rst b/lessons/l07.rst index ec19392..5a08247 100644 --- a/lessons/l07.rst +++ b/lessons/l07.rst @@ -10,7 +10,7 @@ پایتون هر «نوع داده» (Data Type) را توسط یک کلاس ارایه می‌دهد؛ بنابراین هر داده یک نمونه یا یک شی از کلاسی مشخص است. هر چند برنامه‌نویس نیز می‌تواند با تعریف کلاس، نوع دلخواه خود را داشته باشد ولی در این درس می‌خواهیم درباره آن بخشی از انواع داده یا انواع شی‌ای که به شکل آماده (Built-in) در اختیار مفسر زبان پایتون قرار داده شده است صحبت کنیم. -در این درس تنها به بررسی «انواع شی عددی» و «نوع رشته» در پایتون پرداخته می‌شود و انواع باقی مانده دیگر توسط درس بعد بررسی خواهند شد. با اینکه تلاش شده است جزییات کامل باشند ولی در برخی بخش‌ها مطالعه اسناد رسمی پایتون می‌تواند اطلاعات کامل‌تری را در اختیار شما قرار دهد. در مواقع بسیاری از تابع‌های آماده پایتون استفاده خواهد شد که ممکن است جزییاتی بیشتر از آنچه در این درس بیان می‌شود را داشته باشند؛ به همین دلیل لینک تعریف آن‌ها در اسناد پایتون نیز ارایه گشته است. نکته مهم در مطالعه این درس بررسی نمونه کدهاست که گاهی درک توضیح داده شده بدون دقت در آن‌ها ناممکن خواهد بود. +در این درس تنها به بررسی «انواع شی عددی» و «نوع رشته» در پایتون پرداخته می‌شود و انواع باقی مانده دیگر توسط درس بعد بررسی خواهند شد. با اینکه تلاش شده است جزییات کامل باشند ولی در برخی بخش‌ها مطالعه اسناد رسمی پایتون می‌تواند اطلاعات کامل‌تری را در اختیار شما قرار دهد. در مواقع بسیاری از تابع‌های آماده پایتون استفاده خواهد شد که ممکن است جزییاتی بیشتر از آنچه در این درس بیان می‌شود را داشته باشند؛ به همین دلیل لینک تعریف آن‌ها در اسناد پایتون نیز ارایه گشته است. نکته مهم در مطالعه این درس بررسی نمونه کدهاست که گاهی درک توضیحی که داده شده است بدون دقت در این نمونه کدها ناممکن خواهد بود. @@ -18,6 +18,13 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + + انواع عددی diff --git a/lessons/l08.rst b/lessons/l08.rst index eba71be..175b3bd 100644 --- a/lessons/l08.rst +++ b/lessons/l08.rst @@ -18,6 +18,12 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + لیست ------ diff --git a/lessons/l09.rst b/lessons/l09.rst index f5114c6..8856260 100644 --- a/lessons/l09.rst +++ b/lessons/l09.rst @@ -18,6 +18,11 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- + انتخاب -------- diff --git a/lessons/l10.rst b/lessons/l10.rst index 6c7f2d5..dfb465b 100644 --- a/lessons/l10.rst +++ b/lessons/l10.rst @@ -18,6 +18,10 @@ ---- +.. contents:: سرفصل‌ها + :depth: 2 + +---- فایل‌ها -------- From 456b3ef4c61fce18034da2b0e4fe7554b1bf3d51 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Thu, 25 May 2017 09:41:57 +0430 Subject: [PATCH 012/316] start l12 --- _static/nested-namespaces-python.jpg | Bin 0 -> 35697 bytes index.rst | 1 + lessons/l12.rst | 143 +++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 _static/nested-namespaces-python.jpg create mode 100644 lessons/l12.rst diff --git a/_static/nested-namespaces-python.jpg b/_static/nested-namespaces-python.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3506ad03f0e6d168a450e4f7a2d0b80a91b84ddf GIT binary patch literal 35697 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 def func_name(): + ... pass + ... + >>> + >>> type(func_name) + + +.. tip:: + پیشنهاد `PEP 8 `__: نام تابع از حروف کوچک تشکیل شود که کلمه‌های آن با استفاده از خط زیرین (Underscores) از یکدیگر جدا شده باشند. مانند: my_function . حالت ``mixedCase`` مانند: myFunction نیز صحیح می‌باشد به شرط آنکه در سراسر کدها نام توابع با همین الگو نوشته شود. + +بدنه تا زمانی که تابع فراخوانی نگردد، اجرا نمی‌شود. برای فراخوانی تابع از نام تابع + پرانتز استفاده می‌شود و در صورتی که در تعریف تابع پارامترهایی قرار داده شده باشد، می‌بایست هنگام فراخوانی آرگومان‌های متناسب با این پارامترها نیز ارسال گردند:: + + function_name(arg1, arg2,... argN) + + +.. caution:: + در بحث توابع، به متغیرهایی که در سرآیند تابع تعریف می‌شوند پارامتر (Parameter) و به داده‌هایی که هنگام فراخوانی تابع ارسال می‌گردد آرگومان (Argument) گفته می‌شود. به ازای هر آرگومان ارسالی می‌بایست یک پارامتر در تابع جهت دریافت آن تعریف شده باشد. هیچ الزامی به هم نام بودن آرگومان‌ها و پارامترهای نظیر وجود ندارد ولی وجود هم نامی باعث خوانایی بیشتر کد می‌شود. + + + +بدنه تابع می تواند حاوی کلمه کلیدی ``return`` نیز باشد. در واقع ``return`` دستوری است که در هر جایی از بدنه آورده شود، اجرای تابع در آن نقطه متوقف و مقداری (البته در زبان پایتون درست این است که گفته شود: شی‌ایی) را به عنوان نتیجه به محل فراخوانی تابع بازمی‌گرداند:: + + def function_name(param1, param2,... paramN): + ... + return value + +در نمونه کد بالا value مقداری است که توسط ``return`` به محل فراخوانی بازگردانده می‌شود. value می‌تواند صراحتا یک مقدار نباشد بلکه یک عبارت مانند : ``param1**2`` یا ``param1 > 3`` و... باشد که در این صورت ابتدا حاصل عبارت ارزیابی و سپس بازگردانده می‌شود. چنانچه value ذکر نگردد، ``None`` بازگردانده می‌شود:: + + >>> def my_pow(x, y): + ... return x**y + ... + >>> + >>> a = 2 + >>> b = 3 + >>> + >>> my_pow(a, b) + 8 + >>> + +در زبان برنامه نویسی پایتون تابع یک موجودیت **”first-class“** است که یعنی تابع را می‌توان مانند دیگر اشیا به صورت پویا ایجاد یا نابود کرد، به صورت آرگومان به توابع دیگر ارسال نمود، به عنوان نتیجه توسط ``return`` بازگرداند و... در نتیجه می‌توان یک تابع را درون بدنه دستورات کنترلی (``while`` ،``if`` و...) یا درون بدنه تابعی دیگر تعریف نمود:: + + >>> def outer(num1): + ... def inner_increment(num1): # hidden from outer code + ... return num1 + 1 + ... num2 = inner_increment(num1) + ... print(num1, num2) + ... + >>> + >>> outer(1) + 1 2 + + +خیلی خوب است که با استفاده از ”Docstring“ در توابع به مستندسازی و خوانایی بهتر برنامه کمک کنیم - درس ششم:: + + + def function_with_docstring(param1, param2): + """Example function with types documented in the docstring. + + Args: + param1 (int): The first parameter. + param2 (str): The second parameter. + + Returns: + bool: The return value. True for success, False otherwise. + """ + + +فضاهای نام +----------- +در هر برنامه پایتون تعداد زیادی نام وجود دارد که برای نمونه می‌توان به: متغیرها که پیش‌تر اشاره شد و می‌دانیم، متغیرها نام‌هایی هستند که به اشیا (از انواع مختلف) ارجاع دارند، نام توابع که به اشیایی از نوع تابع ارجاع دارند، نام کلاس‌ها که به اشیایی از نوع کلاس ارجاع دارند و... اشاره کرد. بدیهی است که برای شناسایی اشیا لازم است نام‌ها منحصر به فرد باشند، رعایت چنین امری در یک برنامه حتی کوچک کار سختی است. در زبان پایتون برای دسته‌بندی و جلوگیری از تداخل نام‌ها ساختاری با عنوان «**فضاهای نام**» (Namespaces) در نظر گرفته شده است؛ هر فضا نام بخشی از نام‌های درون برنامه را دربر می‌گیرد. فضاهای نام‌ متفاوت نسبت به یکدیگر ایزوله هستند؛ بنابراین در فضاهای نام‌ متفاوت می‌توان از نام‌های یکسان استفاده کرد. به صورت کلی فضاهای نام پایتون در سه سطح تو در توی «محلی» (Local)، «سراسری» (Global) و Built-in به تصویر کشیده می‌شوند: + +.. image:: /_static/nested-namespaces-python.jpg + :align: center + +هر ماژول پایتون فضانام سراسری خود را دارد. فضانام تمام ماژول‌ها درون فضانام بزرگتری ایجاد می‌گردد که به عنوان فضانام Built-in شناخته می‌شود و نام تمامی توابع آماده مانند ``()open`` که پیش از این استفاده می کردیم در این فضا قرار گرفته است. به همین دلیل است که بدون نیاز به import ماژول خاصی در هر جای برنامه به توابع آماده (Built-in) دسترسی داریم ولی برای استفاده از توابع داخل هر ماژول می‌بایست ابتدا آن ماژول را import کرده تا توسط فضا نام ماژول مربوطه به نام‌های درون آن دسترسی پیدا کنیم. + +هر ماژول می‌تواند شامل تعدادی تابع و کلاس باشد. با فراخوانی هر تابع یک فضانام محلی داخل فضانام ماژول آن ایجاد می‌گردد و با پایان اجرا نیز از بین می‌رود، در مورد کلاس‌ها هم اتفاق مشابهی رخ می‌دهد. + + + + + +ارسال آرگومان +-------------- + + + + + + + +| + +---- + +:emoji-size:`😊` امیدوارم مفید بوده باشه + +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ + + From 6e636cf7353770f373b0ecd1854f355c471056dd Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Sun, 9 Jul 2017 13:02:53 +0430 Subject: [PATCH 013/316] review l12 --- lessons/l12.rst | 153 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 5 deletions(-) diff --git a/lessons/l12.rst b/lessons/l12.rst index 87eb0b4..33dd9a6 100644 --- a/lessons/l12.rst +++ b/lessons/l12.rst @@ -108,19 +108,162 @@ """ -فضاهای نام ------------ -در هر برنامه پایتون تعداد زیادی نام وجود دارد که برای نمونه می‌توان به: متغیرها که پیش‌تر اشاره شد و می‌دانیم، متغیرها نام‌هایی هستند که به اشیا (از انواع مختلف) ارجاع دارند، نام توابع که به اشیایی از نوع تابع ارجاع دارند، نام کلاس‌ها که به اشیایی از نوع کلاس ارجاع دارند و... اشاره کرد. بدیهی است که برای شناسایی اشیا لازم است نام‌ها منحصر به فرد باشند، رعایت چنین امری در یک برنامه حتی کوچک کار سختی است. در زبان پایتون برای دسته‌بندی و جلوگیری از تداخل نام‌ها ساختاری با عنوان «**فضاهای نام**» (Namespaces) در نظر گرفته شده است؛ هر فضا نام بخشی از نام‌های درون برنامه را دربر می‌گیرد. فضاهای نام‌ متفاوت نسبت به یکدیگر ایزوله هستند؛ بنابراین در فضاهای نام‌ متفاوت می‌توان از نام‌های یکسان استفاده کرد. به صورت کلی فضاهای نام پایتون در سه سطح تو در توی «محلی» (Local)، «سراسری» (Global) و Built-in به تصویر کشیده می‌شوند: +فضاهای نام و حوزه +------------------ + +در هر برنامه پایتون تعداد زیادی نام وجود دارد که برای نمونه می‌توان به: متغیرها، نام توابع، نام کلاس‌ها و... اشاره کرد. بدیهی است که برای شناسایی اشیا لازم است نام‌ها منحصر به فرد باشند، رعایت چنین امری در یک برنامه حتی کوچک کار سختی است. در زبان پایتون برای دسته‌بندی و جلوگیری از تداخل نام‌ها، ساختاری با عنوان «**فضاهای نام**» (**Namespaces**) در نظر گرفته شده است. هر فضا نام بخشی از نام‌های درون برنامه را دربر‌می‌گیرد. به صورت کلی فضاهای نام پایتون در سه سطح تو در توی «محلی» (Local)، «سراسری» (Global) و Built-in به تصویر کشیده می‌شوند: .. image:: /_static/nested-namespaces-python.jpg :align: center -هر ماژول پایتون فضانام سراسری خود را دارد. فضانام تمام ماژول‌ها درون فضانام بزرگتری ایجاد می‌گردد که به عنوان فضانام Built-in شناخته می‌شود و نام تمامی توابع آماده مانند ``()open`` که پیش از این استفاده می کردیم در این فضا قرار گرفته است. به همین دلیل است که بدون نیاز به import ماژول خاصی در هر جای برنامه به توابع آماده (Built-in) دسترسی داریم ولی برای استفاده از توابع داخل هر ماژول می‌بایست ابتدا آن ماژول را import کرده تا توسط فضا نام ماژول مربوطه به نام‌های درون آن دسترسی پیدا کنیم. +هر ماژول پایتون یک فضانام سراسری برای خود تشکیل می‌دهد که نسبت به فضا نام دیگر ماژول‌ها ایزوله است. فضانام تمام ماژول‌ها درون فضانام بزرگتری ایجاد می‌گردند که به عنوان فضانام Built-in شناخته می‌شود و نام تمامی توابع آماده مانند ``()open`` که پیش از این استفاده می‌کردیم در این فضا قرار گرفته است. ساختار تو در توی سطوح فضا نام باعث می‌شود که بدون نیاز به import ماژول خاصی در هر جای برنامه به توابع آماده (Built-in) دسترسی داشته باشیم. + +هر ماژول می‌تواند شامل تعدادی تابع و کلاس باشد. با فراخوانی هر تابع یک فضانام محلی برای آن تابع، درون فضانام ماژول مربوطه ایجاد می‌گردد و با پایان اجرای تابع نیز از بین می‌رود، در مورد کلاس‌ها هم اتفاق مشابهی رخ می‌دهد. بر همین اساس می‌توانیم درون تابع متغیرهایی متفاوت ولی هم نام با متغیرهای خارج از تابع در ماژول **ایجاد** نماییم چرا که آن‌ها در دو فضانام متفاوت قرار دارند و از طرفی به دلیل داخل بودن فضا نام تابع درون فضا نام ماژول خود، می‌توان به نام‌های خارج از تابع نیز دسترسی داشت. + +گفتیم فضا نام ماژول‌ها نسبت به یکدیگر ایزوله هستند. بنابراین برای دسترسی به نام‌های درون ماژول‌های دیگر، ابتدا می‌بایست آن‌ ماژول‌ها را import نماییم که در این صورت با استفاده از نام ماژول - به شکل یک پیشوند - قابل دستیابی هستند. برای نمونه دستیابی نام ``getcwd`` که به یک تابع ارجاع دارد از فضانام ماژول ``os``، در نمونه کد پایین نمایش داده شده است:: + + >>> import os + + >>> os.getcwd() + '/home/saeid' + +اما استفاده از نام‌های یک ماژول درون خودش چگونه است؟ جایی که فضا‌های نام دیگری همچون توابع نیز وجود دارند ولی هیچ پیشوندی مانند نام ماژول وجود ندارد که بتوان نام‌های درون این فضاهای متفاوت را از یکدیگر تمیز داد. برای اینکه بدانیم هر نام ماژول در هر نقطه‌ایی از همان ماژول چگونه مورد دستیابی قرار می‌گیرد با مفهوم دیگری به نام «**حوزه**» (**Scope**) آشنا می‌شویم. به صورت کلی حوزه به نواحی‌ایی از برنامه گفته می‌شود که می‌توان یک نام را بدون استفاده از هیچ پیشوندی و البته بدون تداخل با نام‌های دیگر به کار برد. بحث حوزه صرفا در داخل هر ماژول مطرح است. + +*قوانین حوزه:* + +* بدنه ماژول - منظور نواحی‌ایی که خارج از بدنه توابع و کلاس‌ها قرار دارد - **حوزه سراسری** (**Global Scope**) است. توجه داشته باشید که واژه «سراسری» در بحث حوزه (یا فضانام) تنها به سراسر کدهای داخل هر ماژول اشاره دارد و نه سراسر برنامه. به صورت کلی هر جایی از زبان پایتون که واژه سراسری (Global) را شنیدید (یا خواندید) به یاد ماژول بیافتید:: + + # This is a global variable + a = 0 + + if a == 0: + # This is still a global variable + b = 1 -هر ماژول می‌تواند شامل تعدادی تابع و کلاس باشد. با فراخوانی هر تابع یک فضانام محلی داخل فضانام ماژول آن ایجاد می‌گردد و با پایان اجرا نیز از بین می‌رود، در مورد کلاس‌ها هم اتفاق مشابهی رخ می‌دهد. + *در نمونه کد بالا، حوزه تعریف هر دو متغیر a و b از نوع سراسری است. بدنه دستورات کنترلی فاقد یک فضانام جداگانه است و تعریف متغیر در این نواحی از برنامه درون حوزه سراسری قرار می‌گیرد.* + | +* بدنه هر تابع یک **حوزه محلی** (**Local Scope**) است و به صورت پیش‌فرض تمام متغیرهایی که درون توابع ایجاد می‌گردند درون حوزه محلی قرار گرفته‌اند مگر اینکه با استفاده از کلمه‌های کلیدی ``global`` یا ``nonlocal`` مشخص شده باشند. چنانچه بخواهیم درون تابع انتسابی به یکی از نام‌های موجود در حوزه سراسری انجام دهیم، می‌بایست از دستور ``global`` استفاده کنیم. به نمونه کدهای پایین توجه نمایید:: + + + def my_function(c): + # this is a local variable + d = 3 + + + :: + + >>> a = 0 + >>> + >>> def my_function(): + ... a = 3 + ... print(a) + ... + >>> + >>> a + 0 + >>> my_function() + 3 + >>> a + 0 + >>> + + :: + + >>> a = 0 + >>> + >>> def my_function(): + ... global a + ... a = 3 + ... print(a) + ... + >>> + >>> a + 0 + >>> my_function() + 3 + >>> a + 3 + >>> + + در توابع تو در تو نیز فرقی ندارد، هر تابع که فراخوانی می‌شود فضانامی مجزا برای آن ایجاد می‌شود و حوزه محلی خود را خواهد داشت. دستور ``nonlocal`` در پایتون ۳ ارائه شده است و در توابع تو در تو کاربرد دارد. هنگامی که بخواهیم داخل بدنه تابع درونی انتسابی به نامی تعریف شده در یکی از توابع بیرونی آن انجام دهیم، می‌بایست از این دستور برای مشخص کردن نام مورد نظر استفاده کنیم:: + + >>> def outer(): + ... x = 1 + ... def inner(): + ... x = 2 + ... print("inner:", x) + ... inner() + ... print("outer:", x) + ... + >>> + >>> outer() + inner: 2 + outer: 1 + >>> + + :: + + >>> def outer(): + ... x = 1 + ... def inner(): + ... nonlocal x + ... x = 2 + ... print("inner:", x) + ... inner() + ... print("outer:", x) + ... + >>> + >>> outer() + inner: 2 + outer: 2 + >>> + +* وقتی از متغیری استفاده می‌کنیم، مفسر پایتون ابتدا می‌بایست حوزه و فضانام آن را تشخیص دهد تا بتواند شی‌ایی که این متغیر به آن ارجاع دارد را پیدا کند. فرض کنیم متغیری درون عبارتی در بدنه یک تابع به کار رفته باشد در این صورت مفسر ابتدا حوزه محلی که متغیر در آن وجود دارد را برای یافتن تعریف متغیر جستجو می‌کند و چنانچه نیابد به سراغ حوزه محلی تابع بیرونی آن - در صورت وجود - می‌رود و همینطور ادامه می‌دهد که در نهایت حوزه سراسری ماژول و پس از آن نیز Built-in را بررسی می‌کند؛ اگر هم به نتیجه‌ایی نرسد یک استثنا ``NameError`` رخ می‌دهد:: + + >>> x = 0 + >>> + >>> def outer(): + ... x = 1 + ... def inner(): + ... print(x) + ... inner() + ... + >>> outer() + 1 + + :: + + >>> x = 0 + >>> + >>> def outer(): + ... def inner(): + ... print(x) + ... inner() + ... + >>> outer() + 0 + + + :: + + >>> x = 0 + >>> + >>> def outer(): + ... def inner(): + ... print(z) + ... inner() + ... + >>> outer() + Traceback (most recent call last): + File "", line 1, in + File "", line 4, in outer + File "", line 3, in inner + NameError: name 'z' is not defined + >>> + ارسال آرگومان From b9e95b2a94e908f8716dcb4295332e088329d37a Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Mon, 10 Jul 2017 22:29:56 +0430 Subject: [PATCH 014/316] l12 - write: passing arguments & argument matching --- _static/l12-python-passing-arguments-01.png | Bin 0 -> 32699 bytes _static/l12-python-passing-arguments-02.png | Bin 0 -> 63335 bytes lessons/l12.rst | 208 ++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 _static/l12-python-passing-arguments-01.png create mode 100644 _static/l12-python-passing-arguments-02.png diff --git a/_static/l12-python-passing-arguments-01.png b/_static/l12-python-passing-arguments-01.png new file mode 100644 index 0000000000000000000000000000000000000000..01e8fe681fa7f1466f7c9fea6a8f5ded048aee7c GIT binary patch literal 32699 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 z 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 def f(a): + ... print(a*a) + ... + >>> + >>> b = 3 + >>> f(b) + 9 + +*با فراخوانی تابع f در نمونه کد بالا، متغیر محلی a ایجاد می‌گردد که به شی صحیح 3 اشاره دارد.* + +توجه داشته باشید که با انتساب شی‌ایی جدید به پارامترهای تابع، عملا ارسال آرگومان بی‌تاثیر می‌گردد:: + + >>> def f(a): + ... a = 2 + ... print(a*a) + ... + >>> b = 3 + >>> f(b) + 4 + + +**نکته مهم در ارسال آرگومان، توجه به چگونگی آن است!** + +در بین زبان‌های برنامه‌نویسی دو شیوه برای ارسال آرگومان‌ رایج است: **”by value“** و **”by reference“**. در شیوه by value یک کپی از مقدار آرگومان به تابع ارسال می‌گردد و در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان ارسال شده در خارج از تابع بدون تغییر باقی می‌ماند. به مثال پایتونی پایین توجه نمایید:: + + >>> def f(a): + ... a = 2 + ... print(a*a) + ... + >>> b = 3 + >>> f(b) + 4 + >>> b + 3 + +*همانطور که در نمونه کد بالا قابل مشاهده است، مقدار متغییر b بدون تغییر باقی مانده است.* + +ولی در شیوه by reference به جای ارسال یک کپی از مقدار آرگومان، یک ارجاع (reference) به آن آرگومان به تابع ارسال می‌گردد. می‌توان این‌طور در نظر گرفت که پارامتر متناظر در تابع، همان آرگومان در خارج از تابع است. در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان در خارج از تابع نیز تغییر می‌کند. به مثال پایتونی پایین توجه نمایید:: + + >>> def f(a): + ... a[0] = 3 + ... print(a) + ... + >>> b = [1, 2] + >>> f(b) + [3, 2] + >>> b + [3, 2] + +این دو از شیوه‌‌های مرسوم در زبان‌های برنامه‌نویسی هستند ولی ارسال پارامتر به صورت خاص در زبان برنامه‌نویسی پایتون چگونه است؟ در پایتون هر چیزی یک شی است و در نتیجه ارسال آرگومان‌ها در هر شرایطی به صورت **”by reference“** انجام می‌پذیرد. + +و اگر سوال شود که علت تفاوت رفتار در دو مثال قبل چیست؟ باید بدانیم که علت به ماهیت اشیای آرگومان‌های ارسالی مربوط است. ارسال اشیای تغییرناپذیر (Immutable) به مانند انواع بولین، اعداد، رشته و تاپل به تابع، باعث بروز رفتاری مشابه با شیوه by value می‌شود ولی در مورد ارسال اشیای تغییرپذیر (Mutable) به مانند انواع لیست، دیکشنری و مجموعه اینگونه نخواهد بود. به تصاویر پایین توجه نمایید: + +.. image:: /_static/l12-python-passing-arguments-01.png + :align: center + +.. image:: /_static/l12-python-passing-arguments-02.png + :align: center + +اشیای تغییرپذیر در پایتون اشیایی هستند که بدون تغییر ``()id‍‍`` آن‌ها، مقدارشان قابل تغییر است. خروجی تابع ``()id‍‍`` برای هر شی بیانگر شناسه منحصر به فرد آن شی است که در واقع نشانی آن در حافظه نیز می‌باشد [`اسناد پایتون `__] - درس پنجم. + +برای جلوگیری از تغییر اشیای تغییرپذیر درون تابع، می‌توان به گونه‌ایی که در درس هشتم گفته شد یک کپی از این نوع اشیا را ایجاد و سپس به صورت آرگومان به تابع ارسال کرد:: + + >>> def f(a): + ... a[0] = 3 + ... print(a) + ... + >>> b = [1, 2] + >>> f(b[:]) # Pass a copy + [3, 2] + >>> b + [1, 2] + +در نمونه کد بالا، از آنجایی که تمام اعضای شی لیست متغیر b تماما از انواع تغییرناپذیر هستند، یک کپی سطحی (Shallow Copy) از شی کفایت می‌کند ولی در حالتی غیر از این می‌بایست یک کپی عمیق (Deep Copy) از شی ارسال گردد - درس هشتم. + +البته گاهی واقعا نیاز است که مقدار تغییر یافته از متغیری که به تابع ارسال می‌شود را نیز بیرون از تابع هم در اختیار داشته باشیم. برای این منظور در برخی از زبان‌های برنامه‌نویسی امکان ارسال به شیوه by reference بنابر خواست برنامه‌نویس فراهم شده است. برای مثال در زبان php این کار با قرار دادن یک ``&`` در پشت پارامتر مورد نظر انجام می‌پذیرد: + +.. code-block:: php + + + +در پایتون چنین قابلیتی وجود ندارد، حداقل برای اشیای تغییرناپذیر! ولی می‌توان با استفاده از امکان بازگشت چندین شی توسط دستور ``return``، آن را پوشش داد. با استفاده از این شیوه می‌توان هر تعداد از پارمترهای مورد نیاز خود را به خارج از تابع انتقال داد:: + + >>> def multiple(x, y): + ... x = 2 + ... y = [3, 4] + ... return x, y + ... + >>> X = 1 + >>> Y = [1, 2] + >>> + >>> X, Y = multiple(X, Y) + >>> + >>> X + 2 + >>> Y + [3, 4] + +توجه داشته باشید که در این حالت دستور ``return`` تمام این اشیا را در قالب یک شی تاپل برمی‌گرداند:: + + >>> multiple(X, Y) + (2, [3, 4]) + + +تطابق آرگومان‌ها +------------------ +پیش‌تر به لزوم همخوانی تعداد آرگومان‌های ارسالی با پارامترهای موجود در سرآیند تابع اشاره شد:: + + >>> def f(a, b, c): + ... pass + ... + >>> + >>> f(1, 2) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() missing 1 required positional argument: 'c' + >>> + >>> f(1, 2, 3, 4) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() takes 3 positional arguments but 4 were given + >>> + +در ادامه به ارایه انواع سینتکس‌های مورد قبول پایتون در تطابق آرگومان‌ها (Argument Matching) با پارامتر‌های تابع می‌پردازیم: + +* سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت در ازای هر پارامتر یک آرگومان نظیر ارسال گردد. عمل تطابق در این سینتکس بر اساس موقعیت آرگومان‌ها انجام می‌شود که در نتیجه می‌بایست ترتیب آرگومان‌ها، متناظر با ترتیب پارامترها در سرآیند تابع باشد:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> f(1, 2, 3) + 1 2 3 + + +* سینتکس نام=مقدار، در این سینتکس آرگومان‌ها به نام پارامترها انتساب داده می‌شوند و از آنجا که عمل تطابق بر اساس نام پارامترها انجام می‌شود دیگر موقعیت یا ترتیب آرگومان‌ها اهمیتی ندارد:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> f(a=1, c=3, b=2) + 1 2 3 + + می‌توان از این دو سینتکس به صورت ترکیبی نیز استفاده کرد. فقط باید توجه داشت آرگومان‌هایی که عمل تطابق آن‌ها وابسته به موقعیت است را - با رعایت ترتیب موارد قبل‌تر از آن - در ابتدا قرار دهیم. به مثال پایین توجه نمایید:: + + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> f(1, c=3, b=2) + 1 2 3 + >>> f(1, 2, c=3) + 1 2 3 + >>> f(1, 2, 3) + 1 2 3 + + برای تابع مثال بالا، حالت‌های فراخوانی پایین نادرست هستند:: + + >>> f(c=3, b=2, 1) + File "", line 1 + SyntaxError: positional argument follows keyword argument + + >>> f(a=1, 2, c=3) + File "", line 1 + SyntaxError: positional argument follows keyword argument + + >>> f(a=1, 2, 3) + File "", line 1 + SyntaxError: positional argument follows keyword argument + + >>> f(2, a=1, c=3) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() got multiple values for argument 'a' + + +* سینتکس ``iterable*``، در این سینتکس یک شی از نوع تکرارپذیر (iterable - درس نهم) مانند انواع رشته، تاپل، لیست و... که توسط یک کاراکتر ستاره ``*‍‍`` نشانه‌گذاری شده است، به تابع ارسال می‌گردد. در این صورت بر اساس ترتیب موقعیت، اعضای درون شی تکرارپذیر به پارامتر‌های تابع اختصاص می‌یابند:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> b = [1, 2, 3] + >>> f(*b) + 1 2 3 + + +* سینتکس ``dict**``، در این سینتکس یک شی دیکشنری که توسط دو کاراکتر ستاره ``**`` نشانه‌گذاری شده است به تابع ارسال می‌شود. کلید‌های این شی دیکشنری می‌بایست هم‌نام با پارامترهای تعریف شده در سرآیند تابع باشند. پس از فراخوانی تابع، این شی دیکشنری باز می‌شود و بر اساس نام کلید در جفت‌های کلید:مقدار درون آن، پارامترهای تابع مقداردهی می‌شوند:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> b = {'a':1, 'c':3, 'b':2} + >>> f(**b) + 1 2 3 + +این چهار سینتکس بر اعمال در هنگام فراخوانی تابع بحث می‌کنند و در تمام آن‌ها می‌بایست تعداد آرگومان‌های ارسالی با تعداد پارامترهای تعریف شده در سرآیند تابع برابر باشد و البته بدیهی است که در دو سینتکس پایانی لازم است تعداد اعضای شی تکرارپذیر یا تعداد جفت‌های کلید:مقدار شی دیکشنری با تعداد پارامترهای تابع برابر باشند. + +در ادامه به ارایه سینتکس‌هایی در این زمینه می‌پردازیم که در تعریف پارامترهای تابع نقش دارند. From f30b27c6b718d99ee195e8a395d92f8d4cfd23f3 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Sat, 1 Jun 2019 21:33:41 +0430 Subject: [PATCH 015/316] edit l07 --- index.rst | 1 - lessons/l07.rst | 2 +- lessons/l12.rst | 494 ------------------------------------------------ 3 files changed, 1 insertion(+), 496 deletions(-) delete mode 100644 lessons/l12.rst diff --git a/index.rst b/index.rst index 8151cf6..f1f3e2b 100644 --- a/index.rst +++ b/index.rst @@ -26,7 +26,6 @@ lessons/l09 lessons/l10 lessons/l11 - lessons/l12 log | diff --git a/lessons/l07.rst b/lessons/l07.rst index 5a08247..a5d54d4 100644 --- a/lessons/l07.rst +++ b/lessons/l07.rst @@ -1042,7 +1042,7 @@ .. rubric:: تبدیل کد به کاراکتر و برعکس -می‌دانیم برای اینکه کامپیوتر بتواند کاراکتر‌ها را درک کند نیاز به سیستم‌هایی است که آن‌ها را برای تبدیل به کدهای پایه دو کدگذاری کند؛ به مانند سیستم اَسکی (ASCII) یا سیستم‌های جامع‌تری مانند UTF-8 که تحت استاندارد یونیکد (Unicode) در دسترس هستند. گاهی نیاز است به این کدها دسترسی داشته باشیم و با کاراکترها بر اساس آن‌ها کار کنیم؛ برای این منظور در پایتون می‌توان از دو تابع ``()ord`` (تبدیل کد به کاراکتر) [`اسناد پایتون `__] و ``()chr`` (تبدیل کاراکتر به کد) [`اسناد پایتون `__] استفاده کرد. تابع ``()ord`` یک رشته تک کاراکتری را گرفته و یک عدد (در پایه ده) که بیانگر کد کاراکتر مورد نظر می‌باشد را برمی‌گرداند. تابع ``()chr`` نیز کد کاراکتری (که می‌بایست عددی در پایه ده باشد) را گرفته و کاراکتر مربوط به آن را برمی‌گرداند:: +می‌دانیم برای اینکه کامپیوتر بتواند کاراکتر‌ها را درک کند نیاز به سیستم‌هایی است که آن‌ها را برای تبدیل به کدهای پایه دو کدگذاری کند؛ به مانند سیستم اَسکی (ASCII) یا سیستم‌های جامع‌تری مانند UTF-8 که تحت استاندارد یونیکد (Unicode) در دسترس است. گاهی نیاز است به این کدها دسترسی داشته باشیم و با کاراکترها بر اساس آن‌ها کار کنیم؛ برای این منظور در پایتون می‌توان از دو تابع ``()ord`` (تبدیل کد به کاراکتر) [`اسناد پایتون `__] و ``()chr`` (تبدیل کاراکتر به کد) [`اسناد پایتون `__] استفاده کرد. تابع ``()ord`` یک رشته تک کاراکتری را گرفته و یک عدد (در پایه ده) که بیانگر کد کاراکتر مورد نظر می‌باشد را برمی‌گرداند. تابع ``()chr`` نیز کد کاراکتری (که می‌بایست عددی در پایه ده باشد) را گرفته و کاراکتر مربوط به آن را برمی‌گرداند:: >>> # Python 3.x - GNU/Linux diff --git a/lessons/l12.rst b/lessons/l12.rst deleted file mode 100644 index 873bd3e..0000000 --- a/lessons/l12.rst +++ /dev/null @@ -1,494 +0,0 @@ -.. role:: emoji-size - -.. meta:: - :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس دوازدهم تابع - :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, پایتون - - -درس ۱۲: تابع -============ - - - - - - - - -:emoji-size:`✔` سطح: متوسط - ----- - - -.. contents:: سرفصل‌ها - :depth: 2 - ----- - - - -مقدمه ------- - -**تابع (Function)** به بلاکی از دستورات گفته می‌شود که برای به اجرا درآمدن نیازمند فراخوانی هستند و این فراخوانی می‌تواند بیش از یک بار در برنامه انجام گیرد. تابع می‌تواند به هنگام فراخوانی مقادیری را دریافت کند و در صورت لزوم مقداری نیز به عنوان نتیجه برگرداند. - -تابع جایگزینی برای بخش‌های تکراری برنامه است که با یک بار نوشتن و چندین بار فراخوانی و اجرای آن می‌توان از پیچیدگی برنامه جلوگیری و تغییر در آن را آسان نمود. استفاده از توابع باعث بالابردن قابلیت استفاده مجدد از کدها می‌شود و افزونگی را نیز کاهش می‌دهد. توابع ابزاری برای خرد کردن منطق برنامه به واحدهای اجرایی کوچکتر برای تسهیل ساخت برنامه‌های بزرگ است. - -سینتکس تابع در زبان برنامه‌نویسی پایتون همانند هر دستور مرکب دیگری شامل یک سرآیند و یک بدنه است - درس ششم. بخش سرآیند شامل کلمه کلیدی ``def``، یک نام به دلخواه کاربر و پرانتز‌ می‌باشد که این پرانتز‌ محل قرار گرفتن پارامترهای تابع را نمایش می‌دهد. هر تابع می‌تواند هیچ، یک یا چند پارامتر بپذیرد:: - - def function_name(param1, param2,... paramN): - statements - -همانطور که بارها گفته شد، هر چیزی در پایتون شی است، هنگامی که اجرای برنامه به کلمه کلیدی ``def`` می‌رسد، ابتدا یک شی تابع ایجاد و سپس از نام تابع (در اینجا: function_name) به آن ارجاع داده می‌شود:: - - >>> def func_name(): - ... pass - ... - >>> - >>> type(func_name) - - -.. tip:: - پیشنهاد `PEP 8 `__: نام تابع از حروف کوچک تشکیل شود که کلمه‌های آن با استفاده از خط زیرین (Underscores) از یکدیگر جدا شده باشند. مانند: my_function . حالت ``mixedCase`` مانند: myFunction نیز صحیح می‌باشد به شرط آنکه در سراسر کدها نام توابع با همین الگو نوشته شود. - -بدنه تا زمانی که تابع فراخوانی نگردد، اجرا نمی‌شود. برای فراخوانی تابع از نام تابع + پرانتز استفاده می‌شود و در صورتی که در تعریف تابع پارامترهایی قرار داده شده باشد، می‌بایست هنگام فراخوانی آرگومان‌های متناسب با این پارامترها نیز ارسال گردند:: - - function_name(arg1, arg2,... argN) - - -.. caution:: - در بحث توابع، به متغیرهایی که در سرآیند تابع تعریف می‌شوند پارامتر (Parameter) و به داده‌هایی که هنگام فراخوانی تابع ارسال می‌گردد آرگومان (Argument) گفته می‌شود. به ازای هر آرگومان ارسالی می‌بایست یک پارامتر در تابع جهت دریافت آن تعریف شده باشد. هیچ الزامی به هم نام بودن آرگومان‌ها و پارامترهای نظیر وجود ندارد ولی وجود هم نامی باعث خوانایی بیشتر کد می‌شود. - - - -بدنه تابع می تواند حاوی کلمه کلیدی ``return`` نیز باشد. در واقع ``return`` دستوری است که در هر جایی از بدنه آورده شود، اجرای تابع در آن نقطه متوقف و مقداری (البته در زبان پایتون درست این است که گفته شود: شی‌ایی) را به عنوان نتیجه به محل فراخوانی تابع بازمی‌گرداند:: - - def function_name(param1, param2,... paramN): - ... - return value - -در نمونه کد بالا value مقداری است که توسط ``return`` به محل فراخوانی بازگردانده می‌شود. value می‌تواند صراحتا یک مقدار نباشد بلکه یک عبارت مانند : ``param1**2`` یا ``param1 > 3`` و... باشد که در این صورت ابتدا حاصل عبارت ارزیابی و سپس بازگردانده می‌شود. چنانچه value ذکر نگردد، ``None`` بازگردانده می‌شود:: - - >>> def my_pow(x, y): - ... return x**y - ... - >>> - >>> a = 2 - >>> b = 3 - >>> - >>> my_pow(a, b) - 8 - >>> - -در زبان برنامه نویسی پایتون تابع یک موجودیت **”first-class“** است که یعنی تابع را می‌توان مانند دیگر اشیا به صورت پویا ایجاد یا نابود کرد، به صورت آرگومان به توابع دیگر ارسال نمود، به عنوان نتیجه توسط ``return`` بازگرداند و... در نتیجه می‌توان یک تابع را درون بدنه دستورات کنترلی (``while`` ،``if`` و...) یا درون بدنه تابعی دیگر تعریف نمود:: - - >>> def outer(num1): - ... def inner_increment(num1): # hidden from outer code - ... return num1 + 1 - ... num2 = inner_increment(num1) - ... print(num1, num2) - ... - >>> - >>> outer(1) - 1 2 - - -خیلی خوب است که با استفاده از ”Docstring“ در توابع به مستندسازی و خوانایی بهتر برنامه کمک کنیم - درس ششم:: - - - def function_with_docstring(param1, param2): - """Example function with types documented in the docstring. - - Args: - param1 (int): The first parameter. - param2 (str): The second parameter. - - Returns: - bool: The return value. True for success, False otherwise. - """ - - -فضاهای نام و حوزه ------------------- - -در هر برنامه پایتون تعداد زیادی نام وجود دارد که برای نمونه می‌توان به: متغیرها، نام توابع، نام کلاس‌ها و... اشاره کرد. بدیهی است که برای شناسایی اشیا لازم است نام‌ها منحصر به فرد باشند، رعایت چنین امری در یک برنامه حتی کوچک کار سختی است. در زبان پایتون برای دسته‌بندی و جلوگیری از تداخل نام‌ها، ساختاری با عنوان «**فضاهای نام**» (**Namespaces**) در نظر گرفته شده است. هر فضا نام بخشی از نام‌های درون برنامه را دربر‌می‌گیرد. به صورت کلی فضاهای نام پایتون در سه سطح تو در توی «محلی» (Local)، «سراسری» (Global) و Built-in به تصویر کشیده می‌شوند: - -.. image:: /_static/nested-namespaces-python.jpg - :align: center - -هر ماژول پایتون یک فضانام سراسری برای خود تشکیل می‌دهد که نسبت به فضا نام دیگر ماژول‌ها ایزوله است. فضانام تمام ماژول‌ها درون فضانام بزرگتری ایجاد می‌گردند که به عنوان فضانام Built-in شناخته می‌شود و نام تمامی توابع آماده مانند ``()open`` که پیش از این استفاده می‌کردیم در این فضا قرار گرفته است. ساختار تو در توی سطوح فضا نام باعث می‌شود که بدون نیاز به import ماژول خاصی در هر جای برنامه به توابع آماده (Built-in) دسترسی داشته باشیم. - -هر ماژول می‌تواند شامل تعدادی تابع و کلاس باشد. با فراخوانی هر تابع یک فضانام محلی برای آن تابع، درون فضانام ماژول مربوطه ایجاد می‌گردد و با پایان اجرای تابع نیز از بین می‌رود، در مورد کلاس‌ها هم اتفاق مشابهی رخ می‌دهد. بر همین اساس می‌توانیم درون تابع متغیرهایی متفاوت ولی هم نام با متغیرهای خارج از تابع در ماژول **ایجاد** نماییم چرا که آن‌ها در دو فضانام متفاوت قرار دارند و از طرفی به دلیل داخل بودن فضا نام تابع درون فضا نام ماژول خود، می‌توان به نام‌های خارج از تابع نیز دسترسی داشت. - -گفتیم فضا نام ماژول‌ها نسبت به یکدیگر ایزوله هستند. بنابراین برای دسترسی به نام‌های درون ماژول‌های دیگر، ابتدا می‌بایست آن‌ ماژول‌ها را import نماییم که در این صورت با استفاده از نام ماژول - به شکل یک پیشوند - قابل دستیابی هستند. برای نمونه دستیابی نام ``getcwd`` که به یک تابع ارجاع دارد از فضانام ماژول ``os``، در نمونه کد پایین نمایش داده شده است:: - - >>> import os - - >>> os.getcwd() - '/home/saeid' - -اما استفاده از نام‌های یک ماژول درون خودش چگونه است؟ جایی که فضا‌های نام دیگری همچون توابع نیز وجود دارند ولی هیچ پیشوندی مانند نام ماژول وجود ندارد که بتوان نام‌های درون این فضاهای متفاوت را از یکدیگر تمیز داد. برای اینکه بدانیم هر نام ماژول در هر نقطه‌ایی از همان ماژول چگونه مورد دستیابی قرار می‌گیرد با مفهوم دیگری به نام «**حوزه**» (**Scope**) آشنا می‌شویم. به صورت کلی حوزه به نواحی‌ایی از برنامه گفته می‌شود که می‌توان یک نام را بدون استفاده از هیچ پیشوندی و البته بدون تداخل با نام‌های دیگر به کار برد. بحث حوزه صرفا در داخل هر ماژول مطرح است. - -*قوانین حوزه:* - -* بدنه ماژول - منظور نواحی‌ایی که خارج از بدنه توابع و کلاس‌ها قرار دارد - **حوزه سراسری** (**Global Scope**) است. توجه داشته باشید که واژه «سراسری» در بحث حوزه (یا فضانام) تنها به سراسر کدهای داخل هر ماژول اشاره دارد و نه سراسر برنامه. به صورت کلی هر جایی از زبان پایتون که واژه سراسری (Global) را شنیدید (یا خواندید) به یاد ماژول بیافتید:: - - # This is a global variable - a = 0 - - if a == 0: - # This is still a global variable - b = 1 - - *در نمونه کد بالا، حوزه تعریف هر دو متغیر a و b از نوع سراسری است. بدنه دستورات کنترلی فاقد یک فضانام جداگانه است و تعریف متغیر در این نواحی از برنامه درون حوزه سراسری قرار می‌گیرد.* - - | - - -* بدنه هر تابع یک **حوزه محلی** (**Local Scope**) است و به صورت پیش‌فرض تمام متغیرهایی که درون توابع ایجاد می‌گردند درون حوزه محلی قرار گرفته‌اند مگر اینکه با استفاده از کلمه‌های کلیدی ``global`` یا ``nonlocal`` مشخص شده باشند. چنانچه بخواهیم درون تابع انتسابی به یکی از نام‌های موجود در حوزه سراسری انجام دهیم، می‌بایست از دستور ``global`` استفاده کنیم. به نمونه کدهای پایین توجه نمایید:: - - - def my_function(c): - # this is a local variable - d = 3 - - - :: - - >>> a = 0 - >>> - >>> def my_function(): - ... a = 3 - ... print(a) - ... - >>> - >>> a - 0 - >>> my_function() - 3 - >>> a - 0 - >>> - - :: - - >>> a = 0 - >>> - >>> def my_function(): - ... global a - ... a = 3 - ... print(a) - ... - >>> - >>> a - 0 - >>> my_function() - 3 - >>> a - 3 - >>> - - در توابع تو در تو نیز فرقی ندارد، هر تابع که فراخوانی می‌شود فضانامی مجزا برای آن ایجاد می‌شود و حوزه محلی خود را خواهد داشت. دستور ``nonlocal`` در پایتون ۳ ارائه شده است و در توابع تو در تو کاربرد دارد. هنگامی که بخواهیم داخل بدنه تابع درونی انتسابی به نامی تعریف شده در یکی از توابع بیرونی آن انجام دهیم، می‌بایست از این دستور برای مشخص کردن نام مورد نظر استفاده کنیم:: - - >>> def outer(): - ... x = 1 - ... def inner(): - ... x = 2 - ... print("inner:", x) - ... inner() - ... print("outer:", x) - ... - >>> - >>> outer() - inner: 2 - outer: 1 - >>> - - :: - - >>> def outer(): - ... x = 1 - ... def inner(): - ... nonlocal x - ... x = 2 - ... print("inner:", x) - ... inner() - ... print("outer:", x) - ... - >>> - >>> outer() - inner: 2 - outer: 2 - >>> - -* وقتی از متغیری استفاده می‌کنیم، مفسر پایتون ابتدا می‌بایست حوزه و فضانام آن را تشخیص دهد تا بتواند شی‌ایی که این متغیر به آن ارجاع دارد را پیدا کند. فرض کنیم متغیری درون عبارتی در بدنه یک تابع به کار رفته باشد در این صورت مفسر ابتدا حوزه محلی که متغیر در آن وجود دارد را برای یافتن تعریف متغیر جستجو می‌کند و چنانچه نیابد به سراغ حوزه محلی تابع بیرونی آن - در صورت وجود - می‌رود و همینطور ادامه می‌دهد که در نهایت حوزه سراسری ماژول و پس از آن نیز Built-in را بررسی می‌کند؛ اگر هم به نتیجه‌ایی نرسد یک استثنا ``NameError`` رخ می‌دهد:: - - >>> x = 0 - >>> - >>> def outer(): - ... x = 1 - ... def inner(): - ... print(x) - ... inner() - ... - >>> outer() - 1 - - :: - - >>> x = 0 - >>> - >>> def outer(): - ... def inner(): - ... print(x) - ... inner() - ... - >>> outer() - 0 - - - :: - - >>> x = 0 - >>> - >>> def outer(): - ... def inner(): - ... print(z) - ... inner() - ... - >>> outer() - Traceback (most recent call last): - File "", line 1, in - File "", line 4, in outer - File "", line 3, in inner - NameError: name 'z' is not defined - >>> - - - -ارسال آرگومان --------------- - -به صورت خودکار با ارسال آرگومان به تابع، متغیرهایی محلی از انتساب اشیای آرگومان‌ها به اسامی پارامترهای موجود در سرآیند تابع به وجود می‌آیند:: - - >>> def f(a): - ... print(a*a) - ... - >>> - >>> b = 3 - >>> f(b) - 9 - -*با فراخوانی تابع f در نمونه کد بالا، متغیر محلی a ایجاد می‌گردد که به شی صحیح 3 اشاره دارد.* - -توجه داشته باشید که با انتساب شی‌ایی جدید به پارامترهای تابع، عملا ارسال آرگومان بی‌تاثیر می‌گردد:: - - >>> def f(a): - ... a = 2 - ... print(a*a) - ... - >>> b = 3 - >>> f(b) - 4 - - -**نکته مهم در ارسال آرگومان، توجه به چگونگی آن است!** - -در بین زبان‌های برنامه‌نویسی دو شیوه برای ارسال آرگومان‌ رایج است: **”by value“** و **”by reference“**. در شیوه by value یک کپی از مقدار آرگومان به تابع ارسال می‌گردد و در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان ارسال شده در خارج از تابع بدون تغییر باقی می‌ماند. به مثال پایتونی پایین توجه نمایید:: - - >>> def f(a): - ... a = 2 - ... print(a*a) - ... - >>> b = 3 - >>> f(b) - 4 - >>> b - 3 - -*همانطور که در نمونه کد بالا قابل مشاهده است، مقدار متغییر b بدون تغییر باقی مانده است.* - -ولی در شیوه by reference به جای ارسال یک کپی از مقدار آرگومان، یک ارجاع (reference) به آن آرگومان به تابع ارسال می‌گردد. می‌توان این‌طور در نظر گرفت که پارامتر متناظر در تابع، همان آرگومان در خارج از تابع است. در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان در خارج از تابع نیز تغییر می‌کند. به مثال پایتونی پایین توجه نمایید:: - - >>> def f(a): - ... a[0] = 3 - ... print(a) - ... - >>> b = [1, 2] - >>> f(b) - [3, 2] - >>> b - [3, 2] - -این دو از شیوه‌‌های مرسوم در زبان‌های برنامه‌نویسی هستند ولی ارسال پارامتر به صورت خاص در زبان برنامه‌نویسی پایتون چگونه است؟ در پایتون هر چیزی یک شی است و در نتیجه ارسال آرگومان‌ها در هر شرایطی به صورت **”by reference“** انجام می‌پذیرد. - -و اگر سوال شود که علت تفاوت رفتار در دو مثال قبل چیست؟ باید بدانیم که علت به ماهیت اشیای آرگومان‌های ارسالی مربوط است. ارسال اشیای تغییرناپذیر (Immutable) به مانند انواع بولین، اعداد، رشته و تاپل به تابع، باعث بروز رفتاری مشابه با شیوه by value می‌شود ولی در مورد ارسال اشیای تغییرپذیر (Mutable) به مانند انواع لیست، دیکشنری و مجموعه اینگونه نخواهد بود. به تصاویر پایین توجه نمایید: - -.. image:: /_static/l12-python-passing-arguments-01.png - :align: center - -.. image:: /_static/l12-python-passing-arguments-02.png - :align: center - -اشیای تغییرپذیر در پایتون اشیایی هستند که بدون تغییر ``()id‍‍`` آن‌ها، مقدارشان قابل تغییر است. خروجی تابع ``()id‍‍`` برای هر شی بیانگر شناسه منحصر به فرد آن شی است که در واقع نشانی آن در حافظه نیز می‌باشد [`اسناد پایتون `__] - درس پنجم. - -برای جلوگیری از تغییر اشیای تغییرپذیر درون تابع، می‌توان به گونه‌ایی که در درس هشتم گفته شد یک کپی از این نوع اشیا را ایجاد و سپس به صورت آرگومان به تابع ارسال کرد:: - - >>> def f(a): - ... a[0] = 3 - ... print(a) - ... - >>> b = [1, 2] - >>> f(b[:]) # Pass a copy - [3, 2] - >>> b - [1, 2] - -در نمونه کد بالا، از آنجایی که تمام اعضای شی لیست متغیر b تماما از انواع تغییرناپذیر هستند، یک کپی سطحی (Shallow Copy) از شی کفایت می‌کند ولی در حالتی غیر از این می‌بایست یک کپی عمیق (Deep Copy) از شی ارسال گردد - درس هشتم. - -البته گاهی واقعا نیاز است که مقدار تغییر یافته از متغیری که به تابع ارسال می‌شود را نیز بیرون از تابع هم در اختیار داشته باشیم. برای این منظور در برخی از زبان‌های برنامه‌نویسی امکان ارسال به شیوه by reference بنابر خواست برنامه‌نویس فراهم شده است. برای مثال در زبان php این کار با قرار دادن یک ``&`` در پشت پارامتر مورد نظر انجام می‌پذیرد: - -.. code-block:: php - - - -در پایتون چنین قابلیتی وجود ندارد، حداقل برای اشیای تغییرناپذیر! ولی می‌توان با استفاده از امکان بازگشت چندین شی توسط دستور ``return``، آن را پوشش داد. با استفاده از این شیوه می‌توان هر تعداد از پارمترهای مورد نیاز خود را به خارج از تابع انتقال داد:: - - >>> def multiple(x, y): - ... x = 2 - ... y = [3, 4] - ... return x, y - ... - >>> X = 1 - >>> Y = [1, 2] - >>> - >>> X, Y = multiple(X, Y) - >>> - >>> X - 2 - >>> Y - [3, 4] - -توجه داشته باشید که در این حالت دستور ``return`` تمام این اشیا را در قالب یک شی تاپل برمی‌گرداند:: - - >>> multiple(X, Y) - (2, [3, 4]) - - -تطابق آرگومان‌ها ------------------- -پیش‌تر به لزوم همخوانی تعداد آرگومان‌های ارسالی با پارامترهای موجود در سرآیند تابع اشاره شد:: - - >>> def f(a, b, c): - ... pass - ... - >>> - >>> f(1, 2) - Traceback (most recent call last): - File "", line 1, in - TypeError: f() missing 1 required positional argument: 'c' - >>> - >>> f(1, 2, 3, 4) - Traceback (most recent call last): - File "", line 1, in - TypeError: f() takes 3 positional arguments but 4 were given - >>> - -در ادامه به ارایه انواع سینتکس‌های مورد قبول پایتون در تطابق آرگومان‌ها (Argument Matching) با پارامتر‌های تابع می‌پردازیم: - -* سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت در ازای هر پارامتر یک آرگومان نظیر ارسال گردد. عمل تطابق در این سینتکس بر اساس موقعیت آرگومان‌ها انجام می‌شود که در نتیجه می‌بایست ترتیب آرگومان‌ها، متناظر با ترتیب پارامترها در سرآیند تابع باشد:: - - >>> def f(a, b, c): - ... print(a, b, c) - ... - >>> f(1, 2, 3) - 1 2 3 - - -* سینتکس نام=مقدار، در این سینتکس آرگومان‌ها به نام پارامترها انتساب داده می‌شوند و از آنجا که عمل تطابق بر اساس نام پارامترها انجام می‌شود دیگر موقعیت یا ترتیب آرگومان‌ها اهمیتی ندارد:: - - >>> def f(a, b, c): - ... print(a, b, c) - ... - >>> f(a=1, c=3, b=2) - 1 2 3 - - می‌توان از این دو سینتکس به صورت ترکیبی نیز استفاده کرد. فقط باید توجه داشت آرگومان‌هایی که عمل تطابق آن‌ها وابسته به موقعیت است را - با رعایت ترتیب موارد قبل‌تر از آن - در ابتدا قرار دهیم. به مثال پایین توجه نمایید:: - - - >>> def f(a, b, c): - ... print(a, b, c) - ... - >>> f(1, c=3, b=2) - 1 2 3 - >>> f(1, 2, c=3) - 1 2 3 - >>> f(1, 2, 3) - 1 2 3 - - برای تابع مثال بالا، حالت‌های فراخوانی پایین نادرست هستند:: - - >>> f(c=3, b=2, 1) - File "", line 1 - SyntaxError: positional argument follows keyword argument - - >>> f(a=1, 2, c=3) - File "", line 1 - SyntaxError: positional argument follows keyword argument - - >>> f(a=1, 2, 3) - File "", line 1 - SyntaxError: positional argument follows keyword argument - - >>> f(2, a=1, c=3) - Traceback (most recent call last): - File "", line 1, in - TypeError: f() got multiple values for argument 'a' - - -* سینتکس ``iterable*``، در این سینتکس یک شی از نوع تکرارپذیر (iterable - درس نهم) مانند انواع رشته، تاپل، لیست و... که توسط یک کاراکتر ستاره ``*‍‍`` نشانه‌گذاری شده است، به تابع ارسال می‌گردد. در این صورت بر اساس ترتیب موقعیت، اعضای درون شی تکرارپذیر به پارامتر‌های تابع اختصاص می‌یابند:: - - >>> def f(a, b, c): - ... print(a, b, c) - ... - >>> b = [1, 2, 3] - >>> f(*b) - 1 2 3 - - -* سینتکس ``dict**``، در این سینتکس یک شی دیکشنری که توسط دو کاراکتر ستاره ``**`` نشانه‌گذاری شده است به تابع ارسال می‌شود. کلید‌های این شی دیکشنری می‌بایست هم‌نام با پارامترهای تعریف شده در سرآیند تابع باشند. پس از فراخوانی تابع، این شی دیکشنری باز می‌شود و بر اساس نام کلید در جفت‌های کلید:مقدار درون آن، پارامترهای تابع مقداردهی می‌شوند:: - - >>> def f(a, b, c): - ... print(a, b, c) - ... - >>> b = {'a':1, 'c':3, 'b':2} - >>> f(**b) - 1 2 3 - -این چهار سینتکس بر اعمال در هنگام فراخوانی تابع بحث می‌کنند و در تمام آن‌ها می‌بایست تعداد آرگومان‌های ارسالی با تعداد پارامترهای تعریف شده در سرآیند تابع برابر باشد و البته بدیهی است که در دو سینتکس پایانی لازم است تعداد اعضای شی تکرارپذیر یا تعداد جفت‌های کلید:مقدار شی دیکشنری با تعداد پارامترهای تابع برابر باشند. - -در ادامه به ارایه سینتکس‌هایی در این زمینه می‌پردازیم که در تعریف پارامترهای تابع نقش دارند. - - - - - - -| - ----- - -:emoji-size:`😊` امیدوارم مفید بوده باشه - -`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ - - From e54696dcb4267a7b14eff90635ae77719cb16ee2 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Sat, 1 Jun 2019 21:36:07 +0430 Subject: [PATCH 016/316] add l12 --- index.rst | 1 + lessons/l12.rst | 707 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 708 insertions(+) create mode 100644 lessons/l12.rst diff --git a/index.rst b/index.rst index f1f3e2b..8151cf6 100644 --- a/index.rst +++ b/index.rst @@ -26,6 +26,7 @@ lessons/l09 lessons/l10 lessons/l11 + lessons/l12 log | diff --git a/lessons/l12.rst b/lessons/l12.rst new file mode 100644 index 0000000..1c249bc --- /dev/null +++ b/lessons/l12.rst @@ -0,0 +1,707 @@ +.. role:: emoji-size + +.. meta:: + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس دوازدهم تابع + :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, پایتون + + +درس ۱۲: تابع - بخش یکم +======================== + + + + + + + + +:emoji-size:`✔` سطح: متوسط + +---- + + +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + + +مقدمه +------ + +**تابع (Function)** به بلاکی از دستورات گفته می‌شود که برای به اجرا درآمدن نیازمند فراخوانی هستند و این فراخوانی می‌تواند بیش از یک بار انجام گیرد. تابع می‌تواند به هنگام فراخوانی مقادیری را دریافت کند و در صورت لزوم مقداری نیز به عنوان نتیجه برگرداند. + +تابع جایگزینی برای بخش‌های تکراری برنامه است که با یک بار نوشتن و چندین بار فراخوانی و اجرای آن می‌توان از پیچیدگی برنامه جلوگیری و تغییر در آن را آسان نمود. استفاده از توابع باعث بالابردن قابلیت استفاده مجدد از کدها می‌شود و افزونگی را نیز کاهش می‌دهد. توابع ابزاری برای خرد کردن منطق برنامه به واحدهای اجرایی کوچکتر برای تسهیل ساخت برنامه‌های بزرگ است. + +مفهوم تابع از علم ریاضی وارد برنامه‌نویسی شده و به معنی ابزاری است که می‌تواند نتیجه (یا خروجی) را بر اساس داده‌های ورودی محاسبه نماید. چنانچه تمام بخش‌های اساسی برنامه با چنین رویکردی توسعه یابد، به این شیوه توسعه «برنامه‌نویسی تابعی» (Functional Programming) گفته می‌شود، شیوه‌ایی که با آن در زبان‌های برنامه‌نویسی همچون Scala ،Scheme ،Lisp و Haskell مواجه هستید. تابع در زبان‌های دیگری همچون C++ ،C ،Pascal و Java نیز وجود دارد که البته این زبان‌ها در دسته «برنامه‌نویسی اعلانی» (Imperative programming) قرار دارند و رویکردی که این‌ها نسبت به تابع دارند کاملا متفاوت از چیزی است که در زبان‌های برنامه‌نویسی تابعی وجود دارد. توضیح تفاوت این دو کمی سخت است ولی حتما توسط برنامه‌نویسی با زبان‌های موجود در این دو دسته به آن پی خواهید برد. :) + +رویکرد این آموزش به تابع بر اساس برنامه‌نویسی اعلانی است. زبان پایتون قابلیت برنامه‌نویسی تابعی را نیز در کنار رویکردهای دیگر همچون اعلانی یا شی‌گرایی ارایه می‌دهد. برای چگونگی برنامه‌نویسی تابعی با استفاده از زبان پایتون می‌توانید به کتاب Functional Programming in Python از انتشارات O'Reilly مراجعه نمایید (`دریافت نسخه pdf - رایگان `__). + +در کنار اصطلاح تابع در برنامه‌نویسی، اصطلاح مشابه دیگری نیز به عنوان «رِوال» (Procedure) وجود دارد. روال و تابع در ساختار شبیه یکدیگر هستند با این تفاوت که روال‌ها مقداری برنمی‌گردانند. در پایتون سینتکسی برای تعریف روال وجود ندارد ولی به توابعی که مقداری برنمی‌گردانند، روال نیز گفته می‌شوند. + +سینتکس +-------- + +سینتکس تابع در زبان برنامه‌نویسی پایتون همانند هر دستور مرکب دیگری شامل یک سرآیند و یک بدنه است - درس ششم. بخش سرآیند شامل کلمه کلیدی ``def``، یک نام به دلخواه کاربر و پرانتز‌ می‌باشد که این پرانتز‌ محل قرار گرفتن پارامترهای تابع را نمایش می‌دهد. هر تابع می‌تواند هیچ، یک یا چند پارامتر بپذیرد:: + + def function_name(param1, param2,... paramN): + statements + +همانطور که بارها گفته شد، هر چیزی در پایتون شی است، هنگامی که اجرای برنامه به کلمه کلیدی ``def`` می‌رسد، ابتدا یک شی تابع ایجاد و سپس از نام تابع (در اینجا: function_name) به آن ارجاع داده می‌شود:: + + >>> def func_name(): + ... pass + ... + >>> + >>> type(func_name) + + +.. tip:: + پیشنهاد `PEP 8 `__: نام تابع از حروف کوچک تشکیل شود که کلمه‌های آن با استفاده از خط زیرین (Underscores) از یکدیگر جدا شده باشند. مانند: my_function . حالت ``mixedCase`` مانند: myFunction نیز صحیح می‌باشد به شرط آنکه در سراسر کدها نام توابع با همین الگو نوشته شود. + +بدنه تا زمانی که تابع فراخوانی نگردد، اجرا نمی‌شود. برای فراخوانی تابع از نام تابع + پرانتز استفاده می‌شود و در صورتی که در تعریف تابع پارامترهایی قرار داده شده باشد، می‌بایست هنگام فراخوانی آرگومان‌های متناسب با این پارامترها نیز ارسال گردند:: + + function_name(arg1, arg2,... argN) + + +.. caution:: + در بحث توابع، به متغیرهایی که در سرآیند تابع تعریف می‌شوند پارامتر (Parameter) و به داده‌هایی که هنگام فراخوانی تابع ارسال می‌گردد آرگومان (Argument) گفته می‌شود. به ازای هر آرگومان ارسالی می‌بایست یک پارامتر در تابع جهت دریافت آن تعریف شده باشد. هیچ الزامی به هم نام بودن آرگومان‌ها و پارامترهای نظیر وجود ندارد ولی وجود هم نامی باعث خوانایی بیشتر کد می‌شود. + + + +بدنه تابع می تواند حاوی کلمه کلیدی ``return`` نیز باشد. در واقع ``return`` دستوری است که در هر جایی از بدنه آورده شود، اجرای تابع در آن نقطه متوقف و مقداری (البته در زبان پایتون درست این است که گفته شود: شی‌ایی) را به عنوان نتیجه به محل فراخوانی تابع بازمی‌گرداند:: + + def function_name(param1, param2,... paramN): + ... + return value + +در نمونه کد بالا value مقداری است که توسط ``return`` به محل فراخوانی بازگردانده می‌شود. value می‌تواند صراحتا یک مقدار نباشد بلکه یک عبارت مانند : ``param1**2`` یا ``param1 > 3`` و... باشد که در این صورت ابتدا حاصل عبارت ارزیابی و سپس بازگردانده می‌شود. چنانچه value ذکر نگردد، ``None`` بازگردانده می‌شود:: + + >>> def my_pow(x, y): + ... return x**y + ... + >>> + >>> a = 2 + >>> b = 3 + >>> + >>> my_pow(a, b) + 8 + >>> + +در زبان برنامه نویسی پایتون تابع یک موجودیت **”first-class“** است که یعنی تابع را می‌توان مانند دیگر اشیا به صورت پویا ایجاد یا نابود کرد، به صورت آرگومان به توابع دیگر ارسال نمود، به عنوان نتیجه توسط ``return`` بازگرداند و... در نتیجه می‌توان یک تابع را درون بدنه دستورات کنترلی (``while`` ،``if`` و...) یا درون بدنه تابعی دیگر تعریف نمود:: + + >>> def outer(num1): + ... def inner_increment(num1): # hidden from outer code + ... return num1 + 1 + ... num2 = inner_increment(num1) + ... print(num1, num2) + ... + >>> + >>> outer(1) + 1 2 + + +خیلی خوب است که با استفاده از ”Docstring“ در توابع به مستندسازی و خوانایی بهتر برنامه کمک کنیم - درس ششم:: + + + def function_with_docstring(param1, param2): + """Example function with types documented in the docstring. + + Args: + param1 (int): The first parameter. + param2 (str): The second parameter. + + Returns: + bool: The return value. True for success, False otherwise. + """ + + +فضاهای نام و حوزه +------------------ + +در هر برنامه پایتون تعداد زیادی نام وجود دارد که برای نمونه می‌توان به: متغیرها، نام توابع، نام کلاس‌ها و... اشاره کرد. بدیهی است که برای شناسایی اشیا لازم است نام‌ها منحصر به فرد باشند، رعایت چنین امری در یک برنامه حتی کوچک کار سختی است. در زبان پایتون برای دسته‌بندی و جلوگیری از تداخل نام‌ها، ساختاری با عنوان «**فضاهای نام**» (**Namespaces**) در نظر گرفته شده است. هر فضا نام بخشی از نام‌های درون برنامه را دربر‌می‌گیرد. به صورت کلی فضاهای نام پایتون در سه سطح تو در توی «محلی» (Local)، «سراسری» (Global) و Built-in به تصویر کشیده می‌شوند: + +.. image:: /_static/nested-namespaces-python.jpg + :align: center + +هر ماژول پایتون یک فضانام سراسری برای خود تشکیل می‌دهد که نسبت به فضا نام دیگر ماژول‌ها ایزوله است. فضانام تمام ماژول‌ها درون فضانام بزرگتری ایجاد می‌گردند که به عنوان فضانام Built-in شناخته می‌شود و نام تمامی توابع آماده مانند ``()open`` که پیش از این استفاده می‌کردیم در این فضا قرار گرفته است. ساختار تو در توی سطوح فضا نام باعث می‌شود که بدون نیاز به import ماژول خاصی در هر جای برنامه به توابع آماده (Built-in) دسترسی داشته باشیم. + +هر ماژول می‌تواند شامل تعدادی تابع و کلاس باشد. با فراخوانی هر تابع یک فضانام محلی برای آن تابع، درون فضانام ماژول مربوطه ایجاد می‌گردد و با پایان اجرای تابع نیز از بین می‌رود، در مورد کلاس‌ها هم اتفاق مشابهی رخ می‌دهد. بر همین اساس می‌توانیم درون تابع متغیرهایی متفاوت ولی هم نام با متغیرهای خارج از تابع در ماژول **ایجاد** نماییم چرا که آن‌ها در دو فضانام متفاوت قرار دارند و از طرفی به دلیل داخل بودن فضا نام تابع درون فضا نام ماژول خود، می‌توان به نام‌های خارج از تابع نیز دسترسی داشت. + +گفتیم فضا نام ماژول‌ها نسبت به یکدیگر ایزوله هستند. بنابراین برای دسترسی به نام‌های درون ماژول‌های دیگر، ابتدا می‌بایست آن‌ ماژول‌ها را import نماییم که در این صورت با استفاده از نام ماژول - به شکل یک پیشوند - قابل دستیابی هستند. برای نمونه دستیابی نام ``getcwd`` که به یک تابع ارجاع دارد از فضانام ماژول ``os``، در نمونه کد پایین نمایش داده شده است:: + + >>> import os + + >>> os.getcwd() + '/home/saeid' + +اما استفاده از نام‌های یک ماژول درون خودش چگونه است؟ جایی که فضا‌های نام دیگری همچون توابع نیز وجود دارند ولی هیچ پیشوندی مانند نام ماژول وجود ندارد که بتوان نام‌های درون این فضاهای متفاوت را از یکدیگر تمیز داد. برای اینکه بدانیم هر نام ماژول در هر نقطه‌ایی از همان ماژول چگونه مورد دستیابی قرار می‌گیرد با مفهوم دیگری به نام «**حوزه**» (**Scope**) آشنا می‌شویم. به صورت کلی حوزه به نواحی‌ایی از برنامه گفته می‌شود که می‌توان یک نام را بدون استفاده از هیچ پیشوندی و البته بدون تداخل با نام‌های دیگر به کار برد. بحث حوزه صرفا در داخل هر ماژول مطرح است. + +*قوانین حوزه:* + +* بدنه ماژول - منظور نواحی‌ایی که خارج از بدنه توابع و کلاس‌ها قرار دارد - **حوزه سراسری** (**Global Scope**) است. توجه داشته باشید که واژه «سراسری» در بحث حوزه (یا فضانام) تنها به سراسر کدهای داخل هر ماژول اشاره دارد و نه سراسر برنامه. به صورت کلی هر جایی از زبان پایتون که واژه سراسری (Global) را شنیدید (یا خواندید) به یاد ماژول بیافتید:: + + # This is a global variable + a = 0 + + if a == 0: + # This is still a global variable + b = 1 + + *در نمونه کد بالا، حوزه تعریف هر دو متغیر a و b از نوع سراسری است. بدنه دستورات کنترلی فاقد یک فضانام جداگانه است و تعریف متغیر در این نواحی از برنامه درون حوزه سراسری قرار می‌گیرد.* + + | + + +* بدنه هر تابع یک **حوزه محلی** (**Local Scope**) است و به صورت پیش‌فرض تمام متغیرهایی که درون توابع ایجاد می‌گردند درون حوزه محلی قرار گرفته‌اند مگر اینکه با استفاده از کلمه‌های کلیدی ``global`` یا ``nonlocal`` مشخص شده باشند. چنانچه بخواهیم درون تابع انتسابی به یکی از نام‌های موجود در حوزه سراسری انجام دهیم، می‌بایست از دستور ``global`` استفاده کنیم. به نمونه کدهای پایین توجه نمایید:: + + + def my_function(c): + # this is a local variable + d = 3 + + + :: + + >>> a = 0 + >>> + >>> def my_function(): + ... a = 3 + ... print(a) + ... + >>> + >>> a + 0 + >>> my_function() + 3 + >>> a + 0 + >>> + + :: + + >>> a = 0 + >>> + >>> def my_function(): + ... global a + ... a = 3 + ... print(a) + ... + >>> + >>> a + 0 + >>> my_function() + 3 + >>> a + 3 + >>> + + در توابع تو در تو نیز فرقی ندارد، هر تابع که فراخوانی می‌شود فضانامی مجزا برای آن ایجاد می‌شود و حوزه محلی خود را خواهد داشت. دستور ``nonlocal`` در پایتون ۳ ارائه شده است و در توابع تو در تو کاربرد دارد. هنگامی که بخواهیم داخل بدنه تابع درونی انتسابی به نامی تعریف شده در یکی از توابع بیرونی آن انجام دهیم، می‌بایست از این دستور برای مشخص کردن نام مورد نظر استفاده کنیم:: + + >>> def outer(): + ... x = 1 + ... def inner(): + ... x = 2 + ... print("inner:", x) + ... inner() + ... print("outer:", x) + ... + >>> + >>> outer() + inner: 2 + outer: 1 + >>> + + :: + + >>> def outer(): + ... x = 1 + ... def inner(): + ... nonlocal x + ... x = 2 + ... print("inner:", x) + ... inner() + ... print("outer:", x) + ... + >>> + >>> outer() + inner: 2 + outer: 2 + >>> + +* وقتی از متغیری استفاده می‌کنیم، مفسر پایتون ابتدا می‌بایست حوزه و فضانام آن را تشخیص دهد تا بتواند شی‌ایی که این متغیر به آن ارجاع دارد را پیدا کند. فرض کنیم متغیری درون عبارتی در بدنه یک تابع به کار رفته باشد در این صورت مفسر ابتدا حوزه محلی که متغیر در آن وجود دارد را برای یافتن تعریف متغیر جستجو می‌کند و چنانچه نیابد به سراغ حوزه محلی تابع بیرونی آن - در صورت وجود - می‌رود و همینطور ادامه می‌دهد که در نهایت حوزه سراسری ماژول و پس از آن نیز Built-in را بررسی می‌کند؛ اگر هم به نتیجه‌ایی نرسد یک استثنا ``NameError`` رخ می‌دهد:: + + >>> x = 0 + >>> + >>> def outer(): + ... x = 1 + ... def inner(): + ... print(x) + ... inner() + ... + >>> outer() + 1 + + :: + + >>> x = 0 + >>> + >>> def outer(): + ... def inner(): + ... print(x) + ... inner() + ... + >>> outer() + 0 + + + :: + + >>> x = 0 + >>> + >>> def outer(): + ... def inner(): + ... print(z) + ... inner() + ... + >>> outer() + Traceback (most recent call last): + File "", line 1, in + File "", line 4, in outer + File "", line 3, in inner + NameError: name 'z' is not defined + >>> + + + +ارسال آرگومان +-------------- + +به صورت خودکار با ارسال آرگومان به تابع، متغیرهایی محلی از انتساب اشیای آرگومان‌ها به اسامی پارامترهای موجود در سرآیند تابع به وجود می‌آیند:: + + >>> def f(a): + ... print(a*a) + ... + >>> + >>> b = 3 + >>> f(b) + 9 + +*با فراخوانی تابع f در نمونه کد بالا، متغیر محلی a ایجاد می‌گردد که به شی صحیح 3 اشاره دارد.* + +توجه داشته باشید که با انتساب شی‌ایی جدید به پارامترهای تابع، عملا ارسال آرگومان بی‌تاثیر می‌گردد:: + + >>> def f(a): + ... a = 2 + ... print(a*a) + ... + >>> b = 3 + >>> f(b) + 4 + + +**نکته مهم در ارسال آرگومان، توجه به چگونگی آن است!** + +در بین زبان‌های برنامه‌نویسی دو شیوه برای ارسال آرگومان‌ رایج است: **”by value“** و **”by reference“**. در شیوه by value یک کپی از مقدار آرگومان به تابع ارسال می‌گردد و در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان ارسال شده در خارج از تابع بدون تغییر باقی می‌ماند. به مثال پایتونی پایین توجه نمایید:: + + >>> def f(a): + ... a = 2 + ... print(a*a) + ... + >>> b = 3 + >>> f(b) + 4 + >>> b + 3 + +*همانطور که در نمونه کد بالا قابل مشاهده است، مقدار متغییر b بدون تغییر باقی مانده است.* + +ولی در شیوه by reference به جای ارسال یک کپی از مقدار آرگومان، یک ارجاع (reference) به آن آرگومان به تابع ارسال می‌گردد. می‌توان این‌طور در نظر گرفت که پارامتر متناظر در تابع، همان آرگومان در خارج از تابع است. در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان در خارج از تابع نیز تغییر می‌کند. به مثال پایتونی پایین توجه نمایید:: + + >>> def f(a): + ... a[0] = 3 + ... print(a) + ... + >>> b = [1, 2] + >>> f(b) + [3, 2] + >>> b + [3, 2] + +این دو از شیوه‌‌های مرسوم در زبان‌های برنامه‌نویسی هستند ولی ارسال پارامتر به صورت خاص در زبان برنامه‌نویسی پایتون چگونه است؟ در پایتون هر چیزی یک شی است و در نتیجه ارسال آرگومان‌ها در هر شرایطی به صورت **”by reference“** انجام می‌پذیرد. + +و اگر سوال شود که علت تفاوت رفتار در دو مثال قبل چیست؟ باید بدانیم که علت به ماهیت اشیای آرگومان‌های ارسالی مربوط است. ارسال اشیای تغییرناپذیر (Immutable) به مانند انواع بولین، اعداد، رشته و تاپل به تابع، باعث بروز رفتاری مشابه با شیوه by value می‌شود ولی در مورد ارسال اشیای تغییرپذیر (Mutable) به مانند انواع لیست، دیکشنری و مجموعه اینگونه نخواهد بود. به تصاویر پایین توجه نمایید: + +.. image:: /_static/l12-python-passing-arguments-01.png + :align: center + +.. image:: /_static/l12-python-passing-arguments-02.png + :align: center + +اشیای تغییرپذیر در پایتون اشیایی هستند که بدون تغییر ``()id‍‍`` آن‌ها، مقدارشان قابل تغییر است. خروجی تابع ``()id‍‍`` برای هر شی بیانگر شناسه منحصر به فرد آن شی است که در واقع نشانی آن در حافظه نیز می‌باشد [`اسناد پایتون `__] - درس پنجم. + +برای جلوگیری از تغییر اشیای تغییرپذیر درون تابع، می‌توان به گونه‌ایی که در درس هشتم گفته شد یک کپی از این نوع اشیا را ایجاد و سپس به صورت آرگومان به تابع ارسال کرد:: + + >>> def f(a): + ... a[0] = 3 + ... print(a) + ... + >>> b = [1, 2] + >>> f(b[:]) # Pass a copy + [3, 2] + >>> b + [1, 2] + +در نمونه کد بالا، از آنجایی که تمام اعضای شی لیست متغیر b تماما از انواع تغییرناپذیر هستند، یک کپی سطحی (Shallow Copy) از شی کفایت می‌کند ولی در حالتی غیر از این می‌بایست یک کپی عمیق (Deep Copy) از شی ارسال گردد - درس هشتم. + +البته گاهی واقعا نیاز است که مقدار تغییر یافته از متغیری که به تابع ارسال می‌شود را نیز بیرون از تابع هم در اختیار داشته باشیم. برای این منظور در برخی از زبان‌های برنامه‌نویسی امکان ارسال به شیوه by reference بنابر خواست برنامه‌نویس فراهم شده است. برای مثال در زبان php این کار با قرار دادن یک ``&`` در پشت پارامتر مورد نظر انجام می‌پذیرد: + +.. code-block:: php + + + +در پایتون چنین قابلیتی وجود ندارد، حداقل برای اشیای تغییرناپذیر! ولی می‌توان با استفاده از امکان بازگشت چندین شی توسط دستور ``return``، آن را پوشش داد. با استفاده از این شیوه می‌توان هر تعداد از پارمترهای مورد نیاز خود را به خارج از تابع انتقال داد:: + + >>> def multiple(x, y): + ... x = 2 + ... y = [3, 4] + ... return x, y + ... + >>> X = 1 + >>> Y = [1, 2] + >>> + >>> X, Y = multiple(X, Y) + >>> + >>> X + 2 + >>> Y + [3, 4] + +توجه داشته باشید که در این حالت دستور ``return`` تمام این اشیا را در قالب یک شی تاپل برمی‌گرداند:: + + >>> multiple(X, Y) + (2, [3, 4]) + + +تطابق آرگومان‌ها +------------------ +پیش‌تر به لزوم همخوانی تعداد آرگومان‌های ارسالی با پارامترهای موجود در سرآیند تابع اشاره شد:: + + >>> def f(a, b, c): + ... pass + ... + >>> + >>> f(1, 2) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() missing 1 required positional argument: 'c' + >>> + >>> f(1, 2, 3, 4) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() takes 3 positional arguments but 4 were given + >>> + +در ادامه به ارایه انواع سینتکس‌های مورد قبول پایتون در تطابق آرگومان‌ها (Argument Matching) با پارامتر‌های تابع می‌پردازیم: + +* سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت در ازای هر پارامتر یک آرگومان نظیر ارسال گردد. عمل تطابق در این سینتکس بر اساس موقعیت آرگومان‌ها انجام می‌شود که در نتیجه می‌بایست ترتیب آرگومان‌ها، متناظر با ترتیب پارامترها در سرآیند تابع باشد:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> f(1, 2, 3) + 1 2 3 + + +* سینتکس نام=مقدار، در این سینتکس آرگومان‌ها به نام پارامترها انتساب داده می‌شوند و از آنجا که عمل تطابق بر اساس نام پارامترها انجام می‌شود دیگر موقعیت یا ترتیب آرگومان‌ها اهمیتی ندارد:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> f(a=1, c=3, b=2) + 1 2 3 + + می‌توان از این دو سینتکس به صورت ترکیبی نیز استفاده کرد. فقط باید توجه داشت آرگومان‌هایی که عمل تطابق آن‌ها وابسته به موقعیت است را - با رعایت ترتیب موارد قبل‌تر از آن - در ابتدا قرار دهیم. به مثال پایین توجه نمایید:: + + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> f(1, c=3, b=2) + 1 2 3 + >>> f(1, 2, c=3) + 1 2 3 + >>> f(1, 2, 3) + 1 2 3 + + برای تابع مثال بالا، حالت‌های فراخوانی پایین نادرست هستند:: + + >>> f(c=3, b=2, 1) + File "", line 1 + SyntaxError: positional argument follows keyword argument + + >>> f(a=1, 2, c=3) + File "", line 1 + SyntaxError: positional argument follows keyword argument + + >>> f(a=1, 2, 3) + File "", line 1 + SyntaxError: positional argument follows keyword argument + + >>> f(2, a=1, c=3) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() got multiple values for argument 'a' + + +* سینتکس ``iterable*``، در این سینتکس یک شی از نوع تکرارپذیر (iterable - درس نهم) مانند انواع رشته، تاپل، لیست و... که توسط یک کاراکتر ستاره ``*‍‍`` نشانه‌گذاری شده است، به تابع ارسال می‌گردد. در این صورت بر اساس ترتیب موقعیت، اعضای درون شی تکرارپذیر به پارامتر‌های تابع اختصاص می‌یابند:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> b = [1, 2, 3] + >>> f(*b) + 1 2 3 + + +* سینتکس ``dict**``، در این سینتکس یک شی دیکشنری که توسط دو کاراکتر ستاره ``**`` نشانه‌گذاری شده است به تابع ارسال می‌شود. کلید‌های این شی دیکشنری می‌بایست هم‌نام با پارامترهای تعریف شده در سرآیند تابع باشند. پس از فراخوانی تابع، این شی دیکشنری باز می‌شود و بر اساس نام کلید در جفت‌های کلید:مقدار درون آن، پارامترهای تابع مقداردهی می‌شوند:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> b = {'a':1, 'c':3, 'b':2} + >>> f(**b) + 1 2 3 + +این چهار سینتکس بر اعمال در هنگام فراخوانی تابع بحث می‌کنند و در تمام آن‌ها می‌بایست تعداد آرگومان‌های ارسالی با تعداد پارامترهای تعریف شده در سرآیند تابع برابر باشد و البته بدیهی است که در دو سینتکس پایانی لازم است تعداد اعضای شی تکرارپذیر یا تعداد جفت‌های کلید:مقدار شی دیکشنری با تعداد پارامترهای تابع برابر باشند. + +در ادامه به ارایه سینتکس‌هایی در این زمینه می‌پردازیم که هنگام تعیین پارامترهای تابع نقش دارند. + +* سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت تک تک پارامترها را تعرف کنیم:: + + >>> def f(a, b, c): + ... print(a, b, c) + ... + >>> f(1, 2, 3) + 1 2 3 + +* سینتکس تعیین مقدار پیش‌فرض برای پارمترها. می‌توان هنگام تعیین هر پارامتر در تعریف تابع، مقداری را نیز به آن انتساب داد؛ در این شرایط اگر آرگومانی نظیر با آن پارامتر ارسال نگردد، مقدار پیش‌فرض آن پارمتر در نظر گرفته خواهد شد. به این گونه پارامترها، اختیاری نیز گفته می‌شود:: + + >>> def chaap(text=None): + ... if text: + ... print(text) + ... else: + ... print("Nothing!") + ... + >>> + >>> chaap("Python :)") + Python :) + >>> + >>> chaap() + Nothing! + >>> + + پارامتر با مقدار پیش‌فرض را می‌توان در کنار پارمترهای اجباری (بدون مقدار پیش‌فرض) تعریف کرد که در این شرایط می‌بایست پارامترهای دارای مقدار پیش‌فرض را در انتها قرار داد:: + + >>> def f(a, b=2, c=3): # a required, b and c optional + print(a, b, c) + + + :: + + >>> f(1) # Use defaults + 1 2 3 + + >>> f(a=1) + 1 2 3 + + + :: + + >>> f(1, 4) # Override defaults + 1 4 3 + + >>> f(1, 4, 5) + 1 4 5 + + :: + + >>> f(1, c=6) # Choose defaults + 1 2 6 + + + +* سینتکس ``name*``، تمام آرگومان‌های ارسالی را در قالب یه شی تاپل دریافت می‌کند- این قابلیت در مواقعی که تعداد آرگومان‌های ارسالی متغییر است کمک بزرگی می‌کند:: + + >>> def f(*name): + ... print(type(name)) + ... print(name) + ... + >>> + + >>> f(1) + + (1,) + + >>> f(1, 2, 3) + + (1, 2, 3) + + + :: + + >>> def f(a, b=2, *args): + ... print(a, b , args) + ... + >>> + + >>> f(1) + 1 2 () + + >>> f(1, 2, 3) + 1 2 (3,) + + :: + + >>> a = [3, (4, 5)] + >>> f(a) + [3, (4, 5)] 2 () + + :: + + >>> f(1, 4, [8, 12, 16]) + 1 4 ([8, 12, 16],) + + :: + + >>> a = [3, 6, 9, (10, 11)] + >>> f(*a) + 3 6 (9, (10, 11)) + + + :: + + >>> f(b=10, a=5, c=15) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() got an unexpected keyword argument 'c' + + + + +* سینتکس ``name**``، تمام آرگومان‌های کلید:مقدار ارسالی را در قالب یک شی دیکشنری دریافت می‌کند:: + + >>> def f(**name): + ... print(type(name)) + ... print(name) + ... + >>> + + >>> f() + + {} + + >>> f(a=1) + + {'a': 1} + + + :: + + >>> def f(a, b=2, **kwargs): + ... print(a, b, kwargs) + ... + >>> + + >>> f(1, c=3) + 1 2 {'c': 3} + + >>> f(b=10, a=5, c=15) + 5 10 {'c': 15} + + + :: + + >>> def f(a, b=2, *args, **kwargs): + ... print(a, b , args, kwargs) + ... + >>> + + >>> f(*[1, 2, 3, 4 ,5], **{"c":7, "d":9}) + 1 2 (3, 4, 5) {'d': 9, 'c': 7} + + >>> f(11, 12, 13, 14, 15) + 11 12 (13, 14, 15) {} + + >>> f(b=14, a=7, c=21, d=28) + 7 14 () {'d': 28, 'c': 21} + + + +در پایتون نسخه 3x دو سینتکس جدید نیز منظور شده است: + + * ``def func(*other, name)`` - این سینتکس امکانی است که بتوان تابعی تعریف که از یک طرف بتواند هر تعداد آرگومان را دریافت کند و از طرف دیگر نیز تعداد مشخصی آرگومان خاص را تعیین کرد. تنها باید توجه داشت که آرگومان نظیر تمامی پارامترهایی که پس از پارامتر ستاره‌دار قرار گرفته‌اند، می‌بایست به صورت نام=مقدار ارسال گردند:: + + >>> def f(a, *b, c): + ... print(a, b, c) + ... + >>> + + >>> f(1, 2, c=3) + 1 (2,) 3 + + >>> f(1, c=3) + 1 () 3 + + >>> f(1) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() missing 1 required keyword-only argument: 'c' + + + >>> f(1, 2, 3) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() missing 1 required keyword-only argument: 'c' + + + :: + + >>> def f(a, *b, c, d=5): + ... print(a, b, c, d) + ... + >>> + + >>> f(1, 2, 3, c=4) + 1 (2, 3) 4 5 + + >>> f(1, 2, 3, 4, c=7, d=9) + 1 (2, 3, 4) 7 9 + + + + * ``def func(*, name)`` - استفاده از کاراکتر ستاره خالی نیز ممکن است که در این حالت آرگومان‌های اضافی نادیده گرفته می‌شوند ولی همانند مورد قبل امکان دریافت برخی پارامترها آن‌هم تنها به صورت نام=مقدار ممکن است: + + + + + +| + +---- + +:emoji-size:`😊` امیدوارم مفید بوده باشه + +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ + + From b7e60077885930a7eb540a3b00e00ca211130bf3 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Mon, 24 Jun 2019 23:45:05 +0430 Subject: [PATCH 017/316] write last section --- lessons/l12.rst | 118 +++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 47 deletions(-) diff --git a/lessons/l12.rst b/lessons/l12.rst index 1c249bc..04f6b55 100644 --- a/lessons/l12.rst +++ b/lessons/l12.rst @@ -34,7 +34,7 @@ تابع جایگزینی برای بخش‌های تکراری برنامه است که با یک بار نوشتن و چندین بار فراخوانی و اجرای آن می‌توان از پیچیدگی برنامه جلوگیری و تغییر در آن را آسان نمود. استفاده از توابع باعث بالابردن قابلیت استفاده مجدد از کدها می‌شود و افزونگی را نیز کاهش می‌دهد. توابع ابزاری برای خرد کردن منطق برنامه به واحدهای اجرایی کوچکتر برای تسهیل ساخت برنامه‌های بزرگ است. -مفهوم تابع از علم ریاضی وارد برنامه‌نویسی شده و به معنی ابزاری است که می‌تواند نتیجه (یا خروجی) را بر اساس داده‌های ورودی محاسبه نماید. چنانچه تمام بخش‌های اساسی برنامه با چنین رویکردی توسعه یابد، به این شیوه توسعه «برنامه‌نویسی تابعی» (Functional Programming) گفته می‌شود، شیوه‌ایی که با آن در زبان‌های برنامه‌نویسی همچون Scala ،Scheme ،Lisp و Haskell مواجه هستید. تابع در زبان‌های دیگری همچون C++ ،C ،Pascal و Java نیز وجود دارد که البته این زبان‌ها در دسته «برنامه‌نویسی اعلانی» (Imperative programming) قرار دارند و رویکردی که این‌ها نسبت به تابع دارند کاملا متفاوت از چیزی است که در زبان‌های برنامه‌نویسی تابعی وجود دارد. توضیح تفاوت این دو کمی سخت است ولی حتما توسط برنامه‌نویسی با زبان‌های موجود در این دو دسته به آن پی خواهید برد. :) +مفهوم تابع از علم ریاضی وارد برنامه‌نویسی شده و به معنی ابزاری است که می‌تواند نتیجه (یا خروجی) را بر اساس داده‌های ورودی محاسبه نماید. چنانچه تمام بخش‌های اساسی برنامه با چنین رویکردی توسعه یابد، به این شیوه توسعه «برنامه‌نویسی تابعی» (Functional Programming) گفته می‌شود، شیوه‌ایی که با آن در زبان‌های برنامه‌نویسی همچون Scala ،Scheme ،Lisp و Haskell مواجه هستید. تابع در زبان‌های دیگری همچون C ،Pascal و ++C نیز وجود دارد که البته این زبان‌ها در دسته «برنامه‌نویسی اعلانی» (Imperative programming) قرار دارند و رویکردی که این‌ها نسبت به تابع دارند کاملا متفاوت از چیزی است که در زبان‌های برنامه‌نویسی تابعی وجود دارد. توضیح تفاوت این دو کمی سخت است ولی حتما توسط برنامه‌نویسی با زبان‌های موجود در این دو دسته به آن پی خواهید برد. :) رویکرد این آموزش به تابع بر اساس برنامه‌نویسی اعلانی است. زبان پایتون قابلیت برنامه‌نویسی تابعی را نیز در کنار رویکردهای دیگر همچون اعلانی یا شی‌گرایی ارایه می‌دهد. برای چگونگی برنامه‌نویسی تابعی با استفاده از زبان پایتون می‌توانید به کتاب Functional Programming in Python از انتشارات O'Reilly مراجعه نمایید (`دریافت نسخه pdf - رایگان `__). @@ -487,7 +487,7 @@ در ادامه به ارایه سینتکس‌هایی در این زمینه می‌پردازیم که هنگام تعیین پارامترهای تابع نقش دارند. -* سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت تک تک پارامترها را تعرف کنیم:: +* سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت تک تک پارامترها را تعریف کنیم:: >>> def f(a, b, c): ... print(a, b, c) @@ -495,7 +495,7 @@ >>> f(1, 2, 3) 1 2 3 -* سینتکس تعیین مقدار پیش‌فرض برای پارمترها. می‌توان هنگام تعیین هر پارامتر در تعریف تابع، مقداری را نیز به آن انتساب داد؛ در این شرایط اگر آرگومانی نظیر با آن پارامتر ارسال نگردد، مقدار پیش‌فرض آن پارمتر در نظر گرفته خواهد شد. به این گونه پارامترها، اختیاری نیز گفته می‌شود:: +* سینتکس تعیین مقدار پیش‌فرض برای پارامترها. می‌توان هنگام تعیین هر پارامتر در تعریف تابع، مقداری را نیز به آن انتساب داد؛ در این شرایط اگر آرگومانی نظیر با آن پارامتر ارسال نگردد، مقدار پیش‌فرض آن پارامتر در نظر گرفته خواهد شد. به این گونه پارامترها، اختیاری نیز گفته می‌شود:: >>> def chaap(text=None): ... if text: @@ -598,6 +598,74 @@ + **Keyword-Only Arguments** `PEP 3102 `_ + + در پایتون نسخه 2x پس از پارامتری ستاره‌دار، نمی‌توان پارامتر دیگری قرار داد و این امکان تنها در پایتون نسخه 3x امکان‌‌پذیر می‌باشد. باید توجه داشت که در این نسخه‌ (3x) آرگومان نظیر تمامی پارامترهایی که پس از پارامتر ستاره‌دار قرار گرفته‌اند، می‌بایست به صورت **نام=مقدار** ارسال گردند. + + + تابع با سرآیند ``(def f(a, *b, c`` را در نظر بگیرید. در چنین شرایطی که پارامتر ``a`` با استفاده از موقعیت آن مقدار دهی می‌شود و پارامتر ``b`` هر تعداد آرگومان دیگری را دریافت می‌کند، دیگر برای ارسال آرگومان به پارامتر ``c`` چاره‌ای جز ذکر نام آن باقی نمی‌ماند! :: + + + >>> def f(a, *b, c): + ... print(a, b, c) + ... + >>> + + >>> f(1, 2, c=3) + 1 (2,) 3 + + >>> f(1, c=3) + 1 () 3 + + >>> f(1, 2 ,3 ,4 , 5, c=30) + 1 (2, 3, 4, 5) 30 + + + >>> f(1) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() missing 1 required keyword-only argument: 'c' + + + >>> f(1, 2, 3) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() missing 1 required keyword-only argument: 'c' + + + >>> f(1, 2 ,3 ,4 , 5, c=30, 40) + File "", line 1 + SyntaxError: positional argument follows keyword argument + + + + :: + + >>> def f(a, *b, c, d=5): + ... print(a, b, c, d) + ... + >>> + + >>> f(1, 2, 3, c=4) + 1 (2, 3) 4 5 + + >>> f(1, 2, 3, 4, c=7, d=9) + 1 (2, 3, 4) 7 9 + + + :: + + >>> # Python 2.x + >>> def f(a, *b, c): + File "", line 1 + def f(a, *b, c): + ^ + SyntaxError: invalid syntax + + + + + * سینتکس ``name**``، تمام آرگومان‌های کلید:مقدار ارسالی را در قالب یک شی دیکشنری دریافت می‌کند:: @@ -648,50 +716,6 @@ -در پایتون نسخه 3x دو سینتکس جدید نیز منظور شده است: - - * ``def func(*other, name)`` - این سینتکس امکانی است که بتوان تابعی تعریف که از یک طرف بتواند هر تعداد آرگومان را دریافت کند و از طرف دیگر نیز تعداد مشخصی آرگومان خاص را تعیین کرد. تنها باید توجه داشت که آرگومان نظیر تمامی پارامترهایی که پس از پارامتر ستاره‌دار قرار گرفته‌اند، می‌بایست به صورت نام=مقدار ارسال گردند:: - - >>> def f(a, *b, c): - ... print(a, b, c) - ... - >>> - - >>> f(1, 2, c=3) - 1 (2,) 3 - - >>> f(1, c=3) - 1 () 3 - - >>> f(1) - Traceback (most recent call last): - File "", line 1, in - TypeError: f() missing 1 required keyword-only argument: 'c' - - - >>> f(1, 2, 3) - Traceback (most recent call last): - File "", line 1, in - TypeError: f() missing 1 required keyword-only argument: 'c' - - - :: - - >>> def f(a, *b, c, d=5): - ... print(a, b, c, d) - ... - >>> - - >>> f(1, 2, 3, c=4) - 1 (2, 3) 4 5 - - >>> f(1, 2, 3, 4, c=7, d=9) - 1 (2, 3, 4) 7 9 - - - - * ``def func(*, name)`` - استفاده از کاراکتر ستاره خالی نیز ممکن است که در این حالت آرگومان‌های اضافی نادیده گرفته می‌شوند ولی همانند مورد قبل امکان دریافت برخی پارامترها آن‌هم تنها به صورت نام=مقدار ممکن است: - From 6e06088f9e013fc2f5800f56b336445718140e9f Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 24 Jun 2019 23:48:47 +0430 Subject: [PATCH 018/316] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 32bd64a..8d302b1 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ A free, online python book in persian. This book currently is under development http://python.coderz.ir by : -* [Saeid Darvishi](https://twitter.com/saeiddrv) +* [Saeid Darvish](https://twitter.com/saeiddrv) Feel free to contribute :) License ----- -Creative Commons License
Python Persian Tutorial by Saeid Darvishi is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
Based on a work at http://python.coderz.ir/. +Creative Commons License
Python Persian Tutorial by Saeid Darvish is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
Based on a work at http://python.coderz.ir/. From 632b7ea722737c77a02c7261242c57d254b68db6 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Tue, 25 Jun 2019 22:44:55 +0430 Subject: [PATCH 019/316] l12: edit 1 --- lessons/l12.rst | 110 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 31 deletions(-) diff --git a/lessons/l12.rst b/lessons/l12.rst index 04f6b55..a8275b4 100644 --- a/lessons/l12.rst +++ b/lessons/l12.rst @@ -66,11 +66,11 @@ .. caution:: - در بحث توابع، به متغیرهایی که در سرآیند تابع تعریف می‌شوند پارامتر (Parameter) و به داده‌هایی که هنگام فراخوانی تابع ارسال می‌گردد آرگومان (Argument) گفته می‌شود. به ازای هر آرگومان ارسالی می‌بایست یک پارامتر در تابع جهت دریافت آن تعریف شده باشد. هیچ الزامی به هم نام بودن آرگومان‌ها و پارامترهای نظیر وجود ندارد ولی وجود هم نامی باعث خوانایی بیشتر کد می‌شود. + در بحث توابع، به متغیرهایی که در سرآیند تابع تعریف می‌شوند پارامتر (Parameter) و به داده‌هایی که هنگام فراخوانی تابع ارسال می‌گردند، آرگومان (Argument) گفته می‌شود. به ازای هر پارامتر در نظر گرفته شده در تعریف تابع می‌بایست یک آرگومان نظیر به آن ارسال گردد. در واقع آرگومان‌ها مقادیری هستند که می‌خواهیم به پارامترهای یک تابع انتساب دهیم. هیچ الزامی به هم نام بودن آرگومان‌ها و پارامترهای نظیر وجود ندارد ولی وجود هم نامی باعث خوانایی بیشتر کد می‌شود. -بدنه تابع می تواند حاوی کلمه کلیدی ``return`` نیز باشد. در واقع ``return`` دستوری است که در هر جایی از بدنه آورده شود، اجرای تابع در آن نقطه متوقف و مقداری (البته در زبان پایتون درست این است که گفته شود: شی‌ایی) را به عنوان نتیجه به محل فراخوانی تابع بازمی‌گرداند:: +بدنه تابع می تواند حاوی کلمه کلیدی ``return`` نیز باشد. در واقع ``return`` دستوری است که در هر جایی از بدنه آورده شود، اجرای تابع در آن نقطه متوقف و مقداری (البته در زبان پایتون درست این است که گفته شود: شی‌ای) را به عنوان نتیجه به محل فراخوانی تابع بازمی‌گرداند:: def function_name(param1, param2,... paramN): ... @@ -136,11 +136,11 @@ >>> os.getcwd() '/home/saeid' -اما استفاده از نام‌های یک ماژول درون خودش چگونه است؟ جایی که فضا‌های نام دیگری همچون توابع نیز وجود دارند ولی هیچ پیشوندی مانند نام ماژول وجود ندارد که بتوان نام‌های درون این فضاهای متفاوت را از یکدیگر تمیز داد. برای اینکه بدانیم هر نام ماژول در هر نقطه‌ایی از همان ماژول چگونه مورد دستیابی قرار می‌گیرد با مفهوم دیگری به نام «**حوزه**» (**Scope**) آشنا می‌شویم. به صورت کلی حوزه به نواحی‌ایی از برنامه گفته می‌شود که می‌توان یک نام را بدون استفاده از هیچ پیشوندی و البته بدون تداخل با نام‌های دیگر به کار برد. بحث حوزه صرفا در داخل هر ماژول مطرح است. +اما استفاده از نام‌های یک ماژول درون خودش چگونه است؟ جایی که فضا‌های نام دیگری همچون توابع نیز وجود دارند ولی هیچ پیشوندی مانند نام ماژول وجود ندارد که بتوان نام‌های درون این فضاهای متفاوت را از یکدیگر تمیز داد. برای اینکه بدانیم هر نام ماژول در هر نقطه‌ایی از همان ماژول چگونه مورد دستیابی قرار می‌گیرد با مفهوم دیگری به نام «**حوزه**» (**Scope**) آشنا می‌شویم. به صورت کلی حوزه به نواحی‌ای از برنامه گفته می‌شود که می‌توان یک نام را بدون استفاده از هیچ پیشوندی و البته بدون تداخل با نام‌های دیگر به کار برد. بحث حوزه صرفا در داخل هر ماژول مطرح است. *قوانین حوزه:* -* بدنه ماژول - منظور نواحی‌ایی که خارج از بدنه توابع و کلاس‌ها قرار دارد - **حوزه سراسری** (**Global Scope**) است. توجه داشته باشید که واژه «سراسری» در بحث حوزه (یا فضانام) تنها به سراسر کدهای داخل هر ماژول اشاره دارد و نه سراسر برنامه. به صورت کلی هر جایی از زبان پایتون که واژه سراسری (Global) را شنیدید (یا خواندید) به یاد ماژول بیافتید:: +* بدنه ماژول - منظور نواحی‌ای که خارج از بدنه توابع و کلاس‌ها قرار دارد - **حوزه سراسری** (**Global Scope**) است. توجه داشته باشید که واژه «سراسری» در بحث حوزه (یا فضانام) تنها به سراسر کدهای داخل هر ماژول اشاره دارد و نه سراسر برنامه. به صورت کلی هر جایی از زبان پایتون که واژه سراسری (Global) را شنیدید (یا خواندید) به یاد ماژول بیافتید:: # This is a global variable a = 0 @@ -230,7 +230,7 @@ outer: 2 >>> -* وقتی از متغیری استفاده می‌کنیم، مفسر پایتون ابتدا می‌بایست حوزه و فضانام آن را تشخیص دهد تا بتواند شی‌ایی که این متغیر به آن ارجاع دارد را پیدا کند. فرض کنیم متغیری درون عبارتی در بدنه یک تابع به کار رفته باشد در این صورت مفسر ابتدا حوزه محلی که متغیر در آن وجود دارد را برای یافتن تعریف متغیر جستجو می‌کند و چنانچه نیابد به سراغ حوزه محلی تابع بیرونی آن - در صورت وجود - می‌رود و همینطور ادامه می‌دهد که در نهایت حوزه سراسری ماژول و پس از آن نیز Built-in را بررسی می‌کند؛ اگر هم به نتیجه‌ایی نرسد یک استثنا ``NameError`` رخ می‌دهد:: +* وقتی از متغیری استفاده می‌کنیم، مفسر پایتون ابتدا می‌بایست حوزه و فضانام آن را تشخیص دهد تا بتواند شی‌ای که این متغیر به آن ارجاع دارد را پیدا کند. فرض کنیم متغیری درون عبارتی در بدنه یک تابع به کار رفته باشد در این صورت مفسر ابتدا حوزه محلی که متغیر در آن وجود دارد را برای یافتن تعریف متغیر جستجو می‌کند و چنانچه نیابد به سراغ حوزه محلی تابع بیرونی آن - در صورت وجود - می‌رود و همینطور ادامه می‌دهد که در نهایت حوزه سراسری ماژول و پس از آن نیز Built-in را بررسی می‌کند؛ اگر هم به نتیجه‌ایی نرسد یک استثنا ``NameError`` رخ می‌دهد:: >>> x = 0 >>> @@ -290,7 +290,7 @@ *با فراخوانی تابع f در نمونه کد بالا، متغیر محلی a ایجاد می‌گردد که به شی صحیح 3 اشاره دارد.* -توجه داشته باشید که با انتساب شی‌ایی جدید به پارامترهای تابع، عملا ارسال آرگومان بی‌تاثیر می‌گردد:: +توجه داشته باشید که با انتساب شی‌ای جدید به پارامترهای تابع، عملا ارسال آرگومان بی‌تاثیر می‌گردد:: >>> def f(a): ... a = 2 @@ -317,7 +317,7 @@ *همانطور که در نمونه کد بالا قابل مشاهده است، مقدار متغییر b بدون تغییر باقی مانده است.* -ولی در شیوه by reference به جای ارسال یک کپی از مقدار آرگومان، یک ارجاع (reference) به آن آرگومان به تابع ارسال می‌گردد. می‌توان این‌طور در نظر گرفت که پارامتر متناظر در تابع، همان آرگومان در خارج از تابع است. در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان در خارج از تابع نیز تغییر می‌کند. به مثال پایتونی پایین توجه نمایید:: +ولی در شیوه by reference به جای ارسال یک کپی از مقدار آرگومان، یک ارجاع (reference) به از آرگومان به تابع ارسال می‌گردد. می‌توان این‌طور در نظر گرفت که پارامتر متناظر در تابع، همان آرگومان در خارج از تابع است. در نتیجه با تغییر مقدار پارامتر متناظر در تابع، مقدار آرگومان در خارج از تابع نیز تغییر می‌کند. به مثال پایتونی پایین توجه نمایید:: >>> def f(a): ... a[0] = 3 @@ -417,10 +417,19 @@ * سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت در ازای هر پارامتر یک آرگومان نظیر ارسال گردد. عمل تطابق در این سینتکس بر اساس موقعیت آرگومان‌ها انجام می‌شود که در نتیجه می‌بایست ترتیب آرگومان‌ها، متناظر با ترتیب پارامترها در سرآیند تابع باشد:: >>> def f(a, b, c): - ... print(a, b, c) + ... print("a= ", a) + ... print("b= ", b) + ... print("c= ", c) ... >>> f(1, 2, 3) - 1 2 3 + a= 1 + b= 2 + c= 3 + >>> f("one", 2, [3,33,333]) + a= one + b= 2 + c= [3, 33, 333] + >>> * سینتکس نام=مقدار، در این سینتکس آرگومان‌ها به نام پارامترها انتساب داده می‌شوند و از آنجا که عمل تطابق بر اساس نام پارامترها انجام می‌شود دیگر موقعیت یا ترتیب آرگومان‌ها اهمیتی ندارد:: @@ -435,14 +444,20 @@ >>> def f(a, b, c): - ... print(a, b, c) + ... print("a= ", a) + ... print("b= ", b) + ... print("c= ", c) ... >>> f(1, c=3, b=2) - 1 2 3 + a= 1 + b= 2 + c= 3 >>> f(1, 2, c=3) - 1 2 3 - >>> f(1, 2, 3) - 1 2 3 + a= 1 + b= 2 + c= 3 + >>> + برای تابع مثال بالا، حالت‌های فراخوانی پایین نادرست هستند:: @@ -467,11 +482,26 @@ * سینتکس ``iterable*``، در این سینتکس یک شی از نوع تکرارپذیر (iterable - درس نهم) مانند انواع رشته، تاپل، لیست و... که توسط یک کاراکتر ستاره ``*‍‍`` نشانه‌گذاری شده است، به تابع ارسال می‌گردد. در این صورت بر اساس ترتیب موقعیت، اعضای درون شی تکرارپذیر به پارامتر‌های تابع اختصاص می‌یابند:: >>> def f(a, b, c): - ... print(a, b, c) + ... print("a= ", a) + ... print("b= ", b) + ... print("c= ", c) ... - >>> b = [1, 2, 3] - >>> f(*b) - 1 2 3 + >>> + >>>my_list = [1, 2, 3] + >>> + >>> f(*my_list) + a= 1 + b= 2 + c= 3 + >>> + >>> my_list_2 = [1, 2, 3, 4] + >>> + >>> f(*my_list_2) + Traceback (most recent call last): + File "", line 1, in + TypeError: f() takes 3 positional arguments but 4 were given + >>> + * سینتکس ``dict**``، در این سینتکس یک شی دیکشنری که توسط دو کاراکتر ستاره ``**`` نشانه‌گذاری شده است به تابع ارسال می‌شود. کلید‌های این شی دیکشنری می‌بایست هم‌نام با پارامترهای تعریف شده در سرآیند تابع باشند. پس از فراخوانی تابع، این شی دیکشنری باز می‌شود و بر اساس نام کلید در جفت‌های کلید:مقدار درون آن، پارامترهای تابع مقداردهی می‌شوند:: @@ -483,11 +513,11 @@ >>> f(**b) 1 2 3 -این چهار سینتکس بر اعمال در هنگام فراخوانی تابع بحث می‌کنند و در تمام آن‌ها می‌بایست تعداد آرگومان‌های ارسالی با تعداد پارامترهای تعریف شده در سرآیند تابع برابر باشد و البته بدیهی است که در دو سینتکس پایانی لازم است تعداد اعضای شی تکرارپذیر یا تعداد جفت‌های کلید:مقدار شی دیکشنری با تعداد پارامترهای تابع برابر باشند. +**این چهار سینتکس بر تعیین آرگومان‌ها در هنگام فراخوانی تابع بحث می‌کردند و در تمام آن‌ها می‌بایست تعداد آرگومان‌های ارسالی با تعداد پارامترهای تعریف شده در سرآیند تابع برابر باشد و البته بدیهی است که در دو سینتکس پایانی لازم است تعداد اعضای شی تکرارپذیر یا تعداد جفت‌های کلید:مقدار شی دیکشنری با تعداد پارامترهای تابع برابر باشند.** در ادامه به ارایه سینتکس‌هایی در این زمینه می‌پردازیم که هنگام تعیین پارامترهای تابع نقش دارند. -* سینتکس معمول که تاکنون استفاده می‌کردیم یعنی به صراحت تک تک پارامترها را تعریف کنیم:: +* **سینتکس معمول** که تاکنون استفاده می‌کردیم یعنی به صراحت تک تک پارامترها را تعریف کنیم:: >>> def f(a, b, c): ... print(a, b, c) @@ -495,7 +525,7 @@ >>> f(1, 2, 3) 1 2 3 -* سینتکس تعیین مقدار پیش‌فرض برای پارامترها. می‌توان هنگام تعیین هر پارامتر در تعریف تابع، مقداری را نیز به آن انتساب داد؛ در این شرایط اگر آرگومانی نظیر با آن پارامتر ارسال نگردد، مقدار پیش‌فرض آن پارامتر در نظر گرفته خواهد شد. به این گونه پارامترها، اختیاری نیز گفته می‌شود:: +* **سینتکس تعیین مقدار پیش‌فرض برای پارامترها**. می‌توان هنگام تعیین هر پارامتر در تعریف تابع، مقداری را نیز به آن انتساب داد؛ در این شرایط اگر آرگومانی نظیر با آن پارامتر ارسال نگردد، مقدار پیش‌فرض آن پارامتر در نظر گرفته خواهد شد. به این گونه پارامترها، **اختیاری** نیز گفته می‌شود:: >>> def chaap(text=None): ... if text: @@ -561,32 +591,50 @@ :: >>> def f(a, b=2, *args): - ... print(a, b , args) + ... print("a= ", a) + ... print("b= ", b) + ... print("args= ", args) ... >>> >>> f(1) - 1 2 () + a= 1 + b= 2 + args= () + >>> f(1, 2, 3) - 1 2 (3,) + a= 1 + b= 2 + args= (3,) + :: - >>> a = [3, (4, 5)] - >>> f(a) - [3, (4, 5)] 2 () + >>> a_list = [3, (4, 5)] + >>> + >>> f(a_list) + a= [3, (4, 5)] + b= 2 + args= () + :: >>> f(1, 4, [8, 12, 16]) - 1 4 ([8, 12, 16],) + a= 1 + b= 4 + args= ([8, 12, 16],) :: - >>> a = [3, 6, 9, (10, 11)] - >>> f(*a) - 3 6 (9, (10, 11)) + >>> a_list = [3, 6, 9, (10, 11)] + >>> + >>> f(*a_list) + a= 3 + b= 6 + args= (9, (10, 11)) + :: From 5188dc851887562f6d2cb72ff1ed663da645cd4a Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Wed, 26 Jun 2019 13:31:51 +0430 Subject: [PATCH 020/316] l12 - last edit --- lessons/l12.rst | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/lessons/l12.rst b/lessons/l12.rst index a8275b4..2e4957e 100644 --- a/lessons/l12.rst +++ b/lessons/l12.rst @@ -8,7 +8,7 @@ درس ۱۲: تابع - بخش یکم ======================== - +این درس به معرفی مفهوم تابع در زبان برنامه‌نویسی پایتون می‌پردازد. @@ -571,7 +571,7 @@ -* سینتکس ``name*``، تمام آرگومان‌های ارسالی را در قالب یه شی تاپل دریافت می‌کند- این قابلیت در مواقعی که تعداد آرگومان‌های ارسالی متغییر است کمک بزرگی می‌کند:: +* سینتکس ``name*``، تمام آرگومان‌های ارسالی را در قالب یه شی تاپل دریافت می‌کند - این قابلیت در مواقعی که تعداد آرگومان‌های ارسالی متغییر است کمک بزرگی می‌کند:: >>> def f(*name): ... print(type(name)) @@ -603,12 +603,31 @@ args= () - >>> f(1, 2, 3) + >>> f(1, 5) a= 1 - b= 2 + b= 5 + args= () + + + >>> f(1, "FF", 3) + a= 1 + b= FF args= (3,) + >>> f(1, "FF", 3, 4, 5) + a= 1 + b= FF + args= (3, 4, 5) + + + >>> f() + Traceback (most recent call last): + File "", line 1, in + TypeError: f() missing 1 required positional argument: 'a' + + + :: >>> a_list = [3, (4, 5)] @@ -634,21 +653,27 @@ a= 3 b= 6 args= (9, (10, 11)) - - + :: - - >>> f(b=10, a=5, c=15) + + >>> def f(a, *b, c): + ... print(a, b, c) + ... + >>> f(a=1, b=2, c=3) Traceback (most recent call last): File "", line 1, in - TypeError: f() got an unexpected keyword argument 'c' + TypeError: f() got an unexpected keyword argument 'b' + >>> + + + توجه داشته باشید که نمی‌توان آرگومان را با استفاده از شیوه **نام=مقدار** به پارامتر ستاره‌دار ارسال کرد. **Keyword-Only Arguments** `PEP 3102 `_ - در پایتون نسخه 2x پس از پارامتری ستاره‌دار، نمی‌توان پارامتر دیگری قرار داد و این امکان تنها در پایتون نسخه 3x امکان‌‌پذیر می‌باشد. باید توجه داشت که در این نسخه‌ (3x) آرگومان نظیر تمامی پارامترهایی که پس از پارامتر ستاره‌دار قرار گرفته‌اند، می‌بایست به صورت **نام=مقدار** ارسال گردند. + در پایتون نسخه 2x پس از پارامتر ستاره‌دار، نمی‌توان پارامتر دیگری قرار داد و این امکان تنها در پایتون نسخه 3x امکان‌‌پذیر می‌باشد. باید توجه داشت که در این نسخه‌ (3x) آرگومان نظیر تمامی پارامترهایی که پس از پارامتر ستاره‌دار قرار گرفته‌اند، می‌بایست به صورت **نام=مقدار** ارسال گردند. تابع با سرآیند ``(def f(a, *b, c`` را در نظر بگیرید. در چنین شرایطی که پارامتر ``a`` با استفاده از موقعیت آن مقدار دهی می‌شود و پارامتر ``b`` هر تعداد آرگومان دیگری را دریافت می‌کند، دیگر برای ارسال آرگومان به پارامتر ``c`` چاره‌ای جز ذکر نام آن باقی نمی‌ماند! :: @@ -715,7 +740,7 @@ -* سینتکس ``name**``، تمام آرگومان‌های کلید:مقدار ارسالی را در قالب یک شی دیکشنری دریافت می‌کند:: +* سینتکس ``name**``، تمام آرگومان‌های **کلید:مقدار** ارسالی را در قالب یک شی دیکشنری دریافت می‌کند:: >>> def f(**name): ... print(type(name)) From 4ea68fec8f1781ff0329c621dcc7b1224c986389 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Wed, 26 Jun 2019 13:38:07 +0430 Subject: [PATCH 021/316] add l12 --- lessons/l11.rst | 2 +- lessons/l12.rst | 1 - log.rst | 10 ++++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lessons/l11.rst b/lessons/l11.rst index 29da135..c000674 100644 --- a/lessons/l11.rst +++ b/lessons/l11.rst @@ -5,7 +5,7 @@ :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, پایتون -درس ۱۱: کتابخانه استاندارد (بخش ۱) +درس ۱۱: کتابخانه استاندارد - بخش یکم ==================================== کتابخانه استاندارد پایتون مجموعه‌ وسیعی از امکانات آماده است که با نصب پایتون در اختیار قرار می‌گیرد. فهرست کامل این امکانات را می‌توانید از نشانی‌های `(پایتون 2x) `_ و `(پایتون 3x) `_ مشاهده نمایید. لازم به یادآوری است که بخشی بزرگی از قدرت پایتون به دلیل وجود کتابخانه‌های فراوان و قدرتمند آن است که تعداد زیادی از آن‌ها خارج کتابخانه استاندارد پایتون و درون جامعه کاربری در حال توسعه هستند که فهرست تقریبا کاملی از آن‌ها نیز توسط `PyPI `_ قابل جستجو و دریافت هستند. diff --git a/lessons/l12.rst b/lessons/l12.rst index 2e4957e..68e709c 100644 --- a/lessons/l12.rst +++ b/lessons/l12.rst @@ -799,6 +799,5 @@ :emoji-size:`😊` امیدوارم مفید بوده باشه -`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ diff --git a/log.rst b/log.rst index fd9e58c..8cd35f1 100644 --- a/log.rst +++ b/log.rst @@ -10,6 +10,16 @@ ============= +.. raw:: html + +

00110 - چهارشنبه ۵ تیر ۱۳۹۸

+ +درس دوازدهم اضافه شد. با امید اینکه بروز رسانی‌های بعدی در فاصله زمانی کمتری انجام بشه. +:emoji-size:`😉` + +---- + + .. raw:: html

00109 - سه‌شنبه ۲۶ اردیبهشت ۱۳۹۶

From 63a426e1b019cd0bf0d2faf1d75b5d2abcab592b Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Wed, 26 Jun 2019 15:22:32 +0430 Subject: [PATCH 022/316] create donation reports page --- _templates/sphinx_minoo_theme/static/minoo.js | 3 + donate.rst | 211 ++++++++++++++++++ index.rst | 1 + log.rst | 8 + 4 files changed, 223 insertions(+) create mode 100644 donate.rst diff --git a/_templates/sphinx_minoo_theme/static/minoo.js b/_templates/sphinx_minoo_theme/static/minoo.js index dbbf7c0..b78a81a 100644 --- a/_templates/sphinx_minoo_theme/static/minoo.js +++ b/_templates/sphinx_minoo_theme/static/minoo.js @@ -127,6 +127,9 @@ $( document ).ready(function() { if ($(this).text().indexOf("پیش‌گفتار")>=0) { $(this).addClass('reportmenufield'); } + if ($(this).text().indexOf("گزارش هدایای پرداخت شده")>=0) { + $(this).addClass('reportmenufield'); + } if ($(this).text().indexOf("خودآزمایی") >= 0) { $(this).addClass('exercisesmenufield'); } diff --git a/donate.rst b/donate.rst new file mode 100644 index 0000000..5db0d5c --- /dev/null +++ b/donate.rst @@ -0,0 +1,211 @@ +.. role:: emoji-size + + +.. meta:: + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - صفحه گزارش هدایای پرداخت شده + :keywords: پایتون, آموزش, آموزش برنامه نویسی, آموزش پایتون, برنامه نویسی, کتاب آموزش, آموزش فارسی, کتاب آزاد + + +گزارش هدایای پرداخت شده +========================= + +مبالغ مهم نیستند، از اقدام شما دوستان بسیار سپاسگذارم. + + +| + +| + +| + + + +.. raw:: html + +

26: 50,000 تومان در زمان 16:52 28-03-1398

+ +---- + +.. raw:: html + +

25: 50,000 تومان در زمان 09:13 08-02-1398

+ +---- + +.. raw:: html + +

24: 50,000 تومان در زمان 22:44 26-01-1398

+ +---- + +سال 1397: 92,000 تومان + +---- + +.. raw:: html + +

23: 5,000 تومان در زمان 13:52 23-11-1397

+ +---- + +.. raw:: html + +

22: 5,000 تومان در زمان 09:13 05-11-1397

+ +---- + +.. raw:: html + +

21: 10,000 تومان در زمان 15:25 01-11-1397

+ +---- + +.. raw:: html + +

20: 2,000 تومان در زمان 20:36 20-10-1397

+ +---- + +.. raw:: html + +

19: 1,000 تومان در زمان 13:47 13-10-1397

+ +---- + +.. raw:: html + +

18: 1,000 تومان در زمان 09:35 28-07-1397

+ +---- + +.. raw:: html + +

17: 1,000 تومان در زمان 18:39 20-07-1397

+ +---- + +.. raw:: html + +

16: 25,000 تومان در زمان 16:45 10-06-1397

+ +---- + +.. raw:: html + +

15: 2,000 تومان در زمان 12:45 24-05-1397

+ +---- + +.. raw:: html + +

14: 20,000 تومان در زمان 19:50 08-04-1397

+ +---- + +.. raw:: html + +

13: 10,000 تومان در زمان 22:27 04-04-1397

+ +---- + +.. raw:: html + +

12: 10,000 تومان در زمان 18:30 26-02-1397

+ +---- + +سال 1396: 61,000 تومان + +---- + +.. raw:: html + +

11: 5,000 تومان در زمان 17:51 06-12-1396

+ +---- + +.. raw:: html + +

10: 10,000 تومان در زمان 21:23 10-09-1396

+ +---- + +.. raw:: html + +

9: 5,000 تومان در زمان 21:00 07-09-1396

+ +---- + +.. raw:: html + +

8: 10,000 تومان در زمان 08:39 06-08-1396

+ +---- + +.. raw:: html + +

7: 10,000 تومان در زمان 13:50 13-07-1396

+ +---- + +.. raw:: html + +

6: 1,000 تومان در زمان 10:04 11-06-1396

+ +---- + +.. raw:: html + +

5: 10,000 تومان در زمان 22:44 16-04-1396

+ +---- + +.. raw:: html + +

4: 10,000 تومان در زمان 17:51 11-04-1396

+ +---- + +سال 1395: 18,000 تومان + +---- + + +.. raw:: html + +

3: 10,000 تومان در زمان 19:33 27-11-1395

+ +---- + +.. raw:: html + +

2: 5,000 تومان در زمان 20:51 15-11-1395

+ +---- + +.. raw:: html + +

1: 3,000 تومان در زمان 11:27 09-11-1395

+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.rst b/index.rst index 8151cf6..696ada8 100644 --- a/index.rst +++ b/index.rst @@ -28,6 +28,7 @@ lessons/l11 lessons/l12 log + donate | diff --git a/log.rst b/log.rst index 8cd35f1..ca07fc3 100644 --- a/log.rst +++ b/log.rst @@ -9,6 +9,14 @@ گزارش توسعه ============= +.. raw:: html + +

00111 - چهارشنبه ۵ تیر ۱۳۹۸

+ +صفحه گزارش هدایای پرداخت شده به منظور شفافیت مالی اضافه گردید. :)) + +---- + .. raw:: html From f5daa7285f13315350fb7d8181a7012304e36c9c Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Fri, 28 Jun 2019 19:14:02 +0430 Subject: [PATCH 023/316] create l13 --- index.rst | 1 + lessons/l13.rst | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 lessons/l13.rst diff --git a/index.rst b/index.rst index 696ada8..3a64957 100644 --- a/index.rst +++ b/index.rst @@ -27,6 +27,7 @@ lessons/l10 lessons/l11 lessons/l12 + lessons/l13 log donate diff --git a/lessons/l13.rst b/lessons/l13.rst new file mode 100644 index 0000000..43d06c5 --- /dev/null +++ b/lessons/l13.rst @@ -0,0 +1,114 @@ +.. role:: emoji-size + +.. meta:: + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس سیزدهم تابع + :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, پایتون + + +درس ۱۳: تابع - بخش دوم +======================== + + + + + + + + +:emoji-size:`✔` سطح: متوسط + +---- + + +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + + + +Decorator (تزئین‌گر) +-------------------- + + +تزئین‌گرها یا همان **Decorator‌** ها توابعی هستند که به منظور پوشش (wrap) توابع یا کلاس‌های دیگر پیاده‌سازی می‌شوند. Decorator‌ها در پایتون ابزار بسیار کاربردی و مفیدی هستند که به برنامه‌نویس این امکان را می‌دهند تا بدون تغییر در بدنه توابع و کلاس‌های خود، رفتار و ویژگی‌های آن‌ها را گسترش دهد. + +برای پوشش یک تابع توسط Decorator‌ از سینتکسی مشابه ``decorator‌_name@`` در بالای بخش سرآیند استفاده می‌شود: + +:: + + @decorator_name + def function_name(): + print("Somthing!") + + + function_name() + +مفهومی که این سینتکس (``decorator‌_name`` + ``@``) در بالای بخش سرآیند یک تابع برای مفسر پایتون ایجاد می‌کند کاملا مشابه با سینتکس پایین است:: + + wrapper = decorator_name(function_name) + wrapper() + +هر چیزی در پایتون یک شی است حتی مفاهیم پیچیده‌ای به مانند تابع؛ از درس پیش نیز به خاطر داریم که تابع در پایتون یک موجودیت **”first-class“** است که یعنی می‌توان تابع را مانند دیگر اشیا به صورت آرگومان به توابع دیگر ارسال نمود. نمونه کد بالا نیز نمایش ارسال یک تابع (``function_name``) به تابعی دیگر (``decorator‌_name``) است. + + +به مثال پایین توجه نمایید: + +:: + + >>> def decorator_name(func): + ... def wrapper(): + ... print("Something is happening before the function is called.") + ... func() + ... print("Something is happening after the function is called.") + ... return wrapper + ... + >>> + >>> @decorator_name + ... def function_name(): + ... print("Somthing!") + ... + >>> + >>> function_name() + Something is happening before the function is called. + Somthing! + Something is happening after the function is called. + >>> + +نمونه کد بالا را می‌توان با ساختار ساده زیر نیز در نظر گرفت: + +:: + + >>> def decorator_name(func): + ... def wrapper(): + ... print("Something is happening before the function is called.") + ... func() + ... print("Something is happening after the function is called.") + ... return wrapper + ... + >>> + >>> def function_name(): + ... print("Somthing!") + ... + >>> + >>> wrapper = decorator_name(function_name) + >>> wrapper() + Something is happening before the function is called. + Somthing! + Something is happening after the function is called. + >>> + +همانطور که با مقایسه دو نمونه کد بالا قابل مشاهده است، Decorator‌ها یک روپوش (wrapper) برای توابع و کلاس‌های ما بوجود می‌آورند. در هنگام فراخوانی تابع ``function_name`` مفسر پایتون متوجه decorator‌ آن شده است و به جای اجرا، یک نمونه شی از آن را به decorator‌ مشخص شده (``decorator‌_name``) ارسال می‌کند و یک شی جدید که در اینجا با عنوان ``wrapper`` مشخص شده است را دریافت و اجرا می‌کند. + + + + +| + +---- + +:emoji-size:`😊` امیدوارم مفید بوده باشه + + + From 1cddb8d2031f9f64c1a35a67bb99c27603e7b689 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 29 Jun 2019 16:21:29 +0430 Subject: [PATCH 024/316] complete decorators and start generators --- lessons/l13.rst | 180 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 4 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index 43d06c5..004c0eb 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -28,11 +28,11 @@ -Decorator (تزئین‌گر) --------------------- +Decorator +---------- -تزئین‌گرها یا همان **Decorator‌** ها توابعی هستند که به منظور پوشش (wrap) توابع یا کلاس‌های دیگر پیاده‌سازی می‌شوند. Decorator‌ها در پایتون ابزار بسیار کاربردی و مفیدی هستند که به برنامه‌نویس این امکان را می‌دهند تا بدون تغییر در بدنه توابع و کلاس‌های خود، رفتار و ویژگی‌های آن‌ها را گسترش دهد. +دکوراتور (تزئین‌گر) یا همان **Decorator‌** ها [`PEP 318 `__] به توابعی گفته می‌شود که به منظور پوشش (wrap) توابع یا کلاس‌های دیگر پیاده‌سازی می‌شوند. Decorator‌ها در پایتون ابزار بسیار کاربردی و مفیدی هستند که به برنامه‌نویس این امکان را می‌دهند تا با کاهش حجم کدنویسی و بدون تغییر در بدنه توابع و کلاس‌های خود، رفتار و ویژگی‌های آن‌ها را گسترش دهد. در این بخش تمرکز بر روی اعمال Decorator‌ها به توابع است و Decorator‌ کلاس را در درس مربوط به کلاس‌ها بررسی خواهیم کرد. برای پوشش یک تابع توسط Decorator‌ از سینتکسی مشابه ``decorator‌_name@`` در بالای بخش سرآیند استفاده می‌شود: @@ -99,7 +99,179 @@ Decorator (تزئین‌گر) Something is happening after the function is called. >>> -همانطور که با مقایسه دو نمونه کد بالا قابل مشاهده است، Decorator‌ها یک روپوش (wrapper) برای توابع و کلاس‌های ما بوجود می‌آورند. در هنگام فراخوانی تابع ``function_name`` مفسر پایتون متوجه decorator‌ آن شده است و به جای اجرا، یک نمونه شی از آن را به decorator‌ مشخص شده (``decorator‌_name``) ارسال می‌کند و یک شی جدید که در اینجا با عنوان ``wrapper`` مشخص شده است را دریافت و اجرا می‌کند. +همانطور که با مقایسه دو نمونه کد بالا قابل مشاهده است، Decorator‌ها یک روپوش (wrapper) برای توابع و کلاس‌های ما بوجود می‌آورند. در هنگام فراخوانی تابع ``function_name`` مفسر پایتون متوجه decorator‌ آن شده است و به جای اجرا، یک نمونه شی از آن را به decorator‌ مشخص شده (``decorator‌_name``) ارسال می‌کند و یک شی جدید که در اینجا با تابع ``wrapper`` مشخص شده است را دریافت و اجرا می‌کند. + +در مورد توابع دارای پارامتر نیز باید توجه داشت که در هنگام فراخوانی تابع مورد نظر و ارسال آرگومان به تابع، مفسر پایتون این آرگومان‌ها را به تابع ``wrapper`` از decorator‌ ارسال می‌کند:: + + >>> def multiply_in_2(func): + ... def wrapper(*args): + ... return func(*args) * 2 + ... return wrapper + ... + >>> + >>> @multiply_in_2 + ... def sum_two_numbers(a, b): + ... return a + b + ... + >>> + >>> sum_two_numbers(2, 3) + 10 + +:: + + >>> # normal + >>> + >>> def multiply_in_2(func): + ... def wrapper(*args): + ... return func(*args) * 2 + ... return wrapper + ... + >>> + >>> def sum_two_numbers(a, b): + ... return a + b + ... + >>> + >>> wrapper = multiply_in_2(sum_two_numbers) + >>> wrapper(2, 3) + 10 + + + + +می‌توان بیش از یک Decorator‌ به کلاس‌ها و توابع خود اعمال کرد که در این صورت ترتیب قرار گرفتن این Decorator‌ها برای مفسر پایتون دارای اهمیت است:: + + @decorator_3 + @decorator_2 + @decorator_1 + def function_name(): + print("Somthing!") + + + function_name() + + +:: + + wrapper = decorator_3(decorator_2(decorator_1(function_name))) + wrapper() + + +همچنین می‌توان به Decorator‌ها آرگومان نیز ارسال کرد:: + + @decorator_name(params) + def function_name(): + print("Somthing!") + + + function_name() + +در این حالت مفسر پایتون ابتدا آرگومان را به تابع Decorator‌ ارسال می‌کند و سپس حاصل را با آرگومان ورودی تابع مورد نظر فراخوانی می‌کند:: + + temp_decorator = decorator_name(params) + wrapper = temp_decorator(function_name) + wrapper() + +به نمونه کد پایین توجه نمایید:: + + >>> def formatting(lowerscase=False): + ... def formatting_decorator(func): + ... def wrapper(text=''): + ... if lowerscase: + ... func(text.lower()) + ... else: + ... func(text.upper()) + ... return wrapper + ... return formatting_decorator + ... + >>> + >>> @formatting(lowerscase=True) + ... def chaap(message): + ... print(message) + ... + >>> + >>> chaap("I Love Python") + i love python + >>> + + +Generator +---------- + +ژنراتور (مولد) یا همان **Generator‌** ها [`PEP 255 `__] به توابعی گفته می‌شود که به منظور ایجاد یک تابع با رفتاری مشابه اشیا ``iterator`` (تکرارکننده - درس نهم) پیاده‌سازی می‌شوند. + +بر خلاف شی لیست، عملکرد Generator‌ به صورت **lazy** (کندرو) [`ویکی‌پدیا `__] می‌باشد و داده‌ها را یکجا ذخیره نمی‌کند بلکه آنها را تنها در همان زمانی که درخواست می‌شوند، **تولید** (Generate) می‌کند. بنابراین در هنگام برخورد با مجموعه داده‌های بزرگ، Generator‌ها مدیریت حافظه کارآمدتری دارند. + +برای ایجاد یک تابع Generator تنها کافی است در یک تابع معمولی از دستور ``yield`` استفاده کنیم. اکنون مفسر پایتون در هنگام فراخوانی این تابع یک شی ``generator`` برمی‌گرداند که توانایی تولید یک **دنباله** (Sequence) از مقادیر (شی) برای استفاده در کاربردهای تکرارپذیر را دارد. به نمونه کد پایین توجه نمایید:: + + + >>> def a_generator_function(): + ... for i in range(3): # i: 0, 1, 2 + ... yield i*i + ... + >>> + >>> my_generator = a_generator_function() # Create a generator + >>> + >>> type(my_generator) + + >>> + >>> for i in my_generator: + ... print(i) + ... + 0 + 1 + 4 + >>> + +دستور ``yield`` را می‌توان همانند دستور ``return`` دانست با این تفاوت که پس از توقف اجرای تابع، وضعیت تابع را نیز حفظ می‌کند. به همین دلیل می‌توان ادامه دنباله را از پی گرفت. + + +:: + + >>> def a_generator_function(): + ... for i in range(3): + ... yield i*i + ... + >>> my_generator = a_generator_function() + >>> + >>> my_generator.__next__() # Use my_generator.next() in Python 2.x + 0 + >>> my_generator.__next__() + 1 + >>> my_generator.__next__() + 4 + >>> my_generator.__next__() + Traceback (most recent call last): + File "", line 1, in + StopIteration + >>> + +مقادیر دنباله مورد نظر خود را می‌توانیم با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) درخواست نماییم. باید توجه داشت که پایان این دنباله توسط استثنا ``StopIteration`` گزارش می‌شود. در زمان استفاده از دستور ``for`` این استثنا کنترل شده و حلقه پایان می‌پذیرد. + +به یک نمونه کد دیگر نیز توجه نمایید:: + + >>> def countdown(n): + ... print("Counting down from %d" % n) + ... while n > 0: + ... yield n + ... n -= 1 + ... return + ... + >>> + >>> countdown_generator = countdown(10) + >>> + >>> countdown_generator.__next__() + Counting down from 10 + 10 + >>> countdown_generator.__next__() + 9 + >>> countdown_generator.__next__() + 8 + >>> countdown_generator.__next__() + 7 + >>> + + + From 28e8e13b5ea4f4c70ee0e66280ce39313070eab0 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Sun, 7 Jul 2019 00:11:31 +0430 Subject: [PATCH 025/316] work on yield - l13 --- lessons/l13.rst | 56 ++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index 004c0eb..addd0ed 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -199,53 +199,65 @@ Generator ژنراتور (مولد) یا همان **Generator‌** ها [`PEP 255 `__] به توابعی گفته می‌شود که به منظور ایجاد یک تابع با رفتاری مشابه اشیا ``iterator`` (تکرارکننده - درس نهم) پیاده‌سازی می‌شوند. -بر خلاف شی لیست، عملکرد Generator‌ به صورت **lazy** (کندرو) [`ویکی‌پدیا `__] می‌باشد و داده‌ها را یکجا ذخیره نمی‌کند بلکه آنها را تنها در همان زمانی که درخواست می‌شوند، **تولید** (Generate) می‌کند. بنابراین در هنگام برخورد با مجموعه داده‌های بزرگ، Generator‌ها مدیریت حافظه کارآمدتری دارند. +بر خلاف شی لیست، عملکرد Generator‌ به صورت **lazy** (کندرو) [`ویکی‌پدیا `__] می‌باشد و داده‌ها را یکجا ذخیره نمی‌کند بلکه آنها را تنها در همان زمانی که درخواست می‌شوند، **تولید** (Generate) می‌کند. بنابراین در هنگام برخورد با مجموعه داده‌های بزرگ، Generator‌ها مدیریت حافظه کارآمدتری دارند و همچینین ما مجبور نیستیم پیش از استفاده از یک دنباله منتظر بمانیم تا تمام مقادیر آن تولید شوند!. -برای ایجاد یک تابع Generator تنها کافی است در یک تابع معمولی از دستور ``yield`` استفاده کنیم. اکنون مفسر پایتون در هنگام فراخوانی این تابع یک شی ``generator`` برمی‌گرداند که توانایی تولید یک **دنباله** (Sequence) از مقادیر (شی) برای استفاده در کاربردهای تکرارپذیر را دارد. به نمونه کد پایین توجه نمایید:: +برای ایجاد یک تابع Generator تنها کافی است در یک تابع معمولی از دستور ``yield`` استفاده کنیم.اکنون مفسر پایتون در هنگام فراخوانی این تابع یک شی ``generator`` برمی‌گرداند که توانایی تولید یک **دنباله** (Sequence) از مقادیر (شی) برای استفاده در کاربردهای تکرارپذیر را دارد. + +دستور ``yield`` روند اجرای برنامه را با حفظ وضعیت، متوقف می‌کند و می‌توانیم با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) روند اجرای تابع را در دست بگیریم:: >>> def a_generator_function(): - ... for i in range(3): # i: 0, 1, 2 + ... for i in range(3): ... yield i*i ... - >>> >>> my_generator = a_generator_function() # Create a generator >>> - >>> type(my_generator) - - >>> - >>> for i in my_generator: - ... print(i) - ... + >>> my_generator.__next__() # Use my_generator.next() in Python 2.x 0 + >>> my_generator.__next__() 1 + >>> my_generator.__next__() 4 + >>> my_generator.__next__() + Traceback (most recent call last): + File "", line 1, in + StopIteration >>> -دستور ``yield`` را می‌توان همانند دستور ``return`` دانست با این تفاوت که پس از توقف اجرای تابع، وضعیت تابع را نیز حفظ می‌کند. به همین دلیل می‌توان ادامه دنباله را از پی گرفت. -:: +همانطور که در انتهای درس نهم (بخش «شی تکرارکننده») نیز اشاره شده بود، می‌توانیم مقادیر دنباله مورد نظر خود را با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) درخواست نماییم. باید توجه داشت که پایان این دنباله توسط استثنا ``StopIteration`` گزارش می‌شود. در زمان استفاده از دستور ``for`` این استثنا کنترل شده و حلقه پایان می‌پذیرد. نمونه کد قبل را به صورت زیر بازنویسی می‌کنیم:: >>> def a_generator_function(): - ... for i in range(3): + ... for i in range(3): # i: 0, 1, 2 ... yield i*i ... - >>> my_generator = a_generator_function() >>> - >>> my_generator.__next__() # Use my_generator.next() in Python 2.x + >>> my_generator = a_generator_function() # Create a generator + >>> + >>> type(my_generator) + + >>> + >>> for i in my_generator: + ... print(i) + ... 0 - >>> my_generator.__next__() 1 - >>> my_generator.__next__() 4 - >>> my_generator.__next__() - Traceback (most recent call last): - File "", line 1, in - StopIteration >>> -مقادیر دنباله مورد نظر خود را می‌توانیم با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) درخواست نماییم. باید توجه داشت که پایان این دنباله توسط استثنا ``StopIteration`` گزارش می‌شود. در زمان استفاده از دستور ``for`` این استثنا کنترل شده و حلقه پایان می‌پذیرد. + +**ویژگی‌های تابع Generator‌** + +* تابع Generator‌ یک تابع معمولی است که رفتاری مشابه با یک شی تکرارکننده (iterator) دارد. + +* تابع Generator‌ شامل یک یا چند دستور ``yield`` می‌باشد. + +* در زمان فراخوانی تابع Generator‌، تابع اجرا نمی‌شود ولی در عوض یک شی از نوع ``generator`` برای آن تابع برگردانده می‌شود. + +* با استفاده از دستور ``yield`` می‌توانیم در هر نقطه‌ای از تابع Generator‌ که بخواهیم توقف ایجاد کنیم - بدون از دست رفتن وضعیت فعلی تابع - و سپس با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) به ادامه روند اجرا برگردیم. + + به یک نمونه کد دیگر نیز توجه نمایید:: From e9f3234e2e6f0b335eb15f51bdf82253f1fc1504 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Sun, 7 Jul 2019 00:12:39 +0430 Subject: [PATCH 026/316] add online python console --- index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.rst b/index.rst index 3a64957..237656b 100644 --- a/index.rst +++ b/index.rst @@ -36,5 +36,9 @@ .. note:: کتاب در حال تکمیل است!. +.. raw:: html + + + From f7fb87ea675430a1d2cd8d3ed697f127edc46db1 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Sun, 7 Jul 2019 00:16:48 +0430 Subject: [PATCH 027/316] change position of online python console --- index.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/index.rst b/index.rst index 237656b..c62d637 100644 --- a/index.rst +++ b/index.rst @@ -33,12 +33,14 @@ | -.. note:: - کتاب در حال تکمیل است!. - .. raw:: html +| + +.. note:: + کتاب در حال تکمیل است!. + From 8b61dd9d6f16fc02d8b085f22c099112d53f45a3 Mon Sep 17 00:00:00 2001 From: Saeid Darvishi Date: Mon, 8 Jul 2019 00:20:01 +0430 Subject: [PATCH 028/316] complete generators - l13 --- lessons/l13.rst | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index addd0ed..ed5c76e 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -38,6 +38,10 @@ Decorator :: + def decorator_name(a_function): + pass + + @decorator_name def function_name(): print("Somthing!") @@ -199,9 +203,9 @@ Generator ژنراتور (مولد) یا همان **Generator‌** ها [`PEP 255 `__] به توابعی گفته می‌شود که به منظور ایجاد یک تابع با رفتاری مشابه اشیا ``iterator`` (تکرارکننده - درس نهم) پیاده‌سازی می‌شوند. -بر خلاف شی لیست، عملکرد Generator‌ به صورت **lazy** (کندرو) [`ویکی‌پدیا `__] می‌باشد و داده‌ها را یکجا ذخیره نمی‌کند بلکه آنها را تنها در همان زمانی که درخواست می‌شوند، **تولید** (Generate) می‌کند. بنابراین در هنگام برخورد با مجموعه داده‌های بزرگ، Generator‌ها مدیریت حافظه کارآمدتری دارند و همچینین ما مجبور نیستیم پیش از استفاده از یک دنباله منتظر بمانیم تا تمام مقادیر آن تولید شوند!. +بر خلاف شی‌ای به مانند لیست، عملکرد Generator‌ به صورت **lazy** (کندرو) [`ویکی‌پدیا `__] می‌باشد و داده‌ها را یکجا ذخیره نمی‌کند بلکه آنها را تنها در همان زمانی که درخواست می‌شوند، **تولید** (Generate) می‌کند. بنابراین در هنگام برخورد با مجموعه داده‌های بزرگ، Generator‌ها مدیریت حافظه کارآمدتری دارند و همچنین ما مجبور نیستیم پیش از استفاده از یک دنباله منتظر بمانیم تا تمام مقادیر آن تولید شوند!. -برای ایجاد یک تابع Generator تنها کافی است در یک تابع معمولی از دستور ``yield`` استفاده کنیم.اکنون مفسر پایتون در هنگام فراخوانی این تابع یک شی ``generator`` برمی‌گرداند که توانایی تولید یک **دنباله** (Sequence) از مقادیر (شی) برای استفاده در کاربردهای تکرارپذیر را دارد. +برای ایجاد یک تابع Generator تنها کافی است در یک تابع معمولی از دستور ``yield`` استفاده کنیم. اکنون مفسر پایتون در هنگام فراخوانی این تابع یک شی ``generator`` برمی‌گرداند که توانایی تولید یک **دنباله** (Sequence) از مقادیر (شی) برای استفاده در کاربردهای تکرارپذیر را دارد. دستور ``yield`` روند اجرای برنامه را با حفظ وضعیت، متوقف می‌کند و می‌توانیم با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) روند اجرای تابع را در دست بگیریم:: @@ -209,6 +213,7 @@ Generator >>> def a_generator_function(): ... for i in range(3): ... yield i*i + ... return ... >>> my_generator = a_generator_function() # Create a generator >>> @@ -231,6 +236,7 @@ Generator >>> def a_generator_function(): ... for i in range(3): # i: 0, 1, 2 ... yield i*i + ... return ... >>> >>> my_generator = a_generator_function() # Create a generator @@ -247,7 +253,9 @@ Generator >>> -**ویژگی‌های تابع Generator‌** +ویژگی‌های تابع Generator‌ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * تابع Generator‌ یک تابع معمولی است که رفتاری مشابه با یک شی تکرارکننده (iterator) دارد. @@ -257,6 +265,14 @@ Generator * با استفاده از دستور ``yield`` می‌توانیم در هر نقطه‌ای از تابع Generator‌ که بخواهیم توقف ایجاد کنیم - بدون از دست رفتن وضعیت فعلی تابع - و سپس با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) به ادامه روند اجرا برگردیم. +* با نخستین فراخوانی متد ``()__next__`` تابع اجرا می‌شود، تا زمانی که به یک دستور ``yield`` برسد. در این زمان دستور ``yield`` یک نتیجه تولید می‌کند و اجرای تابع متوقف می‌شود. با فراخوانی مجدد متد ``()__next__`` اجرای تابع از ادامه دستور ``yield`` سر گرفته می‌شود. + +* معمولا نیازی به استفاده مستقیم از متد ``()__next__`` نمی‌شود و توابع Generator‌ از طریق دستورهایی به مانند ``for`` یا توابعی به مانند ``()sum`` و... که توانایی دریافت یک **دنباله** (Sequence) را دارند، مورد استفاده قرار می‌گیرند. + +* در پایان تولید توابع Generator‌ یک استثنا ``StopIteration`` در نقطه توقف خود گزارش می‌دهند که می‌بایست درون برنامه کنترل شود. + +* فراموش نکنیم که استفاده از دستور ``return`` در هر کجا از بدنه تابع باعث پایان یافتن اجرای تابع در آن نقطه می‌شود و توابع Generator‌ نیز از این امر مسثنا نیستند . + به یک نمونه کد دیگر نیز توجه نمایید:: @@ -283,6 +299,8 @@ Generator >>> +در ادامه Yield و Coroutines +------------------------------------ From 18d02b7e1f6576e475e6e73e0b72650319a18a4c Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 7 Oct 2019 00:09:30 +0330 Subject: [PATCH 029/316] work on l13 --- lessons/l13.rst | 51 +++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index ed5c76e..d0f2533 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -201,17 +201,19 @@ Decorator Generator ---------- -ژنراتور (مولد) یا همان **Generator‌** ها [`PEP 255 `__] به توابعی گفته می‌شود که به منظور ایجاد یک تابع با رفتاری مشابه اشیا ``iterator`` (تکرارکننده - درس نهم) پیاده‌سازی می‌شوند. +ژنراتور (مولد) یا همان **Generator‌** ها [`PEP 255 `__] به توابعی گفته می‌شوند که به منظور ایجاد یک تابع با رفتاری مشابه اشیا ``iterator`` (تکرارکننده - درس نهم) پیاده‌سازی می‌گردند. -بر خلاف شی‌ای به مانند لیست، عملکرد Generator‌ به صورت **lazy** (کندرو) [`ویکی‌پدیا `__] می‌باشد و داده‌ها را یکجا ذخیره نمی‌کند بلکه آنها را تنها در همان زمانی که درخواست می‌شوند، **تولید** (Generate) می‌کند. بنابراین در هنگام برخورد با مجموعه داده‌های بزرگ، Generator‌ها مدیریت حافظه کارآمدتری دارند و همچنین ما مجبور نیستیم پیش از استفاده از یک دنباله منتظر بمانیم تا تمام مقادیر آن تولید شوند!. +هنگام فراخوانی یک تابع معمولی، بدنه تابع اجرا می‌شود تا به یک دستور ``return`` برسد و خاتمه یابد ولی با فراخوانی یک تابع Generator‌، بدنه تابع اجرا نمی‌شود بلکه یک شی ``generator`` برگردانده خواهد شد که می‌توان با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) آن، مقادیر مورد انتظار خود را یکی پس از دیگری درخواست داد. -برای ایجاد یک تابع Generator تنها کافی است در یک تابع معمولی از دستور ``yield`` استفاده کنیم. اکنون مفسر پایتون در هنگام فراخوانی این تابع یک شی ``generator`` برمی‌گرداند که توانایی تولید یک **دنباله** (Sequence) از مقادیر (شی) برای استفاده در کاربردهای تکرارپذیر را دارد. +عملکرد Generator‌ به صورت **lazy** (کندرو) [`ویکی‌پدیا `__] می‌باشد و داده‌ها را یکجا ذخیره نمی‌کند بلکه آنها را تنها در همان زمانی که درخواست می‌شوند، **تولید** (Generate) می‌کند. بنابراین در هنگام برخورد با مجموعه داده‌های بزرگ، Generator‌ها مدیریت حافظه کارآمدتری دارند و همچنین ما مجبور نیستیم پیش از استفاده از یک دنباله منتظر بمانیم تا تمام مقادیر آن تولید شوند!. -دستور ``yield`` روند اجرای برنامه را با حفظ وضعیت، متوقف می‌کند و می‌توانیم با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) روند اجرای تابع را در دست بگیریم:: +برای ایجاد یک تابع Generator تنها کافی است در یک تابع معمولی از یک یا چند دستور ``yield`` استفاده کنیم. اکنون مفسر پایتون در هنگام فراخوانی چنین تابعی یک شی ``generator`` برمی‌گرداند که توانایی تولید یک **دنباله** (Sequence) از مقادیر (یا شی) برای استفاده در کاربردهای تکرارپذیر را دارد. + +سینتکس دستور ``yield`` شبیه دستور ``return`` است ولی با کاربردی متفاوت. این دستور در هر نقطه‌ای از بدنه تابع که باشد، اجرای برنامه را در آن نقطه متوقف می‌کند و ما می‌توانیم با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) مقدار **yield (حاصل) شده** را دریافت نماییم:: >>> def a_generator_function(): - ... for i in range(3): + ... for i in range(3): # i: 0, 1, 2 ... yield i*i ... return ... @@ -229,9 +231,7 @@ Generator StopIteration >>> - - -همانطور که در انتهای درس نهم (بخش «شی تکرارکننده») نیز اشاره شده بود، می‌توانیم مقادیر دنباله مورد نظر خود را با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) درخواست نماییم. باید توجه داشت که پایان این دنباله توسط استثنا ``StopIteration`` گزارش می‌شود. در زمان استفاده از دستور ``for`` این استثنا کنترل شده و حلقه پایان می‌پذیرد. نمونه کد قبل را به صورت زیر بازنویسی می‌کنیم:: +باید توجه داشت که پایان فرآیند تولید تابع Generator توسط استثنا ``StopIteration`` گزارش می‌شود. البته در زمان استفاده از دستورهایی به مانند ``for`` این استثنا کنترل شده و حلقه پایان می‌پذیرد. نمونه کد قبل را به صورت زیر بازنویسی می‌کنیم:: >>> def a_generator_function(): ... for i in range(3): # i: 0, 1, 2 @@ -239,12 +239,7 @@ Generator ... return ... >>> - >>> my_generator = a_generator_function() # Create a generator - >>> - >>> type(my_generator) - - >>> - >>> for i in my_generator: + >>> for i in a_generator_function(): ... print(i) ... 0 @@ -252,26 +247,38 @@ Generator 4 >>> +به منظور درک بهتر عملکرد تابع Generator‌، تصور کنید از شما خواسته شده است که یک تابع شخصی مشابه با تابع ``()range`` پایتون پیاده‌سازی نمایید. راهکار شما چه خواهد بود؟ ایجاد یک شی‌ای مانند لیست (list) یا تاپل خالی و پر کردن آن با استفاده از یک حلقه؟! این راهکار شاید برای ایجاد بازه‌های کوچک پاسخگو باشد ولی برای ایجاد یک بازه صد میلیونی آیا حافظه و زمان کافی در اختیار دارید؟. این مسئله را با استفاده از تابع Generator‌ به سادگی و درستی حل خواهیم کرد:: + + >>> def my_range(stop): + ... number = 0 + ... while number < stop: + ... yield number + ... number = number + 1 + ... return + ... + >>> + >>> for number in my_range(100000000): + ... print(number) + + + ویژگی‌های تابع Generator‌ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -* تابع Generator‌ یک تابع معمولی است که رفتاری مشابه با یک شی تکرارکننده (iterator) دارد. * تابع Generator‌ شامل یک یا چند دستور ``yield`` می‌باشد. * در زمان فراخوانی تابع Generator‌، تابع اجرا نمی‌شود ولی در عوض یک شی از نوع ``generator`` برای آن تابع برگردانده می‌شود. -* با استفاده از دستور ``yield`` می‌توانیم در هر نقطه‌ای از تابع Generator‌ که بخواهیم توقف ایجاد کنیم - بدون از دست رفتن وضعیت فعلی تابع - و سپس با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) به ادامه روند اجرا برگردیم. +* با استفاده از دستور ``yield`` می‌توانیم در هر نقطه‌ای از تابع Generator‌ که بخواهیم توقف ایجاد کنیم و مقدار **yield (حاصل) شده** را با استفاده از متد ``()__next__`` (یا ``()next`` در پایتون 2x) دریافت نماییم. -* با نخستین فراخوانی متد ``()__next__`` تابع اجرا می‌شود، تا زمانی که به یک دستور ``yield`` برسد. در این زمان دستور ``yield`` یک نتیجه تولید می‌کند و اجرای تابع متوقف می‌شود. با فراخوانی مجدد متد ``()__next__`` اجرای تابع از ادامه دستور ``yield`` سر گرفته می‌شود. +* با نخستین فراخوانی متد ``()__next__`` تابع اجرا می‌شود، تا زمانی که به یک دستور ``yield`` برسد. در این زمان دستور ``yield`` یک نتیجه تولید می‌کند و اجرای تابع متوقف می‌شود. با فراخوانی مجدد متد ``()__next__`` اجرای تابع از ادامه همان دستور ``yield`` سر گرفته می‌شود. * معمولا نیازی به استفاده مستقیم از متد ``()__next__`` نمی‌شود و توابع Generator‌ از طریق دستورهایی به مانند ``for`` یا توابعی به مانند ``()sum`` و... که توانایی دریافت یک **دنباله** (Sequence) را دارند، مورد استفاده قرار می‌گیرند. * در پایان تولید توابع Generator‌ یک استثنا ``StopIteration`` در نقطه توقف خود گزارش می‌دهند که می‌بایست درون برنامه کنترل شود. -* فراموش نکنیم که استفاده از دستور ``return`` در هر کجا از بدنه تابع باعث پایان یافتن اجرای تابع در آن نقطه می‌شود و توابع Generator‌ نیز از این امر مسثنا نیستند . +* فراموش نکنیم که استفاده از دستور ``return`` در هر کجا از بدنه تابع باعث پایان یافتن اجرای تابع در آن نقطه می‌شود و توابع Generator‌ نیز از این امر مسثنا نیستند!. @@ -299,7 +306,9 @@ Generator >>> -در ادامه Yield و Coroutines + + +در ادامه Coroutine :yield ------------------------------------ From ac86e73d0109f9d5a80784c149f34a32668f486b Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 7 Oct 2019 01:07:38 +0330 Subject: [PATCH 030/316] start Coroutine --- lessons/l13.rst | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lessons/l13.rst b/lessons/l13.rst index d0f2533..f9dab7e 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -311,6 +311,35 @@ Generator در ادامه Coroutine :yield ------------------------------------ +از نسخه پایتون 2.5 ویژگی‌های جدیدی به تابع Generator‌ افزوده شد [`PEP 342 `__]. اگر داخل یک تابع، دستور ``yield`` را در سمت راست یک عملگر انتساب ``=`` قرار دهیم آنگاه تابع مذکور رفتار متفاوتی از خود نشان می‌دهد که باعث می‌شود به آن **Coroutine** گفته شود. تصور کنید که اکنون می‌توانیم مقادیر دلخواه خود را به تابع Generator‌ ارسال کنیم!:: + + >>> def receiver(): + ... print("Ready to receive") + ... while True: + ... n = (yield) + ... print("Got %s" % n) + ... + >>> + + + >>> receiver_generator = receiver() + + >>> receiver_generator.__next__() + Ready to receive + + >>> receiver_generator.send('WooW!!') + Got WooW!! + + >>> receiver_generator.send(1) + Got 1 + + >>> receiver_generator.send(':)') + Got :) + +چگونگی اجرای یک **Coroutine** همانند یک Generator‌ است. + + + From e636707f96ea057c790498a7144c7739b39bf574 Mon Sep 17 00:00:00 2001 From: Saeid Date: Mon, 7 Oct 2019 10:03:59 +0330 Subject: [PATCH 031/316] following Corotine --- lessons/l13.rst | 64 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index f9dab7e..1a03e32 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -311,7 +311,7 @@ Generator در ادامه Coroutine :yield ------------------------------------ -از نسخه پایتون 2.5 ویژگی‌های جدیدی به تابع Generator‌ افزوده شد [`PEP 342 `__]. اگر داخل یک تابع، دستور ``yield`` را در سمت راست یک عملگر انتساب ``=`` قرار دهیم آنگاه تابع مذکور رفتار متفاوتی از خود نشان می‌دهد که باعث می‌شود به آن **Coroutine** گفته شود. تصور کنید که اکنون می‌توانیم مقادیر دلخواه خود را به تابع Generator‌ ارسال کنیم!:: +از نسخه پایتون 2.5 ویژگی‌های جدیدی به تابع Generator‌ افزوده شد [`PEP 342 `__]. اگر داخل یک تابع، دستور ``yield`` را در سمت راست یک عملگر انتساب ``=`` قرار دهیم آنگاه تابع مذکور رفتار متفاوتی از خود نشان می‌دهد که به آن در زبان برنامه‌نویسی پایتون **Coroutine** گفته شود. تصور کنید که اکنون می‌توانیم مقادیر دلخواه خود را به تابع Generator‌ ارسال کنیم!:: >>> def receiver(): ... print("Ready to receive") @@ -324,7 +324,7 @@ Generator >>> receiver_generator = receiver() - >>> receiver_generator.__next__() + >>> receiver_generator.__next__() # python 3.x - In Python 2.x use .next() Ready to receive >>> receiver_generator.send('WooW!!') @@ -336,7 +336,65 @@ Generator >>> receiver_generator.send(':)') Got :) -چگونگی اجرای یک **Coroutine** همانند یک Generator‌ است. +چگونگی اجرای یک **Coroutine** همانند یک Generator‌ است ولی با این تفاوت که متد ``()send`` نیز برای ارسال مقدار به درون تابع در اختیار است. + + +با فراخوانی تابع Coroutine، بدنه اجرا نمی‌شود بلکه یک شی از نوع Generator‌ برگردانده می‌شود. متد ``()__next__`` (یا ``()next`` در پایتون 2x) اجرای برنامه را به نخستین ``yield`` می‌رساند، در این نقطه تابع در وضعیت تعلیق (Suspend) قرار می‌گیرد و آماده دریافت مقدار است. متد ``()send`` مقدار مورد نظر را به تابع ارسال می‌کند که این مقدار توسط عبارت ``(yield)`` در Coroutine دریافت می‌شود. پس از دریافت مقدار، اجرای Coroutine تا رسیدن به ``yield`` بعدی (در صورت وجود) یا انتهای بدنه تابع ادامه می‌یابد. + +در بحث Coroutineها برای رهایی از فراخوانی متد ``()__next__`` می‌توان از Decorator‌ها استفاده کرد:: + + + >>> def coroutine(func): + ... def start(*args,**kwargs): + ... generator = func(*args,**kwargs) + ... generator.__next__() + ... return generator + ... return start + ... + >>> + >>> @coroutine + ... def receiver(): + ... print("Ready to receive") + ... while True: + ... n = (yield) + ... print("Got %s" % n) + ... + >>> + >>> receiver_generator = receiver() + >>> receiver_generator.send('Hello World') # Note : No initial .next()/.__next__() needed + + +یک Coroutine می‌تواند به دفعات نامحدود اجرا شود مگر اینکه اجرای آن توسط برنامه با فراخوانی متد ``()close`` یا به خودی خود با پایان خطوط اجرای تابع، پایان بپذیرد. + +چنانچه پس از پایان Coroutine، متد ``()send`` فراخوانی شود یک استثنا ``StopIteration`` رخ خواهد داد:: + + >>> receiver_generator.close() + >>> receiver_generator.send('value') + Traceback (most recent call last): + File "", line 1, in + StopIteration + + +یک Coroutine می‌تواند همزمان با دریافت مقدار، خروجی نیز تولید و برگرداند:: + + >>> def line_splitter(delimiter=None): + ... print("Ready to split") + ... result = None + ... while True: + ... line = (yield result) + ... result = line.split(delimiter) + ... + >>> + >>> splitter = line_splitter(",") + >>> splitter.__next__() + Ready to split + >>> splitter.send("A,B,C") + ['A', 'B', 'C'] + >>> splitter.send("100,200,300") + ['100', '200', '300'] + >>> + +**چه اتفاقی افتاد؟** From b64b3ce408ca94fde8158d4aa85a92a0e47a4e91 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Tue, 8 Oct 2019 23:28:20 +0330 Subject: [PATCH 032/316] complete Coroutines --- lessons/l13.rst | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index 1a03e32..f1c8ce5 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -311,7 +311,7 @@ Generator در ادامه Coroutine :yield ------------------------------------ -از نسخه پایتون 2.5 ویژگی‌های جدیدی به تابع Generator‌ افزوده شد [`PEP 342 `__]. اگر داخل یک تابع، دستور ``yield`` را در سمت راست یک عملگر انتساب ``=`` قرار دهیم آنگاه تابع مذکور رفتار متفاوتی از خود نشان می‌دهد که به آن در زبان برنامه‌نویسی پایتون **Coroutine** گفته شود. تصور کنید که اکنون می‌توانیم مقادیر دلخواه خود را به تابع Generator‌ ارسال کنیم!:: +از نسخه پایتون 2.5 ویژگی‌های جدیدی به تابع Generator‌ افزوده شد [`PEP 342 `__]. اگر داخل یک تابع، دستور ``yield`` را در سمت راست یک عملگر انتساب ``=`` قرار دهیم آنگاه تابع مذکور رفتار متفاوتی از خود نشان می‌دهد که به آن در زبان برنامه‌نویسی پایتون **Coroutine** (کوروتین) گفته می‌شود. تصور کنید که اکنون می‌توانیم مقادیر دلخواه خود را به تابع Generator‌ ارسال کنیم!:: >>> def receiver(): ... print("Ready to receive") @@ -381,20 +381,35 @@ Generator ... print("Ready to split") ... result = None ... while True: - ... line = (yield result) + ... line = yield result ... result = line.split(delimiter) ... >>> >>> splitter = line_splitter(",") - >>> splitter.__next__() + >>> + >>> splitter.__next__() # python 3.x - In Python 2.x use .next() Ready to split + >>> >>> splitter.send("A,B,C") ['A', 'B', 'C'] + >>> >>> splitter.send("100,200,300") ['100', '200', '300'] >>> -**چه اتفاقی افتاد؟** +**چه اتفاقی افتاد؟!** + +تابع ``line_splitter`` با مقدار ورودی ``","`` فراخوانی می‌شود. همانطور که می‌دانیم در این لحظه تنها اتفاقی که می‌افتد ایجاد یک نمونه شی از نوع Generator‌ خواهد بود (و هیچ یک از خطوط داخل بدنه تابع اجرا نخواهد شد). با فراخوانی متد ``()__splitter.__next`` بدنه تابع به اجرا درمیاید تا به نخستین ``yield`` برسد. یعنی عبارت ``"Ready to split"`` در خروجی چاپ، متغیر ``result`` با مقدار اولیه ``None`` تعریف و در نهایت با تایید شرط دستور ``while`` اجرا به سطر ``line = yield result`` می‌رسد. در این سطر بر اساس ارزیابی عبارت سمت راست عمل انتساب، مقدار متغیر ``result`` که برابر ``None`` است به خارج از تابع برگردانده و سپس تابع در وضعیت تعلیق (Suspend) قرار می‌گیرد. ولی باید توجه داشت که هنوز عمل انتساب در این سطر به صورت کامل به انجام نرسیده است!. در ادامه با فراخوانی متد ``("splitter.send("A,B,C``، رشته ``"A,B,C"`` در ``yield`` قرار داده می‌شود و اجرای برنامه از حالت تعلیق خارج و ادامه می‌یابد. مقدار ``yield`` به ``line`` انتساب داده می‌شود و اجرای سطر ``line = yield result`` کامل می‌شود. در سطر بعد، رشته درون متغیر ``line`` بر اساس ``delimiter`` که در ابتدا با ``","`` مقداردهی شده بود تفکیک و به متغیر ``result`` انتساب داده می‌شود (مقدار متغیر ``result`` که تا پیش از این برابر ``None`` بوده است تغییر می‌کند). با پایان خطوط بدنه و تایید دوباره درستی شرط دستور ``while``، بدنه آن یکبار دیگر اجرا می‌شود تا از نو به ``yield`` برسد یعنی به سطر ``line = yield result``. اکنون در بار دوم اجرای حلقه بر خلاف بار نخست مقدار متغیر ``result`` برابر با ``None`` نبوده و عمل yield آن یا همان بازگرداندن آن در خروجی قابل مشاهده خواهد بود یعنی مقدار ``['A', 'B', 'C']`` که در بار نخست اجرای حلقه تولید شده بود، اکنون در خروجی به نمایش در خواهد آمد و سپس تابع بار دیگر در حالت تعلیق قرار می‌گیرد (تابع منتظر فراخوانی یکی از متدهای ``()send`` یا ``()__next__`` یا ``()close`` می‌ماند). روال کار با فراخوانی متد ``("splitter.send("100,200,300`` به همین صورت ادامه می‌یابد... + +در مورد سطر ``line = yield result``، می‌دانیم که برای انجام عمل انتساب ابتدا لازم است مقدار عبارت سمت راست ارزیابی و سپس به سمت چپ انتساب داده شود. یعنی مفسر پایتون ابتدا ``yield result`` را اجرا می‌کند که حاصل آن بازگرداندن مقدار متغیر ``result`` (در بار نخست اجرای حلقه = ``None``) به خارج تابع خواهد بود و سپس عبارت ``line = yield`` که مقدار ارسالی از متد ``()send`` را به متغیر ``line`` انتساب می‌دهد. + +| + +مبحث Coroutine گسترده‌تر از سطحی است که در این درس می‌تواند بیان شود ولی در این لحظه برای دریافت مثال‌ها، کاربرد و جزییات بیشتر در موضوع Coroutine زبان برنامه‌نویسی پایتون، ارائه آقای David Beazley در کنفرانس PyCon'2009 می‌تواند مفید باشد. + +PDF: [`A Curious Course on Coroutines and Concurrency `__] + +VIDEO: [`YouTube `__] From e952c7235ec28bd427442f0af6ac1195ee2d048f Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 14 Oct 2019 22:39:53 +0330 Subject: [PATCH 033/316] explain List Comprehensions --- lessons/l13.rst | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/lessons/l13.rst b/lessons/l13.rst index f1c8ce5..69632ee 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -412,6 +412,101 @@ PDF: [`A Curious Course on Coroutines and Concurrency `__] +List Comprehensions +-------------------- + +**List Comprehensions** به عملیاتی گفته می‌شود که در طی آن می‌توان یک تابع را به تک تک اعضای یک نوع شی لیست (list) اعمال و نتیجه را در قالب یک نوع شی لیست جدید دریافت کرد [`PEP 202 `__]:: + + >>> numbers = [1, 2, 3, 4, 5] + >>> squares = [n * n for n in numbers] + >>> + >>> squares + [1, 4, 9, 16, 25] + >>> + +نمونه کد بالا برابر است با:: + + >>> numbers = [1, 2, 3, 4, 5] + >>> squares = [] + >>> for n in numbers: + ... squares.append(n * n) + ... + >>> + >>> squares + [1, 4, 9, 16, 25] + + +سینتکس کلی List Comprehensions به صورت زیر است:: + + [expression for item1 in iterable1 if condition1 + for item2 in iterable2 if condition2 + ... + for itemN in iterableN if conditionN] + + # This syntax is roughly equivalent to the following code: + + s = [] + for item1 in iterable1: + if condition1: + for item2 in iterable2: + if condition2: + ... + for itemN in iterableN: + if conditionN: s.append(expression) + + +به مثال‌هایی دیگر در این زمینه توجه نمایید:: + + >>> a = [-3,5,2,-10,7,8] + >>> b = 'abc' + + >>> [2*s for s in a] + [-6, 10, 4, -20, 14, 16] + + >>> [s for s in a if s >= 0] + [5, 2, 7, 8] + + >>> [(x,y) for x in a for y in b if x > 0] + [(5, 'a'), (5, 'b'), (5, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (7, 'a'), (7, 'b'), (7, 'c'), (8, 'a'), (8, 'b'), (8, 'c')] + + >>> import math + >>> c = [(1,2), (3,4), (5,6)] + >>> [math.sqrt(x*x+y*y) for x,y in c] + [2.23606797749979, 5.0, 7.810249675906654] + + +توجه داشته باشید، چنانچه نتیجه اعمال List Comprehensions در هر نوبت شامل بیش از یک عضو باشد، می‌بایست مقادیر نتایج در داخل یک پرانتز قرار داده شوند (به صورت یک شی تاپل - tuple). + +به نمونه ``[x,y) for x in a for y in b if x > 0)]`` و خروجی آن توجه نمایید. با توجه به این موضوع عبارت زیر از نظر مفسر پایتون نادرست می‌باشد:: + + >>> [x,y for x in a for y in b] + File "", line 1 + [x,y for x in a for y in b] + ^ + SyntaxError: invalid syntax + >>> + +یک نکته مهم دیگر باقی‌مانده است. به نمونه کد پایین در دو نسخه پایتون 3x و 2x توجه نمایید:: + + # Python 3.x + + >>> x = 'before' + >>> a = [x for x in (1, 2, 3)] + >>> + >>> x + 'before' + +:: + + # Python 2.x + + >>> x = 'before' + >>> a = [x for x in (1, 2, 3)] + >>> + >>> x + 3 + +هر دو کد یکسان هستند ولی در نسخه 2x به دلیل اینکه متغیرهای تکرار تعریف شده - در اینجا ``x`` - در یک حوزه (scope) جداگانه در نظر گرفته نمی‌شوند، با تغییر مقدار آنها در داخل عبارت، مقدار همنام موجود در حوزه بیرونی عبارت نیز تغییر داده می‌شود. این به بیان آقای روسوم "dirty little secret" در نسخه 3x برطرف گردیده است. [`توضیحات بیشتر `__] From ce046d9e215fd50efd74ec86ac8151bc105e6a29 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Tue, 15 Oct 2019 21:54:11 +0330 Subject: [PATCH 034/316] explain Generator Expressions --- lessons/l13.rst | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/lessons/l13.rst b/lessons/l13.rst index 69632ee..efe21e1 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -508,6 +508,86 @@ List Comprehensions هر دو کد یکسان هستند ولی در نسخه 2x به دلیل اینکه متغیرهای تکرار تعریف شده - در اینجا ``x`` - در یک حوزه (scope) جداگانه در نظر گرفته نمی‌شوند، با تغییر مقدار آنها در داخل عبارت، مقدار همنام موجود در حوزه بیرونی عبارت نیز تغییر داده می‌شود. این به بیان آقای روسوم "dirty little secret" در نسخه 3x برطرف گردیده است. [`توضیحات بیشتر `__] +Generator Expressions +---------------------- + +عملکرد **Generator Expressions** مشابه **List Comprehensions** است ولی با خاصیت یک شی Generator و برای ایجاد آن کافی است به جای براکت ``[]`` در List Comprehensions از پرانتز ``()`` استفاده کنیم. [`PEP 289 `__]:: + + >>> a = [1, 2, 3, 4] + >>> b = (10*i for i in a) + >>> + >>> + >>> b + at 0x7f488703aca8> + >>> + >>> b.__next__() # python 3.x - In Python 2.x use .next() + 10 + >>> b.__next__() # python 3.x - In Python 2.x use .next() + 20 + >>> + +درک تفاوت Generator Expressions و List Comprehensions بسیار مهم است. خروجی یک **List Comprehensions** دقیقا همان نتیجه انجام عملیات در قالب یک شی لیست است در حالی که خروجی یک **Generator Expressions** شی است که می‌داند چگونه نتایج را مرحله به مرحله تولید کند. درک این دست موضوعات نقش مهمی در بالا بردن کارایی (Performance) برنامه و مصرف حافظه (Memory) خواهد داشت. + +با اجرای نمونه کد پایین؛ از میان تمام سطرهای داخل فایل The_Zen_of_Python.txt، سطرهایی که به صورت کامنت در زبان پایتون باشند چاپ می‌شوند: + +.. code-block:: text + :linenos: + + Beautiful is better than ugly. + Explicit is better than implicit. + Simple is better than complex. + Complex is better than complicated. + Flat is better than nested. + Sparse is better than dense. + Readability counts. + Special cases aren't special enough to break the rules. + Although practicality beats purity. + Errors should never pass silently. + Unless explicitly silenced. + In the face of ambiguity, refuse the temptation to guess. + There should be one-- and preferably only one --obvious way to do it. + Although that way may not be obvious at first unless you're Dutch. + Now is better than never. + Although never is often better than *right* now. + If the implementation is hard to explain, it's a bad idea. + If the implementation is easy to explain, it may be a good idea. + Namespaces are one honking great idea -- let's do more of those! + ------------------------------------------------------------------ + # File Name: The_Zen_of_Python.txt + # The Zen of Python + # PEP 20: https://www.python.org/dev/peps/pep-0020 + +:: + + >>> file = open("/home/saeid/Documents/The_Zen_of_Python.txt") + >>> lines = (t.strip() for t in file) + >>> comments = (t for t in lines if t[0] == '#') + >>> for c in comments: + ... print(c) + ... + # File Name: The_Zen_of_Python.txt + # The Zen of Python + # PEP 20: https://www.python.org/dev/peps/pep-0020 + >>> + +در سطر یکم، فایل The_Zen_of_Python.txt باز شده و در سطر دوم یک شی Generator برای دستیابی و strip کردن (حذف کاراکترهای خالی (space) احتمالی در ابتدا و انتهای متن سطر) آن‌ها به شیوه **Generator Expressions** به دست آمده است. توجه داشته باشید که سطرهای فایل هنوز خوانده نشده‌اند و تنها امکان درخواست و پیمایش سطر به سطر فایل ایجاد شده است. در سطر سوم با ایجاد یک شی Generator دیگر (باز هم به شیوه **Generator Expressions**) امکان فیلتر سطرهای کامنت مانند در داخل فایل را به کمک شی ``lines`` مرحله قبل، به دست آورده‌ایم. ولی هنوز سطرهای فایل خوانده نشده‌اند چرا که هنوز درخواستی مبنی بر تولید به هیچ یک از دو شی Generator ایجاد شده (``lines`` و ``comments``) ارسال نشده است. تا اینکه بالاخره در سطر چهارم دستور حلقه ``for`` شی ``comments`` را به جریان می‌اندازد و این شی نیز بر اساس عملیات تعریف شده برای آن، شی ``lines`` را به جریان در می‌آورد. + +فایل The_Zen_of_Python.txt مورد استفاده در این مثال حجم بسیار کمی دارد ولی تاثیر به کار گرفتن **Generator Expressions** در این مثال را می‌توانید با استخراج کامنت‌های یک فایل چند گیگابایتی مشاهده نمایید! + +.. tip:: + شی Generator ایجاد شده به شیوه **Generator Expressions** را نیز می‌توان با استفاده از تابع ``()list`` به شی لیست تبدیل کرد:: + + >>> comment_list = list(comments) + >>> comment_list + ['# File Name: The_Zen_of_Python.txt', + '# The Zen of Python', + '# PEP 20: https://www.python.org/dev/peps/pep-0020'] + + + + + + From 0811a4e7fd2a8469cff21a727080e92fdfe4bde0 Mon Sep 17 00:00:00 2001 From: Saeid Date: Fri, 18 Oct 2019 19:58:03 +0330 Subject: [PATCH 035/316] explain lambda --- lessons/l13.rst | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/lessons/l13.rst b/lessons/l13.rst index efe21e1..3e8d39b 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -585,6 +585,58 @@ Generator Expressions +lambda و توابع ناشناس +--------------------------- + +در زبان برنامه‌نویسی پایتون توابع ناشناس (Anonymous functions) یا **Lambda functions** توابعی هستند که می‌توانند هر تعداد آرگومان داشته باشند ولی بدنه آن‌ها می‌بایست تنها شامل یک عبارت باشد. برای ساخت این دست توابع از کلمه کلیدی ``lambda`` استفاده می‌شود. الگوی ساختاری این نوع تابع به صورت زیر است:: + + lambda args : expression + +در این الگو ``args`` معرف هر تعداد آرگومان است که با استفاده از کاما (``,``) از یکدیگر جدا شده‌اند و ``expression`` بیانگر تنها یک عبارت پایتونی است که شامل دستوراتی همچون ``for`` یا ``while`` نمی‌شود. + + +به عنوان نمونه تابع پایین را در نظر بگیرید:: + + >>> def a_function(x, y): + ... return x + y + ... + >>> + >>> a_function(2, 3) + 5 + +این تابع در فرم ناشناس به صورت زیر خواهد بود:: + + >>> a_function = lambda x,y : x+y + >>> a_function(2, 3) + 5 + +یا:: + + >>> (lambda x,y: x+y)(2, 3) + 5 + + +**کاربرد اصلی Lambda functions کجاست؟** + +این دست توابع بیشتر در مواقعی که می‌خواهیم یک تابع کوتاه را به عنوان آرگومان به تابعی دیگر ارسال کنیم کاربرد دارند. + +برای نمونه از درس هشتم به یاد داریم که برای مرتب‌سازی اعضای یک شی لیست از متد ``()sort`` استفاده و بیان شد که متد ``()sort`` آرگومان اختیاری با نام ``key`` دارد که می‌توان با ارسال یک تابع تک آرگومانی به آن عمل دلخواهی را بر روی تک تک عضوهای لیست مورد نظر، پیش از مقایسه و مرتب‌سازی به انجام رساند (به عنوان مثال: تبدیل حروف بزرگ به کوچک):: + + >>> L = ['a', 'D', 'c', 'B', 'e', 'f', 'G', 'h'] + + >>> L.sort() + + >>> L + ['B', 'D', 'G', 'a', 'c', 'e', 'f', 'h'] + + >>> L.sort(key=lambda n: n.lower()) + + >>> L + ['a', 'B', 'c', 'D', 'e', 'f', 'G', 'h'] + >>> + + + From fe771fa57551df08417fe21b58a92847de4b58a7 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 19 Oct 2019 18:16:53 +0330 Subject: [PATCH 036/316] review Decorator --- lessons/l13.rst | 122 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 2 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index 3e8d39b..f59e98a 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -8,7 +8,7 @@ درس ۱۳: تابع - بخش دوم ======================== - +این درس در ادامه درس پیش است که به معرفی مواردی از کاربردهای تابع در ایجاد مفاهیمی جدید، مهم و کاربردی در زبان برنامه‌نویسی پایتون می‌پردازد. مبحث تابع در پایتون با این درس به پایان نمی‌رسد و نکات باقی‌مانده در درس بعدی ارائه می‌شوند. @@ -32,7 +32,7 @@ Decorator ---------- -دکوراتور (تزئین‌گر) یا همان **Decorator‌** ها [`PEP 318 `__] به توابعی گفته می‌شود که به منظور پوشش (wrap) توابع یا کلاس‌های دیگر پیاده‌سازی می‌شوند. Decorator‌ها در پایتون ابزار بسیار کاربردی و مفیدی هستند که به برنامه‌نویس این امکان را می‌دهند تا با کاهش حجم کدنویسی و بدون تغییر در بدنه توابع و کلاس‌های خود، رفتار و ویژگی‌های آن‌ها را گسترش دهد. در این بخش تمرکز بر روی اعمال Decorator‌ها به توابع است و Decorator‌ کلاس را در درس مربوط به کلاس‌ها بررسی خواهیم کرد. +دکوراتور (تزئین‌گر) یا همان **Decorator‌** ها [`PEP 318 `__] به توابعی گفته می‌شود که به منظور پوشش (wrap) توابع یا کلاس‌های دیگر پیاده‌سازی می‌شوند. Decorator‌ها در پایتون ابزار بسیار کاربردی و مفیدی هستند که به برنامه‌نویس این امکان را می‌دهند تا با کاهش حجم کدنویسی و بدون تغییر در بدنه توابع و کلاس‌های خود، رفتار و ویژگی‌های آن‌ها را گسترش دهد. در این بخش تمرکز بر روی **اعمال** Decorator‌ها به **توابع** است و Decorator‌ کلاس را در درس مربوط به کلاس‌ها بررسی خواهیم کرد. برای پوشش یک تابع توسط Decorator‌ از سینتکسی مشابه ``decorator‌_name@`` در بالای بخش سرآیند استفاده می‌شود: @@ -198,6 +198,124 @@ Decorator >>> +**functools.wraps@** +====================== + +در پایتون عنوانی مطرح است به نام **Higher-order functions** (توابع مرتبه بالاتر) و به توابعی گفته می‌شود که اعمالی را روی توابع دیگر انجام می‌دهند یا یک تابع جدید را به عنوان خروجی برمی‌گرداند. بر همین اساس یک ماژول به نام ``functools`` نیز در کتابخانه استاندارد پایتون قرار گرفته است که یک سری توابع کمکی و کاربردی ارائه می‌دهد [`مستندات پایتون `__]. یکی از این توابع ``wraps`` [`مستندات پایتون `__] می‌باشد. + +اما چرا معرفی این تابع در این بخش مهم است؟. وقتی ما از یک Decorator‌ استفاده می‌کنیم، اتفاقی که می‌افتد این است که یک تابع جدید جایگزین تابع اصلی ما می‌شود. به نمونه کدهای پایین توجه نمایید:: + + >>> def func(x): + ... """does some math""" + ... return x + x * x + ... + >>> + >>> print(func.__name__) + func + >>> print(func.__doc__) + does some math + >>> + +:: + + >>> def logged(func): + ... def with_logging(*args, **kwargs): + ... print(func.__name__ + " was called") + ... return func(*args, **kwargs) + ... return with_logging + ... + >>> + >>> @logged + ... def f(x): + ... """does some math""" + ... return x + x * x + ... + >>> + >>> print(f.__name__) + with_logging + >>> print(f.__doc__) + None + >>> + +:: + + >>> # It is mean: f = logged(func) + ... + >>> f = logged(func) + >>> print(f.__name__) + with_logging + +در زمان استفاده Decorator‌ وقتی خواستیم نام تابع را چاپ کنیم ``(__print(f.__name`` نام تابع جدید (``with_logging``) چاپ شد و نه تابع اصلی (``f``). + +استفاده از Decorator‌ همیشه به معنی از دست رفتن اطلاعات مربوط به تابع اصلی است که به منظور جلوگیری از این اتفاق و حفظ اطلاعات مربوط به تابع اصلی خود می‌توانیم از تابع ``wraps`` استفاده کنیم. این تابع در واقع خود یک Decorator‌ است که وظیفه آن کپی اطلاعات از تابعی که به عنوان آرگومان دریافت می‌کند به تابعی که به آن انتساب داده شده است:: + + >>> from functools import wraps + >>> + >>> def logged(func): + ... @wraps(func) + ... def with_logging(*args, **kwargs): + ... print(func.__name__ + " was called") + ... return func(*args, **kwargs) + ... return with_logging + ... + >>> + >>> @logged + ... def f(x): + ... """does some math""" + ... return x + x * x + ... + >>> + >>> print(f.__name__) + f + >>> print(f.__doc__) + does some math + >>> + + + + + + + + + + +لطفا به آخرین مثال از بحث Decorator‌ نیز توجه فرمایید. در این مثال زمان اجرای یک تابع را با استفاده از Decorator‌ها محاسبه خواهیم کرد [`منبع `__]:: + + >>> import functools + >>> import time + >>> + >>> def timer(func): + ... """Print the runtime of the decorated function""" + ... @functools.wraps(func) + ... def wrapper_timer(*args, **kwargs): + ... start_time = time.perf_counter() + ... value = func(*args, **kwargs) + ... end_time = time.perf_counter() + ... run_time = end_time - start_time + ... print(f"Finished {func.__name__!r} in {run_time:.4f} secs") + ... return value + ... return wrapper_timer + ... + >>> + >>> @timer + ... def waste_some_time(num_times): + ... result = 0 + ... for _ in range(num_times): + ... for i in range(10000) + ... result += i**2 + ... + >>> + >>> waste_some_time(1) + Finished 'waste_some_time' in 0.0072 secs + >>> waste_some_time(999) + Finished 'waste_some_time' in 2.6838 secs + +در این مثال از تابع ``perf_counter`` برای محاسبه فواصل زمانی (time intervals) [`مستندات پایتون `__] استفاده شده که تنها از نسخه 3.3 به بعد در دسترس می‌باشد [`اطلاعات تکمیلی `__]. + +چنانچه درک دستور ``("print(f"Finished {func.__name__!r} in {run_time:.4f} secs`` برایتان مبهم است به درس هفتم بخش مربوط به رشته‌ها مراجعه نمایید. + + Generator ---------- From 1754c2a080829b4ab607ec527f975e65a8a253f8 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 19 Oct 2019 18:51:30 +0330 Subject: [PATCH 037/316] =?UTF-8?q?review=20Generator=E2=80=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lessons/l13.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lessons/l13.rst b/lessons/l13.rst index f59e98a..b770895 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -398,6 +398,8 @@ Generator * فراموش نکنیم که استفاده از دستور ``return`` در هر کجا از بدنه تابع باعث پایان یافتن اجرای تابع در آن نقطه می‌شود و توابع Generator‌ نیز از این امر مسثنا نیستند!. +* با فراخوانی متد ``close`` می‌توانید یک شی Generator‌ را خاموش کنید!. توجه داشته باشید که پس از فراخوانی این متد چنانچه باز هم درخواست ایجاد مقدار ارسال (``()__next__``) شود یک استثنا ``StopIteration`` گزارش می‌گردد. + به یک نمونه کد دیگر نیز توجه نمایید:: @@ -422,6 +424,26 @@ Generator >>> countdown_generator.__next__() 7 >>> + >>> countdown_generator.close() + >>> + >>> countdown_generator.__next__() + Traceback (most recent call last): + File "", line 1, in + StopIteration + >>> + + +.. tip:: + شی Generator را می‌توان با استفاده از تابع ``()list`` به شی لیست تبدیل کرد:: + + >>> countdown_list = list(countdown(10)) + Counting down from 10 + >>> + >>> countdown_list + [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] + >>> + + From 70dfe987987bac894f27e2b6ea19ae77e7f4724e Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 19 Oct 2019 19:10:30 +0330 Subject: [PATCH 038/316] fix some sentence --- lessons/l13.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index b770895..e4650c6 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -199,11 +199,11 @@ Decorator **functools.wraps@** -====================== +~~~~~~~~~~~~~~~~~~~~~ -در پایتون عنوانی مطرح است به نام **Higher-order functions** (توابع مرتبه بالاتر) و به توابعی گفته می‌شود که اعمالی را روی توابع دیگر انجام می‌دهند یا یک تابع جدید را به عنوان خروجی برمی‌گرداند. بر همین اساس یک ماژول به نام ``functools`` نیز در کتابخانه استاندارد پایتون قرار گرفته است که یک سری توابع کمکی و کاربردی ارائه می‌دهد [`مستندات پایتون `__]. یکی از این توابع ``wraps`` [`مستندات پایتون `__] می‌باشد. +در پایتون عنوانی مطرح است به نام **Higher-order functions** (توابع مرتبه بالاتر) و به توابعی گفته می‌شود که اعمالی را روی توابع دیگر انجام می‌دهند یا یک تابع جدید را به عنوان خروجی برمی‌گرداند. بر همین اساس یک ماژول به نام ``functools`` نیز در کتابخانه استاندارد پایتون قرار گرفته است که یک سری توابع کمکی و کاربردی برای این دست توابع ارائه می‌دهد [`مستندات پایتون `__]. یکی از توابع داخل این ماژول ``wraps`` [`مستندات پایتون `__] می‌باشد. -اما چرا معرفی این تابع در این بخش مهم است؟. وقتی ما از یک Decorator‌ استفاده می‌کنیم، اتفاقی که می‌افتد این است که یک تابع جدید جایگزین تابع اصلی ما می‌شود. به نمونه کدهای پایین توجه نمایید:: +**اما چرا معرفی این تابع در این بخش مهم است؟** وقتی ما از یک Decorator‌ استفاده می‌کنیم، اتفاقی که می‌افتد این است که یک تابع جدید جایگزین تابع اصلی ما می‌شود. به نمونه کدهای پایین توجه نمایید:: >>> def func(x): ... """does some math""" From 474b628aa4030056b60baef72771a0d343938782 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 19 Oct 2019 19:44:45 +0330 Subject: [PATCH 039/316] a little explanation of the return statement --- lessons/l12.rst | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/lessons/l12.rst b/lessons/l12.rst index 68e709c..c9247ab 100644 --- a/lessons/l12.rst +++ b/lessons/l12.rst @@ -2,7 +2,7 @@ .. meta:: :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس دوازدهم تابع - :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, پایتون + :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون,تابع, پایتون درس ۱۲: تابع - بخش یکم @@ -38,7 +38,7 @@ رویکرد این آموزش به تابع بر اساس برنامه‌نویسی اعلانی است. زبان پایتون قابلیت برنامه‌نویسی تابعی را نیز در کنار رویکردهای دیگر همچون اعلانی یا شی‌گرایی ارایه می‌دهد. برای چگونگی برنامه‌نویسی تابعی با استفاده از زبان پایتون می‌توانید به کتاب Functional Programming in Python از انتشارات O'Reilly مراجعه نمایید (`دریافت نسخه pdf - رایگان `__). -در کنار اصطلاح تابع در برنامه‌نویسی، اصطلاح مشابه دیگری نیز به عنوان «رِوال» (Procedure) وجود دارد. روال و تابع در ساختار شبیه یکدیگر هستند با این تفاوت که روال‌ها مقداری برنمی‌گردانند. در پایتون سینتکسی برای تعریف روال وجود ندارد ولی به توابعی که مقداری برنمی‌گردانند، روال نیز گفته می‌شوند. +در کنار اصطلاح تابع در برنامه‌نویسی، اصطلاح مشابه دیگری نیز به عنوان «رِوال» (Procedure) وجود دارد. روال و تابع در ساختار شبیه یکدیگر هستند با این تفاوت که روال‌ها مقداری برنمی‌گردانند. در پایتون سینتکسی برای تعریف روال وجود ندارد ولی به توابعی که مقداری برنمی‌گردانند، روال نیز گفته می‌شوند که اشتباه است چرا که توابع در پایتون تحت هر شرایطی یک مقدار برمی‌گردانند حتی اگر این مقدار ``None`` باشد. سینتکس -------- @@ -89,6 +89,28 @@ 8 >>> +.. tip:: + + چنانچه در انتهای تابع دستور ``return`` نوشته نشود، مفسر پایتون به صورت ضمنی دستور ``return None`` را در نظر می‌گیرد. بنابراین با فراخوانی این چنین توابع در زبان پایتون، پس از اجرای کامل دستورات داخل بدنه مقدار ``None`` بازگردانده خواهد شد (`albeit a rather boring one `__). + +.. tip:: + پیشنهاد `PEP 8 `__: در بازگردان مقدار در تابع یکنواخت عمل کنید. اگر از دستورات مرکبی به مانند ``if/else`` استفاده می‌کنید یا باید هیچ یک از بخش‌ها به صراحت ``return`` نداشته باشند یا اگر لازم است حداقل یک بخش مقداری را برگرداند، باقی بخش‌ها نیز می‌بایست یک مقداری را برگردانند حتی اگر قرار باشد این مقدار ``None`` در نظر گرفته شود:: + + YES: + + def foo(x): + if x >= 0: + return math.sqrt(x) + else: + return None + + + NO: + + def foo(x): + if x >= 0: + return math.sqrt(x) + در زبان برنامه نویسی پایتون تابع یک موجودیت **”first-class“** است که یعنی تابع را می‌توان مانند دیگر اشیا به صورت پویا ایجاد یا نابود کرد، به صورت آرگومان به توابع دیگر ارسال نمود، به عنوان نتیجه توسط ``return`` بازگرداند و... در نتیجه می‌توان یک تابع را درون بدنه دستورات کنترلی (``while`` ،``if`` و...) یا درون بدنه تابعی دیگر تعریف نمود:: >>> def outer(num1): From 02a19f151a5e56b15a2663884140742eef314b20 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 19 Oct 2019 20:52:34 +0330 Subject: [PATCH 040/316] change format & add new --- donate.rst | 104 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/donate.rst b/donate.rst index 5db0d5c..7b6f1a6 100644 --- a/donate.rst +++ b/donate.rst @@ -9,7 +9,9 @@ گزارش هدایای پرداخت شده ========================= -مبالغ مهم نیستند، از اقدام شما دوستان بسیار سپاسگذارم. +مبالغ مهم نیستند، از اقدام و پیام تشویق شما دوستان بسیار سپاسگذارم. (*اطلاعات این صفحه به صورت آنی بروز نمی‌شود!*) + +---- | @@ -20,172 +22,214 @@ + + + .. raw:: html -

26: 50,000 تومان در زمان 16:52 28-03-1398

+

29: 20,000 تومان در زمان 11:41 03-06-1398
ممنون از زحمات شما

---- + + .. raw:: html -

25: 50,000 تومان در زمان 09:13 08-02-1398

+

28: 5,000 تومان در زمان 13:10 02-06-1398
متشکرم که دانشتون رو در اختیار ما می زارید.

---- + .. raw:: html -

24: 50,000 تومان در زمان 22:44 26-01-1398

+

27: 1,000,000 تومان در زمان 22:23 11-04-1398
Omidvaram tashvighi beshe vase sorato detaile bishtar!

---- -سال 1397: 92,000 تومان + +.. raw:: html + +

26: 50,000 تومان در زمان 16:52 28-03-1398
وسع یه دانشجو همینقدره ببخشید. کاش تا جایی که میتونین وب سایتو رایگان نگه دارین...

---- .. raw:: html -

23: 5,000 تومان در زمان 13:52 23-11-1397

+

25: 50,000 تومان در زمان 09:13 08-02-1398
با تشکر

---- .. raw:: html -

22: 5,000 تومان در زمان 09:13 05-11-1397

+

24: 50,000 تومان در زمان 22:44 26-01-1398
آقا برای آموزش پایتون خیلی زحمت کشیدی، مرسی.

+ +---- + +| + +**سال 1397: 92,000 تومان** + +| + + ---- .. raw:: html -

21: 10,000 تومان در زمان 15:25 01-11-1397

+

23: 5,000 تومان در زمان 13:52 23-11-1397
از کتاب آموزش پایتون شما لذت بردم، درس اول و دوم رو خوندم. موفق و پیروز باشید.

---- .. raw:: html -

20: 2,000 تومان در زمان 20:36 20-10-1397

+

22: 5,000 تومان در زمان 09:13 05-11-1397
ممنون از کار بسیار مفید شما

---- .. raw:: html -

19: 1,000 تومان در زمان 13:47 13-10-1397

+

21: 10,000 تومان در زمان 15:25 01-11-1397
تشکر

---- .. raw:: html -

18: 1,000 تومان در زمان 09:35 28-07-1397

+

20: 2,000 تومان در زمان 20:36 20-10-1397
omid

---- .. raw:: html -

17: 1,000 تومان در زمان 18:39 20-07-1397

+

19: 1,000 تومان در زمان 13:47 13-10-1397
با سلام خیلی خوشحال شدم از مطالب خوبت. امیدوارم ادامه بدی ممنونم مجید

---- .. raw:: html -

16: 25,000 تومان در زمان 16:45 10-06-1397

+

18: 1,000 تومان در زمان 09:35 28-07-1397
salam

---- .. raw:: html -

15: 2,000 تومان در زمان 12:45 24-05-1397

+

17: 1,000 تومان در زمان 18:39 20-07-1397
خوب بود

---- .. raw:: html -

14: 20,000 تومان در زمان 19:50 08-04-1397

+

16: 25,000 تومان در زمان 16:45 10-06-1397
با تشکر

---- .. raw:: html -

13: 10,000 تومان در زمان 22:27 04-04-1397

+

15: 2,000 تومان در زمان 12:45 24-05-1397
با تشکر از کتاب روان و جامع شما

---- .. raw:: html -

12: 10,000 تومان در زمان 18:30 26-02-1397

+

14: 20,000 تومان در زمان 19:50 08-04-1397
.لطفا ادامه پایتون را هم تکمیل کنید

---- -سال 1396: 61,000 تومان +.. raw:: html + +

13: 10,000 تومان در زمان 22:27 04-04-1397
Awesome work! continue it!

+ +---- + +.. raw:: html + +

12: 10,000 تومان در زمان 18:30 26-02-1397
تشکر از نوشته بسیار خوبتان

+ +---- + +| + +**سال 1396: 61,000 تومان** + +| ---- .. raw:: html -

11: 5,000 تومان در زمان 17:51 06-12-1396

+

11: 5,000 تومان در زمان 17:51 06-12-1396
هدیه :)

---- .. raw:: html -

10: 10,000 تومان در زمان 21:23 10-09-1396

+

10: 10,000 تومان در زمان 21:23 10-09-1396
بهترین سایت پایتون هستید چقدر بدبختی کشیدم بدون شما. شرمنده فعلا کمه جبران میکنم بیشتر

---- .. raw:: html -

9: 5,000 تومان در زمان 21:00 07-09-1396

+

9: 5,000 تومان در زمان 21:00 07-09-1396
👍

---- .. raw:: html -

8: 10,000 تومان در زمان 08:39 06-08-1396

+

8: 10,000 تومان در زمان 08:39 06-08-1396
مرسی از آقا سعید عزیز برای این کار با ارزش. ارزش این کارتون هیچ جوره با قابل پرداخت نیست.

---- .. raw:: html -

7: 10,000 تومان در زمان 13:50 13-07-1396

+

7: 10,000 تومان در زمان 13:50 13-07-1396
لطفا ادامه بدید

---- .. raw:: html -

6: 1,000 تومان در زمان 10:04 11-06-1396

+

6: 1,000 تومان در زمان 10:04 11-06-1396
ببخشید کمه ولی ایشالا بعد بیشتر

---- .. raw:: html -

5: 10,000 تومان در زمان 22:44 16-04-1396

+

5: 10,000 تومان در زمان 22:44 16-04-1396
مبلغی ناچیز و ناقابل بابت زحماتی که درآموزش پایتون میکشید

---- .. raw:: html -

4: 10,000 تومان در زمان 17:51 11-04-1396

+

4: 10,000 تومان در زمان 17:51 11-04-1396
بخاطر کارهای خوب در نگارش دقیق آموزش پای‌تُن

---- -سال 1395: 18,000 تومان +| + +**سال 1395: 18,000 تومان** + +| + ---- .. raw:: html -

3: 10,000 تومان در زمان 19:33 27-11-1395

+

3: 10,000 تومان در زمان 19:33 27-11-1395
کارتون عالیه، ادامه بدید.

---- .. raw:: html -

2: 5,000 تومان در زمان 20:51 15-11-1395

+ +

2: 5,000 تومان در زمان 20:51 15-11-1395
با تشکر از زحمات شما برای نشر علم .هر چند این مبالغ در برابر تلاش شما ناچیز است .

+ ---- .. raw:: html -

1: 3,000 تومان در زمان 11:27 09-11-1395

+

1: 3,000 تومان در زمان 11:27 09-11-1395
دم شما گرم

From 9e53dfc295972aad7719d7e4a220a042dc0bf911 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 19 Oct 2019 21:12:54 +0330 Subject: [PATCH 041/316] start f-string --- lessons/l07.rst | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/lessons/l07.rst b/lessons/l07.rst index a5d54d4..b6fbef0 100644 --- a/lessons/l07.rst +++ b/lessons/l07.rst @@ -1414,6 +1414,51 @@ >>> '{0:{fill}{align}16}'.format(text, fill=align, align=align) '>>>>>>>>>>>Right' + +f-string +~~~~~~~~~~ + +از نسخه پایتون 3.6 یک امکان جدید و بسیار جالب در مورد بحث قالب‌بندی رشته‌ها ارايه شده است که با عنوان ``f-string`` شناخته می‌شود [`PEP 498 `__]. + +ساختار همان ساده شده حالت ``()str.format`` می‌باشد:: + + >>> name = "Saeid" + >>> age = 32 + >>> f"Hello, {name}. You are {age}." + 'Hello, Saeid. You are 32.' + >>> + +یعنی اگر در ابتدای یک متن، حرف ``f`` یا ``F`` قرار دهیم، آنگاه می‌توانیم متغیرها یا عبارات خود را مستقیم در داخل آن - با استفاده از ``{}`` - قرار بدهیم:: + + >>> f"{2 * 37}" + '74' + +در نمونه کد پایین یک تابع را مستقیم در داخل متن موجود فراخوانی می‌کینم:: + + >>> def to_lowercase(input): + ... return input.lower() + ... + >>> + >>> name = "Eric Idle" + >>> + >>> f"{to_lowercase(name)} is funny." + 'eric idle is funny.' + +:: + + >>> f"{name.lower()} is funny." + 'eric idle is funny.' + >>> + + + + + + + + + + .. rubric:: برخی از متدهای کاربردی یک شی رشته * ``()capitalize`` [`اسناد پایتون `__] - یک کپی از رشته که نخستین حرف آن به صورت بزرگ (Capital) نوشته شده است را برمی‌گرداند:: From 295e922638ad4d0b119518f77a8fdf177c7bada1 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 19 Oct 2019 21:15:44 +0330 Subject: [PATCH 042/316] remove a ref to l07 - temp --- lessons/l13.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index e4650c6..9c7c081 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -313,7 +313,6 @@ Decorator در این مثال از تابع ``perf_counter`` برای محاسبه فواصل زمانی (time intervals) [`مستندات پایتون `__] استفاده شده که تنها از نسخه 3.3 به بعد در دسترس می‌باشد [`اطلاعات تکمیلی `__]. -چنانچه درک دستور ``("print(f"Finished {func.__name__!r} in {run_time:.4f} secs`` برایتان مبهم است به درس هفتم بخش مربوط به رشته‌ها مراجعه نمایید. Generator From dbb7790a049779b65464e748e90ce3360a68853c Mon Sep 17 00:00:00 2001 From: Saeid Date: Sun, 20 Oct 2019 10:14:28 +0330 Subject: [PATCH 043/316] explain f-string --- lessons/l07.rst | 67 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/lessons/l07.rst b/lessons/l07.rst index b6fbef0..3f3b3e3 100644 --- a/lessons/l07.rst +++ b/lessons/l07.rst @@ -893,7 +893,8 @@ -.. rubric:: دنباله‌ها +رشته به عنوان دنباله‌ (Sequence) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ برخی از انواع شی پایتون به مانند رشته، تاپل (tuple)، لیست (list) و... با عنوان **دنباله** (Sequence) نیز شناخته می‌شوند. دنباله ویژگی‌هایی دارد که در اینجا به کمک نوع رشته بررسی خواهیم کرد. رشته در واقع یک **دنباله** از کاراکترهاست در نتیجه می‌توان هر یک از اعضای این دنباله را با استفاده از اندیس (Index) موقعیت آن دستیابی نمود؛ اندیس اعضا از سمت چپ با عدد صفر شروع و به سمت راست یک واحد یک واحد افزایش می‌یابد. به عنوان نمونه برای شی ``'Python Strings'`` می‌توانیم شمای اندیس‌گذاری را به صورت پایین در نظر بگیریم:: @@ -960,7 +961,8 @@ TypeError: 'str' object does not support item assignment -.. rubric:: عملگرها برای رشته +عملگرها برای رشته +~~~~~~~~~~~~~~~~~~~~ با رشته‌ها نیز می‌توان از عملگرهای ``+`` (برای پیوند رشته‌ها) و ``*`` (برای تکرار رشته‌ها) بهره برد:: @@ -1000,7 +1002,8 @@ کمی جلوتر خواهید دید که از عملگر ``%`` نیز برای قالب‌بندی رشته‌ها استفاده می‌گردد. -.. rubric:: کاراکترهای Escape +کاراکترهای Escape +~~~~~~~~~~~~~~~~~~ به صورت پیش‌فرض تعدادی کاراکتر خاص تعریف شده است که می‌توان آن‌ها را درون رشته‌ها بکار برد. تمام این کاراکترها با یک ``\`` آغاز می‌شوند به همین دلیل گاهی نیز به نام Backslash Characters خوانده می‌شوند. در واقع این کاراکترها امکانی برای درج برخی دیگر از کاراکترها هستند که نمی‌توان آن‌ها را به سادگی توسط صفحه‌کلید وارد کرد. برای نمونه یکی از کاراکترهای Escape رایج ``n\`` است که بیانگر کاراکتری با کد اسکی 10 (LF) به نام newline می‌باشد؛ ``n\`` در هر جایی از رشته (یا متن) که درج گردد در هنگام چاپ سطر جاری را پایان می‌دهد و ادامه رشته (یا متن) از سطر جدید آغاز می‌‌شود [`اسناد پایتون `__]:: @@ -1040,7 +1043,8 @@ C:\new\text\sample.txt -.. rubric:: تبدیل کد به کاراکتر و برعکس +تبدیل کد به کاراکتر و برعکس +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ می‌دانیم برای اینکه کامپیوتر بتواند کاراکتر‌ها را درک کند نیاز به سیستم‌هایی است که آن‌ها را برای تبدیل به کدهای پایه دو کدگذاری کند؛ به مانند سیستم اَسکی (ASCII) یا سیستم‌های جامع‌تری مانند UTF-8 که تحت استاندارد یونیکد (Unicode) در دسترس است. گاهی نیاز است به این کدها دسترسی داشته باشیم و با کاراکترها بر اساس آن‌ها کار کنیم؛ برای این منظور در پایتون می‌توان از دو تابع ``()ord`` (تبدیل کد به کاراکتر) [`اسناد پایتون `__] و ``()chr`` (تبدیل کاراکتر به کد) [`اسناد پایتون `__] استفاده کرد. تابع ``()ord`` یک رشته تک کاراکتری را گرفته و یک عدد (در پایه ده) که بیانگر کد کاراکتر مورد نظر می‌باشد را برمی‌گرداند. تابع ``()chr`` نیز کد کاراکتری (که می‌بایست عددی در پایه ده باشد) را گرفته و کاراکتر مربوط به آن را برمی‌گرداند:: @@ -1087,7 +1091,8 @@ -.. rubric:: تبدیل به نوع رشته +تبدیل به نوع رشته +~~~~~~~~~~~~~~~~~~~~ برای تبدیل اشیایی از نوع دیگر به نوع رشته؛ کلاس ``()str`` [`اسناد پایتون `__] و تابع ``()repr`` [`اسناد پایتون `__] وجود دارد. کلاس ``()str`` یک نمونه غیر رسمی (informal) از نوع شی رشته را برمی‌گرداند؛ غیر رسمی از این جهت که توسط آن جزییات شی رشته پنهان می‌شود. اما تابع ``()repr`` یک نمونه رسمی (official) از نوع رشته پایتون را برمی‌گرداند. کمی قبل‌تر راجب تفاوت خروجی ``print`` و حالت تعاملی صحبت کردیم؛ در واقع خروجی ``()str`` مناسب برای چاپ است و همانند ``print`` جزییات این نوع شی را ارایه نمی‌دهد در حالی که ``()repr`` به مانند حالت تعاملی یک ارايه (representation) کامل از شی رشته را برمی‌گرداند:: @@ -1122,7 +1127,8 @@ '10' -.. rubric:: قالب‌بندی رشته‌ (String Formatting) +قالب‌بندی رشته‌ (String Formatting) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ قالب‌بندی امکانی برای جایگزین کردن یک یا چند مقدار (به بیان بهتر: شی) - گاهی همراه با اعمال تغییر دلخواه - درون یک رشته است که به دو شکل در پایتون پیاده‌سازی می‌گردد [`اسناد پایتون `__]: @@ -1418,7 +1424,7 @@ f-string ~~~~~~~~~~ -از نسخه پایتون 3.6 یک امکان جدید و بسیار جالب در مورد بحث قالب‌بندی رشته‌ها ارايه شده است که با عنوان ``f-string`` شناخته می‌شود [`PEP 498 `__]. +از نسخه پایتون 3.6 یک امکان جدید و بسیار جالب در بحث قالب‌بندی رشته‌ها ارايه شده است که با عنوان ``f-string`` شناخته می‌شود [`PEP 498 `__]. ساختار همان ساده شده حالت ``()str.format`` می‌باشد:: @@ -1433,7 +1439,43 @@ f-string >>> f"{2 * 37}" '74' -در نمونه کد پایین یک تابع را مستقیم در داخل متن موجود فراخوانی می‌کینم:: +بدیهی است که متغیرها (- یا نتیجه حاصل عبارات) یا اشیای مورد استفاده در شیوه **f-string** در نهایت برای قرار گرفتن درون متن یا رشته مورد نظر می‌بایست به نوع رشته تبدیل شوند. در این شیوه به صورت پیش‌فرض متد ``()__str__`` برای تبدیل به نوع رشته فراخوانی می‌شود ولی می‌توان با قرار دادن نشانگر ``r!`` در انتهای شی مورد نظر، تعیین کرد که متد ``()__repr__`` فراخوانی شود:: + + >>> name = 'Saeid' + >>> print(f'My name is {name}') + My name is Saeid + >>> print(f'My name is {name!r}') + My name is 'Saeid' + >>> + +در این شیوه می‌توان از نماد ``{}`` در خارج از اصول قالب‌بندی استفاده کرد ولی باید توجه داشت که هر دو نماد ``{{}}`` به عنوان یک ``{}`` در نظر گرفته می‌شود. وجود سه ``{{{}}}`` نیز در حکم همان دو تا می‌باشد:: + + >>> f'{{{{32}}}}' + '{{32}}' + >>> f'{{{32}}}' + '{32}' + >>> f'{{32}}' + '{32}' + >>> f'{32}' + '32' + +:: + + >>> print(f'{{My name}} is {name}') + {My name} is Saeid + + >>> print(f'{{My name}} is {{name}}') # NOTE! + {My name} is {name} + + >>> print(f'{{My name}} is {{{name}}}') + {My name} is {Saeid} + + >>> print(f'{{My name}} is {{{{name}}}}') # NOTE! + {My name} is {{name}} + + + +در نمونه کد پایین یک تابع را مستقیم در داخل متن موجود فراخوانی می‌کنیم:: >>> def to_lowercase(input): ... return input.lower() @@ -1459,7 +1501,9 @@ f-string -.. rubric:: برخی از متدهای کاربردی یک شی رشته + +برخی از متدهای کاربردی یک شی رشته +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ``()capitalize`` [`اسناد پایتون `__] - یک کپی از رشته که نخستین حرف آن به صورت بزرگ (Capital) نوشته شده است را برمی‌گرداند:: @@ -1672,7 +1716,10 @@ f-string -.. rubric:: چگونگی ارايه نوع رشته از موارد اختلاف اساسی در نسخه‌های 2x و 3x پایتون است. +انواع رشته +~~~~~~~~~~~~ + +چگونگی ارايه نوع رشته از موارد اختلاف اساسی در نسخه‌های 2x و 3x پایتون است. در **نسخه‌های 2x** یک نوع جامع ``str`` که محدود به کدگذاری ASCII است؛ هر دو قالب رشته‌های معمولی و داده‌های باینری (متن‌های کدگذاری شده، فایل‌های مدیا و پیام‌های شبکه) را در بر می‌گیرد - رشته باینری با یک حرف b در آغاز آن‌ مشخص می‌گردد. در این سری از نسخه‌ها نوع دیگری نیز با نام ``unicode`` وجود دارد که رشته‌های خارج از محدوده کدگذاری ASCII را در بر می‌گیرد؛ برای ایجاد این نوع اشیا می‌بایست رشته مورد نظر با یک حرف ``u`` آغاز گردد:: From 4715e91d133fa5130bebdc9ef64ec145697489a1 Mon Sep 17 00:00:00 2001 From: Saeid Date: Sun, 20 Oct 2019 10:25:08 +0330 Subject: [PATCH 044/316] add re ref to l07 --- lessons/l13.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index 9c7c081..09d5e8a 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -201,7 +201,7 @@ Decorator **functools.wraps@** ~~~~~~~~~~~~~~~~~~~~~ -در پایتون عنوانی مطرح است به نام **Higher-order functions** (توابع مرتبه بالاتر) و به توابعی گفته می‌شود که اعمالی را روی توابع دیگر انجام می‌دهند یا یک تابع جدید را به عنوان خروجی برمی‌گرداند. بر همین اساس یک ماژول به نام ``functools`` نیز در کتابخانه استاندارد پایتون قرار گرفته است که یک سری توابع کمکی و کاربردی برای این دست توابع ارائه می‌دهد [`مستندات پایتون `__]. یکی از توابع داخل این ماژول ``wraps`` [`مستندات پایتون `__] می‌باشد. +در پایتون عنوانی مطرح است به نام **Higher-order functions** (توابع مرتبه بالاتر) و به توابعی گفته می‌شود که اعمالی را روی توابع دیگر انجام می‌دهند یا یک تابع جدید را به عنوان خروجی برمی‌گرداند. بر همین اساس یک ماژول به نام ``functools`` نیز در کتابخانه استاندارد پایتون قرار گرفته است که یک سری توابع کمکی و کاربردی برای این دست توابع ارائه می‌دهد [`اسناد پایتون `__]. یکی از توابع داخل این ماژول ``wraps`` [`اسناد پایتون `__] می‌باشد. **اما چرا معرفی این تابع در این بخش مهم است؟** وقتی ما از یک Decorator‌ استفاده می‌کنیم، اتفاقی که می‌افتد این است که یک تابع جدید جایگزین تابع اصلی ما می‌شود. به نمونه کدهای پایین توجه نمایید:: @@ -311,7 +311,9 @@ Decorator >>> waste_some_time(999) Finished 'waste_some_time' in 2.6838 secs -در این مثال از تابع ``perf_counter`` برای محاسبه فواصل زمانی (time intervals) [`مستندات پایتون `__] استفاده شده که تنها از نسخه 3.3 به بعد در دسترس می‌باشد [`اطلاعات تکمیلی `__]. +در این مثال از تابع ``perf_counter`` [`اسناد پایتون `__] برای محاسبه فواصل زمانی (time intervals) استفاده شده که تنها از نسخه 3.3 به بعد در دسترس می‌باشد [`اطلاعات تکمیلی `__]. + +چنانچه درک کد ``print(f"Finished {func.__name__!r} in {run_time:.4f} secs")`` برایتان مبهم است به درس هفتم بخش **f-string** مراجعه نمایید [`درس هفتم f-string `__]. From c2b057c1e06a87658bafef95b3de4cb3086561f5 Mon Sep 17 00:00:00 2001 From: Saeid Date: Sun, 20 Oct 2019 10:47:09 +0330 Subject: [PATCH 045/316] some edit on l07 --- lessons/l07.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lessons/l07.rst b/lessons/l07.rst index 3f3b3e3..b170483 100644 --- a/lessons/l07.rst +++ b/lessons/l07.rst @@ -1493,8 +1493,31 @@ f-string >>> +همچنین می‌توانیم هر یک از اشیا مورد استفاده در درون متن را با شیوه خاص آن شی، با قرار دادن یک ``:`` به صورت جداگانه قالب‌بندی نماییم:: + >>> a_float_number = 5.236501 + >>> print(f'{a_float_number:.4f}') + 5.2365 + >>> print(f'{a_float_number:.2f}') + 5.24 + >>> + +:: + + >>> a_int_number = 16 + >>> print(f'{a_int_number:05d}') + 00016 + >>> + +:: + + >>> import datetime + >>> now = datetime.datetime.now() + >>> print(f'{now:%Y-%m-%d %H:%M}') + 2019-10-20 10:37 + +در دروس آینده در مورد ماژول ``datetime`` صحبت خواهیم کرد. [`اسناد پایتون `__] From d411c598714e79aef1cfd319920008a3a25a08e4 Mon Sep 17 00:00:00 2001 From: Saeid Date: Sun, 20 Oct 2019 10:54:30 +0330 Subject: [PATCH 046/316] add l13 report --- log.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/log.rst b/log.rst index ca07fc3..d9569dd 100644 --- a/log.rst +++ b/log.rst @@ -9,6 +9,20 @@ گزارش توسعه ============= + +.. raw:: html + +

00112 - یک‌شنبه ۲۸ مهر ۱۳۹۸

+ +* درس سیزدهم با عنوان «تابع - بخش دوم» به فهرست کتاب افزوده شد. +* بخش **f-string** به درس هفتم اضافه گردید. +* کمی توضیح در مورد دستور ``return`` به درس دوازدهم اضافه گردید. +* گزارش هدایای پرداخت شده بروز گردید. +* یک خط فرمان پایتون به صفحه نخست اضافه گردید. *برگرفته از وب‌سایت پایتون* + +---- + + .. raw:: html

00111 - چهارشنبه ۵ تیر ۱۳۹۸

From 350ac8b1b75897a8c793f3f5e1eca8314b5bdf5c Mon Sep 17 00:00:00 2001 From: Saeid Date: Sun, 20 Oct 2019 15:18:39 +0330 Subject: [PATCH 047/316] change google analytics code --- _templates/sphinx_minoo_theme/theme.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_templates/sphinx_minoo_theme/theme.conf b/_templates/sphinx_minoo_theme/theme.conf index 7e2db3b..76517ed 100644 --- a/_templates/sphinx_minoo_theme/theme.conf +++ b/_templates/sphinx_minoo_theme/theme.conf @@ -15,7 +15,7 @@ language = fa body_max_width = 800px # # Set up the web tracking code (Google Analytics). -analytics_id = UA-61670451-1 +analytics_id = UA-107863650-1 # # Your links: # Whichever you don't want, left empty! From 0f7ef848729c8033cb6bd9e953505b5800c970d0 Mon Sep 17 00:00:00 2001 From: Saeid Date: Sun, 20 Oct 2019 15:59:01 +0330 Subject: [PATCH 048/316] modify footer --- _templates/sphinx_minoo_theme/includes/bottom.html | 2 +- conf.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/_templates/sphinx_minoo_theme/includes/bottom.html b/_templates/sphinx_minoo_theme/includes/bottom.html index 51703cd..2f7b6e9 100644 --- a/_templates/sphinx_minoo_theme/includes/bottom.html +++ b/_templates/sphinx_minoo_theme/includes/bottom.html @@ -39,7 +39,7 @@

{%- if last_updated %}

- {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} + .آخرین بروز رسانی در {{ last_updated }}

{%- endif %} {%- if show_sphinx %} diff --git a/conf.py b/conf.py index ce71d64..8f890dd 100644 --- a/conf.py +++ b/conf.py @@ -47,8 +47,8 @@ # General information about the project. project = u'کتاب آزاد آموزش پایتون' -copyright = u'2015, Saeid Darvishi' -author = u'Saeid Darvishi' +copyright = u'2015, Saeid Darvish' +author = u'Saeid Darvish' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -223,7 +223,7 @@ # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'PythonPersianTutorial.tex', u'PythonPersianTutorial Documentation', - u'Saeid Darvishi', 'manual'), + u'Saeid Darvish', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of From 7bb3f95646f712f4d68e195a18954b954fa99b93 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sun, 20 Oct 2019 23:42:24 +0330 Subject: [PATCH 049/316] add link to coderz.ir (11,12,13) --- lessons/l11.rst | 2 +- lessons/l12.rst | 2 ++ lessons/l13.rst | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lessons/l11.rst b/lessons/l11.rst index c000674..4190665 100644 --- a/lessons/l11.rst +++ b/lessons/l11.rst @@ -830,6 +830,6 @@ os.path :emoji-size:`😊` امیدوارم مفید بوده باشه -`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ diff --git a/lessons/l12.rst b/lessons/l12.rst index c9247ab..a1b8892 100644 --- a/lessons/l12.rst +++ b/lessons/l12.rst @@ -821,5 +821,7 @@ :emoji-size:`😊` امیدوارم مفید بوده باشه +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ + diff --git a/lessons/l13.rst b/lessons/l13.rst index 09d5e8a..dc1dfca 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -2,7 +2,7 @@ .. meta:: :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس سیزدهم تابع - :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, انواع شی, انواع داده, پایتون + :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, تابع, Decorator, پایتون, lambda, Generator, Coroutine درس ۱۳: تابع - بخش دوم @@ -791,5 +791,7 @@ lambda و توابع ناشناس :emoji-size:`😊` امیدوارم مفید بوده باشه +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ + From 1b967cdd4fdf9e6806299008390da72aacf0a36f Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 21 Oct 2019 00:29:41 +0330 Subject: [PATCH 050/316] fix l13 text width --- lessons/l13.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index dc1dfca..68c502e 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -313,7 +313,7 @@ Decorator در این مثال از تابع ``perf_counter`` [`اسناد پایتون `__] برای محاسبه فواصل زمانی (time intervals) استفاده شده که تنها از نسخه 3.3 به بعد در دسترس می‌باشد [`اطلاعات تکمیلی `__]. -چنانچه درک کد ``print(f"Finished {func.__name__!r} in {run_time:.4f} secs")`` برایتان مبهم است به درس هفتم بخش **f-string** مراجعه نمایید [`درس هفتم f-string `__]. +چنانچه درک کد دستور ``print`` در تابع ``wrapper_timer`` برایتان مبهم است به درس هفتم بخش **f-string** مراجعه نمایید [`درس هفتم f-string `__]. From c75973ca97802e4e952676540c3b0f6a37901348 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Wed, 23 Oct 2019 21:40:59 +0330 Subject: [PATCH 051/316] create l14 --- index.rst | 1 + lessons/l14.rst | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 lessons/l14.rst diff --git a/index.rst b/index.rst index c62d637..0ad180c 100644 --- a/index.rst +++ b/index.rst @@ -28,6 +28,7 @@ lessons/l11 lessons/l12 lessons/l13 + lessons/l14 log donate diff --git a/lessons/l14.rst b/lessons/l14.rst new file mode 100644 index 0000000..93d5eae --- /dev/null +++ b/lessons/l14.rst @@ -0,0 +1,49 @@ +.. role:: emoji-size + +.. meta:: + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی - درس چهاردهم تابع + :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, تابع, Decorator, پایتون, lambda, Generator, Coroutine + + +درس ۱۴: تابع - بخش سوم +======================== + +این درس بخش پایانی از بررسی تابع در پایتون می‌باشد و موضوعات باقی‌مانده از مبحث تابع پایتون در این درس بیان می‌شود. + + + + + + +:emoji-size:`✔` سطح: متوسط + +---- + + +.. contents:: سرفصل‌ها + :depth: 2 + +---- + + + + +تابع بازگشتی +------------ + + + + + + + +| + +---- + +:emoji-size:`😊` امیدوارم مفید بوده باشه + +`لطفا دیدگاه و سوال‌های مرتبط با این درس خود را در کدرز مطرح نمایید. `_ + + + From 184938f1bf7d5c7d7bf0e41e4b6975747e0ccba2 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Wed, 23 Oct 2019 22:57:20 +0330 Subject: [PATCH 052/316] start Recursive function --- lessons/l14.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lessons/l14.rst b/lessons/l14.rst index 93d5eae..270b471 100644 --- a/lessons/l14.rst +++ b/lessons/l14.rst @@ -31,6 +31,36 @@ تابع بازگشتی ------------ +از درس نهم با دستورات کنترلی ``for`` و ``while`` آشنا شده‌ایم، این دستورات تنها ابزار ما برای تکرار قسمتی از کد بودند. اکنون با پیاده‌سازی شیوه‌ای جدید در تکرار آشنا می‌شویم. + +به بیانی ساده، **تابع بازگشتی** (Recursive function) به تابعی گفته می‌شود که خود را از داخل بدنه خود فراخوانی می‌کند. پیاده‌سازی تابع به صورت بازگشتی شیوه‌ای است که از آن برای حل برخی مسائل بهره گرفته می‌شود و باید بدانیم که توابع بازگشتی، یک سینتکس یا دستور خاص در زبان پایتون نیست بلکه یک شیوه حل مسئله می‌باشد که با استفاده از تابع در زبان برنامه‌نویسی پایتون (همچون بسیاری از زبان‌های دیگر) قابل پیاده‌سازی است. + +برای مثال در نمونه کد پایین مقدار فاکتوریل (`Factorial `_) عدد پنج را به شیوه بازگشتی محاسبه می‌کنیم:: + + + >>> def factorial(n): + ... if n <= 1: + ... return 1 # 0! == 1 and 1! == 1 + ... else: + ... return n * factorial(n - 1) + ... + >>> + >>> factorial(5) + 120 + >>> + +عموما می‌توان مسئله‌هایی که از **توالی** انجام یک **کار یکسان** قابل حل هستند را به صورت بازگشتی پیاده‌سازی کرد. مراحل اجرای نمونه کد بالا به صورت زیر است:: + + factorial(5) + |--> 5 * factorial(4) + |--> 4 * factorial(3) + |--> 3 * factorial(2) + |--> 2 * factorial(1) + |--> 1 + + 5 * (4 * (3 * (2 * 1))) + +**پیاده‌سازی شیوه بازگشتی شاید به نظر هیجان‌انگیز باشد اما نباید فراموش کرد که میزان حافظه (Memory) زیادی مصرف می‌کند، اجرای آن زمان‌بر خواهد بود، درک جریان اجرای آن اغلب سخت است و اشکال‌زدایی (debug) آن ساده نخواهد بود!** From 8c6b658f07ef47004a60e95412e4508cf74ac96a Mon Sep 17 00:00:00 2001 From: Saeid Date: Thu, 24 Oct 2019 15:10:03 +0330 Subject: [PATCH 053/316] * --- _static/l14-factorial-relation.png | Bin 0 -> 15826 bytes lessons/l14.rst | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 _static/l14-factorial-relation.png diff --git a/_static/l14-factorial-relation.png b/_static/l14-factorial-relation.png new file mode 100644 index 0000000000000000000000000000000000000000..a1c127e12ba90abab796f7016d020e3568dea367 GIT binary patch literal 15826 zcmb8WbyQVb*e|>Z=`InF5*4JoOBw}46e*=kKoIHfkX8X{P(q{|q)Qs4yQKuAL-IcR zy!RX9y?=h5;~8xB+I!74=M%qpPUsU=1$-PT90US^ucRpZ6oEjwgr8qyVZeVYCqg<9 z2)rt{XIc(V4V~%j>}|~~txf42Ts2M6!AFF8ELX{X%06@@;z_7&+*yVhs7@16bgeKpr{w7K`|&CjNJO@O#>`N(!xMq2D8N6&IhKJu3K6AY-{|fPCHBR)`FDakr z%Ipzd)K4q|6RmP9DyKHTl@-S6T2@qyC2fxUsfmB(zF8k7aZcs>NnL^3Gn~64k%yN@ zv(>t6fO}0ZEUB=xdTi;U9fiD4r~LJBp-fI8zNgcqW7X`*#5+#Xo*;B|t1+92a>pTG z<(y=pSH!k>s|UpV_(?vAkW{pix{oh{=-O;m*Gk1jCULRli9|w zq>BJOyY(x&&Ktph1%F??pCGoSd65)FDsRkL(uvc=q$u6PjzpE+b*x7?@7i0Tz zmr2*u63gG|$1IL1#Co>xEyZV)t+zQs+2vyE$G8$L{o)x-U5|cjO^G?0$I5EkY%m{% z%N+#8a17DZX8nkG?UY#5y;1u+kWH|7LMcd@E{0I}$u}#`N>Mp8*dy281$9oGsME5v zJ%ytDto&)_lG20>k#X$4NR^n9$$Y1psfBJKb?uFx*{q7M>m0R2+rKbUJEm&9NZuB} zAtTpVzi;>RJ8z$k-Z#RT$+Fuiq77&2{oRSfHoA_0DtCky#Zfezum3iC%>j1O}-^z zEqQM7IXeX{iFGSM)O0i;k%N_nbEf))iz?izyf{C1iXb34{Rz>fal^uqCjseA@5Ta=hkH2xxJ|?lI~fTa zLMRWawFw>tP1z;8Ju&3_W-VA>^O8LK>0{I;4z!es?l-IWbK8BTH~+P;QbeMLtLuze z2=t@I))hdjCGoF%JLgb=5Fqwd_r%IztiD{1=Y*&qhCx z$0Yr{?R9E0kK?90Ds;oGtVWZk-VcxT68+waE2~v*A#rN6>ukA(yccOt$1OVok4@r0 zr_D!A-IT#<8JS(5YA)8hox0a*x+#lp zk}RUiD*ra4<0Myh#+J4(0G(+HIN8Jj^g@_vpl_;YaWzeoHGX4X>BxbHNo z;@rG-qr~xTEVIpBb*ktr%v!-g0j7-4c;_ey)N6LXa#?)er#~t}JU1cp>w0lnzlQn4 zce{M)x$R;snN!bZQqItyOhS8cRC!5b+Q4FiR(6#WC#?R08Cd4w>I zPrZf>9fi5=4JrFWvF0zoUP^fk{bX4D5`a#bcJEeZWfjRVar-S#VbNPGA~<6+H=jy( zhO3aF2OG#cz46b$Hnclw`FdhF)!uJ8rL4Ijox~k-mxuT}SMi;9AAPTG;5X&2-!~&; z@ZH&f0 z+N%zfBvuD69-@0K&{j|&CK^<0R0a5MN_Gt8VDsIKy20~mCbJLIUo?j?(}5uJ)~|g3 zvUFKmx6eGC*t?jxb+kIzoR7(g2ks4171l2l7I(d?_?6M+O3bM;{qpFS@-zRDYBtf^ z(Woi|?Kb{7{v5 z=V-4hcmoZ?*pzXd%ksve?q^wp;`Nn3@&nYU%)QUhc;w4pVcxe@u<6-)Ll-GiPcU8B zv_?KdeVM0CnkE_QT#@wExP~$64!kadb>Hu`vVS5* zI4isfS(c|9PGlkQ#4P61QN=x)N5isj$mBfn5;R`g3qD|7%=%Hyjq$-7VKGF9jZQ_( zLL&c*mV_{Itx(yAC|+NW!n8=b{yOsXrhMRA{}SKCR@aA12D{24CB*@e{

FU+lI; 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 -عموما می‌توان مسئله‌هایی که از **توالی** انجام یک **کار یکسان** قابل حل هستند را به صورت بازگشتی پیاده‌سازی کرد. مراحل اجرای نمونه کد بالا به صورت زیر است:: +عموما می‌توان مسئله‌هایی که از **توالی** انجام یک **کار یکسان** قابل حل هستند را به صورت بازگشتی پیاده‌سازی کرد. مراحل اجرای نمونه کد بالا به صورت زیر است: + +.. image:: /_static/l14-factorial-relation.png + :align: center + +:: factorial(5) |--> 5 * factorial(4) @@ -60,8 +65,22 @@ 5 * (4 * (3 * (2 * 1))) +**توضیح:** هنگامی factorial(5) فراخوانی می‌شود (``n == 5``)، شرط ``1 => n`` رد و بخش + **پیاده‌سازی شیوه بازگشتی شاید به نظر هیجان‌انگیز باشد اما نباید فراموش کرد که میزان حافظه (Memory) زیادی مصرف می‌کند، اجرای آن زمان‌بر خواهد بود، درک جریان اجرای آن اغلب سخت است و اشکال‌زدایی (debug) آن ساده نخواهد بود!** +هر تابع بازگشتی شامل دو بخش مهم است: + +* یک عبارت حاوی فراخوانی خود تابع +* یک شرط برای انتخاب بین بازگشت (فراخوانی مجدد) و پایان + +در مورد مثال محاسبه فاکتوریل، چنانچه شرط ``1 => n`` برقرار شود، عملیات به انتها می‌رسد. + + + + + + From 18da6a733a439260a18c612f6a97c660c5f94488 Mon Sep 17 00:00:00 2001 From: Saeid Date: Sat, 26 Oct 2019 14:04:53 +0330 Subject: [PATCH 054/316] work on Recursive --- _static/l14-factorial-relation.png | Bin 15826 -> 14992 bytes lessons/l14.rst | 46 +++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/_static/l14-factorial-relation.png b/_static/l14-factorial-relation.png index a1c127e12ba90abab796f7016d020e3568dea367..67bb1d53ae8115fb135875c8080d7c2942992efc 100644 GIT binary patch literal 14992 zcmb8VcR1I7`1k!WviBydP_hcydy|Zik-f>D*)w~StPnEFC^E|)*@Wy7ku4)zxX#b_ zI*#kOf7fyUao^vLufm7V`~7;q&hvaeAJ12mx~c*`4h;?hfxuT%l+{2WP%h!$&#^Gz zW9?LAHv)l2?4zaYu3`Fu(b?6>%GTbJ(cRnGlF`!3)(U~}nki3raAguAkiGs(=8I0U zxaOi55<7KsVE-hKx$f(HPEOp1gbpo}8@pi( zfv39amqYEOzD@^CiG5o>KG*c&jX4A7V=fEVyRVnh`g|C+`ga?i;IWq#ldRa}>t1OZ zz0mN?lPNY{E4KL^_C#bjW_4}tv?*YzDZvT1h8De_P@t| zgv}y#({HV4J;LfwEt&JG1b$oC7G(|ntsk?B(TjgbFIT(nR&JMa>jH)4;>DLy)KjX+ zNXJA?uKt9kcWccZyWNArFKRp4St_ZhuFvV3jZOnw0`=C7ioG8hJ?2y^pGp&KnF?oG zlkg@FdUsJ_>%E!PzI7|$($$0{$PFBS@#XhFq{@CAxD@j&9 z6BLetTJ}b{;!r4brDdCk+w_tVwCwVyeZAMwv@&$!)hI-c-l z@F$>-j!k{AX;YBEy}DAwt2U9@7~pE!JDRGa=TS30sp}?_oBd+iqi+6WYOM1|Vvxyr zrpHZwHDUFQ6-`yKokQNCM(3T)!MZu0*_{`2XJ|D7A6oK{$s1baIh&rOV6p}pUdYDv zm-}-h8K_2^W0)nAMhYk(q+`q}eEalhg}ONiM&3SqX-I+Doy>$0a>jg5;Ij1(X@f); zr}}(gbe3O)f%Ezm{z{0<38`z#@-hB%eujo|OvYX5=h4z^JKZrw?pLOFjT!8?sHd&qHB@V^@v3*AzweM(SAlJ!;Tm!eB=&gYwh4_obSSqkfCcsjhP@=(ez z&|Jjcw$kcw_1s(edOVwsZPpQHiM13T%KPlH&Bz=7e>o->|Ji% zw0xs!MSG-;Lq=KjU3HQCbL_)Mo_XTV)(JinQ~Toyu0>obb$@Ekg?N>Z^^4|p?a5UA zv}Qg;UME~U|G1?}w~hJuj$Uzns7+JSNzQm%L?7X!art=!vE}b`#ztx31zh=k& zPSkQS%Dbv&LKCR?W1rki+=9i-?;5h_6^-#s@(MU|9^x#sadNnoJtcfe`!2C zrDUk_nY^+4@8^~yh12Wl{#zlKDpMR9xOI3QQw1hRDJ-~px5ab}N6K=Q@I7unxR8v@?#}ZvV{H22CH(|5dQ4Z{%U8|RAT~RofCTr+ z7rIS?K;4J+_fQQI?6rgRyodDW`s;S>-{o7+m()t}7*I+5O`v!|y~975{p)dz&fu;z z`777TqOyhTfd|vLEt`sO30J=kk)tntEqk0IBJn+!pFa~9jdW1w{^<_N&hevnWP4F1 zk5}&(6*IF}yeXb%bXoNsEl_g59?=UneqE@&NWrc5R=qq;_O@-Fw|934Tw7S ze2la-yI2<#PUsiqG;s3nRiP)!c1_sI{3rEgFW}dE6l~Jr-^0<(2Lw=<_iSk9=<#Wm z+fQDtrjl*e{r6sT=w0m&hVf$~Q{2@*+?n6J&F#0ngPt2lp`aWyT`N{%N{BzG>?KXP*%g2wy)~MU(1JzUt1}Enz%xnMa^^Dh&VEPp?tWe@xUN^a9f=# z-=SujNLB+SW#OHi2CG`cm<%FO*laW2>0R(9zv_+Y)ahs3pC8n-{BbtWC%APxlwWqv z&}}bENhs-;W|eZRZn(6?dm_BoYR?7*W-{VM|J?rgT@3Aa=CMY3gv1h`_m`1n*JMJW z<=-MtQ~a^!x|e$?MVP)MjA4u2j305oDY|#1si=N)Ojd@MIQUvC+|l92TaE&jT37ze z3{4gs^d;K<*F&u>`y_&vDD7O~4NcFxQUr&s2HtLqixR2qX|0M2v;28Kw655lPxj!) z8o2?wpiUG8+0eGKFLO1fy=}YSy1!qLKyq;8OFMIdKgh%gEjp`}Qh&KHdDN#P6T9`6Qj?mA z-mcojQmxcn3TwKH0ox*APkC{g$knkVj_JW2iV-=PdzQR|XapVCp?ANJeKHqGR(^-K zryjgF;PNm$4mB)PgHwuY{JVqx6nQ)5XT`heP8D{f0sOw0jpzr~8ms;Caol6HUVpMa z+;C-OAMp~e!IL$wRjv9K&)CfV_=r$URexH)chKjyX1c_2-hyMe-T1w>{h~oi#ZHe* zCJlZLGj|7@2WxH5-p-k!*yMTM7ha69`uRn^s`~>4nra`b?@6spb>Lx*L#;$&POLZ6 z@BnMN)*s3|8uZ&7&#TB^5pZvI;^a%rJI&C{7t1=8NWGvvX%i<%R-kz=*hutGvlM)@RQ6U> zxxVv{`MzMM2{OpSm^xK}Iby^47ri}^TiT7E>J+!;a%@A}1A|xUFn8R3% zQzi#yL8H=}swp_Du@Y_{$_gktqe&$Ly389mcbR>bi_-gq=w5Xc#>V1oUb{^nst&3c^a6?W#;r)ft8gQ*_wKXH!<#zL9Lb=-vq zrFB=P((w;GP`Q-W9XmfKsf*lv$k6AH6^F+$V24He(pa%(wt7cSg^MIw+1t@7jmW7O zvDv{gW>DBR+vUU_t323|_uc2A*kwq`%JB+QTi9zlIhT_Z!5LG7y9;Bbov*a8RmE>C z61~JZoe*JCm%k@KAihk$Fcso*3y)H$=c?@up$YapUYz!grm3!!ts&jJIg%JNF>|gz z{spntuvkQpDHMM4Fp4k_5ljEj|5R@3)F(EjjnpRz{|@g1t4DR7&k3m0|4I@lu~&>` zJ?-}VLLz+cAzHE#uD?^je#)o;YKN1R^3>nL-y`|sK1Kb^A+%OnR0_X+Fl5A?AD?_* zSCV+!#W^HTq47AH#E5|-kA0bzl)J-#?j7?D*IOF4BCC5PG{-LYleZ14d`;es;0XU;&zQQX50B%G38$bnT7BQx)eN zs)e{J!-?aqUwDoVD45HQ9ostBiK%X#4A=G~YIQpJli&*Rb13hhy^;QBK415f$$)aL z%P@*T=7FcI*{*nL;ICE_61P2+7$3r(p2xp7dsV+Zo+IST7by3ZG4CkINLYPHKvmVj zkrf-NLClmc7ir_>-5wbzd>VMI_~rG~QqFLdKYF;r2RwQ-A;}@vtSF&>3>DLMCQo=v zK6nwy1Q@@&rzZRO@O#VUJRjeja^gRR!y`fgUXHv(a0@SOWn|QqWMmlCHPqyl9?O9x zc;lZWrr04#+hwe&T&P7mBNZ(ZzG)$))%m1U{UuJGw#|6k%IJNY(d2jaf;bg7FeNBT z3Al#72-o9;EMi8+l&0jzygF@p_x<*_(B*)}uP61sm{{d(V*|}Dl4G1qDUYHX{(YeG zlf&XhfABJLVBq`>bK#Ou^Pi>VEyECN@7xPFypkI!DB?+8ugCFYyh6Qv#y+?$+>NiQ zDkI4yO`vv{`lV38&eh_=CB(5eP?9t_K&lYcr9sFpHqaL?FDgf?!Y@i&pb39Ti8f!EF}m9L>b^Tu$iprO5)R4 zbQ4}-wtVG_Ng;LA5X43|vcE7#$NGc1Q{)iHFzb1Nz9)gE<1=Y&hr*ltPT=dae^^v= z7+e)!GpjHS{vc%3Jf;)rdet;pDS}UU&x=Hf8g5A2IXY$gzY$01ZL;~J(bA$8u=E+7 zc)bX8a=OmhI6OfU8gNad==(zfo(;oHSwR+Yjr{YrsW=6`g6*uR=Y~LVF(Lm)@hX(? zgfC*cE2+p~F5}SLphi^BVzM9*j0h!JDJ`#=o$MF7T9d~oEo7AsSf_5$w1p%q5-M>7 zRZ2c!yKNGs@o>`dAjo7KP3_m=GNrn5|If}#(l5ipmd=m1m`~B+C!+!sDEtBg z1K)^xC!-@T%x?W z%lU_lG1TBt5OLf7w2| ze}1+kWbj)58pz;P*VNRk7t0;)o~g0Rm?T8}T3+V%+A}#^9|^^qi>_3ckwME6a0(9( z$AFdhA;veen3wGlAsZmi<3QkL-?CbA$S?M8O-`Kcy`!?#WTes3hUN}aOm)2&E z|7`N53=R&icm0jy>gKle`*&D8?N8PGpYe$cnUgb!=7R&*&aSS!=4Sev0*;-H-hUrF z|G~;()R>N^LgWyu&T8?|dN`;2)1tMtbw^j%4fszm@JjUWX~WmA9Y21M@mdY6lO2;r z$$lRhv30qCC-O2PVtIS|bG`e9M)9UE^Z5?eM&o&T_QuxcrrG=#k8~bO91J`v1frz8 zoP~+Blig%%q8wJOQaC;Mrhuo*0L)PYPs+yn-R@T{zx-x3(^|Gk3M6lt74^%Iwt zk#YHV>hdx?+-z^L?NQCg($bD3CI#ocMX7g%g(!$OZ{EBuEsgmZa1ke)>*XeAtfN!s zAz-9Q3aiOjK+?HI<;BNW>3`u_IMdnP&BV=3j4&}bAA3J{+SS!1=zsn&o!eQfg!H27(~ol*Bagcp+}5VHlv3_^ zM7Ib@NH9bY&`HBK&C1x?+Ul5{y%~yu|9nJ9OjLC5cbai~d%N`eMI{pdU#VmC{emRu zBR*{G>`56Jy|Tltt#4(nn}mdf1pQ7QprWECrlnybK2=q<|LTfa+T4r|xIC{por{l; z&;D{hX`K{Zs!{sGhY!wwS5@E%nqHnCtNi4(e?jT#R4c2is0a>D&Pu;C z*ZPJADK)hOVWOyjwV>!tBH4?(LPFFcp4*bn&JPf8U+gaEHv63^&sthr_t)3S-6no1 zeXHv8XH#=?G?l^E_`l`kLQJ$6QM{- zN@DZfD|!E3%GH&JfL=86)29co4SITeu}gJ6euMJRx=NJESF2_Z$D@{(XN>gZ|0?0N z$5?AW9Rhpz_=1>8{^2YaJ3H=O)i*)V1TN-xX6u%=w_~p_cLPg4e(Z)%O>J%8A6g5$ zt>QJGZ?f0gBM{G?J=?C)<@mOi8_4D6@YeJ_R6z4M|ND{>Nqc(^Wr91?-`3aHBagNw z&FAV}))$&YJm{hOe%K_Iy~ryo!$TIQo*uR1{Fkt}n*z6mg=x;u&%M^NUu4>+B_<+7 zL`1Z-w0i!D3kak&Gm-flxaiQSfKdW4C!H725G zV4(BE(^5u?7-CvlJWfu|*T=IxJta@|t~<@R9e*~*g<=xkhWbXdF7GccEd}%0O|%XS z;2C~#&x?l@B0?XzLf-G;##p6E8|shoac-SP=<7Zwf95SjczJo>6%~an3);`s6H7@+ zE$(|oMn#!6@cA5XzpviX*VH71u2k>5gbJ^ZgY5yZ6Ay21NM!fzr%yzhMUR8OeiiZa z^Mm&$Vqh4a$x2VJ)_vtPSC71b9G1?JiHY#iQg&!zn7q87RjF0f{=1@J=nHN6axqgJ zhE+!s?d_=00_>`?U%#fn!^gix5tEdYL-5vAsI{{bUCj5`et+$Wj!t(ni}KX9rUn4m zj&S@?=#>;)29Z!@X0VXkRJ{vch)*>&4*NB*;bQO+LEPrwS|=tbWWw=owFSzlr#5+_ zI!rP}9w#t!<01SGM-*^sh-11q2#{U4oaA4Nrjb$nuU}@XddR(be!RoZbc%3Z8=_mq zrxNpVkNGG7vjB>wt-Bj@VqyYTsSOH{+xx)c^z5v1SUPb%1^$rAepS$TplobxY`V{J z|Gst7MNv@^+oh;kW%`YS)Yq@8Sbc1vU(t*CbT*=t4`K+Lv?Aw#3?itZp`qP(h-Lir)jk31-wb9# zG8oZ&M@J6Kn||WC4J(6#gZkv1C;!ge8ol;W5#Q^aj5!Rykm*zyv{jmSKk(SpVrFJG zxj5eO+HE@7JDN0Rx_dW5m>^1A3Tk<|D~7V(`|q8g@NL(@@-<~9?CP<}$!>k8roz!- z=IrZ^!9f*AAL9*;+2r-B*CaGF(f2fq7WbAq22!Ez#svObX28P1fo8)DT^E{FgyC0D z(}8sEz2jqf4UObSwb&$1iR&@4$RYim?iN_F^2CKESzK)fr9vKvb zn3|q89m$tdR8*Ao@Zj?(I_5a{6K8+{-3A4)KPd3?JDqnNw3S}Jjq&kbVp*aOZ=0KQ zqMCWO&de&Q^z`%)G^jhzmY=1)aO`yr&CaG1KV1x!?}q6^G4Et)Ilg)HkDOh*b$FQY z_3PJ)%E~EQeY?;G?x^L&{#_ehhKaOyc!-WbM@L6C(xIUto(0T&x~KqXA9qwTUt0FR zUiubyla+(xoyY;r`||SC222(f77MZvb(H%?jV8a|5BN0ea##tSJT=ry8D9JBI&WoV z1y$)PXIzyd;d8jIUEDD~I@&&3sO+*c!}mtm14px1HPz+!$7eM-y}iANATGl%tur$; zS65f{9$OSJpW2`{si~uoPwDLM+K8Mn zafsSBVqS z7bi>{9C&$od06=PVJRu36J>g#`^()j`uh5gXU3LyMM3wJfQV}HJs~0@YF&tli|cCk zzgS#d#ZXaE0Y&-#U+`8Lxhl*4`pit4hHn4!jpA)L*vZis zTOV7DG6s{AlLgh()P`DHgW~*i{SL5SZ2q`cQC(gAbS+2ZMMdoK!;|IB&A#!83D5NA zl5c!#`p?aCBmxOYNlA|%W+WvA=gCBjR!a_X7@yyhU}ukE+aZ<}L2fjO%R|z#@^Vv4 z%fj!OE}*C3lccmXxTs3_Zp-EIO?w9iZs*0;J8l>&YirAM4Q^DtR(Jyg14c1BuCA`m zr+cQS7Z;y*{8v|3>jN%*VyqWo$yo2*3x>f2oh?1$@9u)iTT=lkJ26}*5>5(#@L7?O zSTJqP`d@Q?|Nh;^eE^=L^TsHPsLvr*7QaIXXpMmj5J&049&GHZd)w2zsTE`HWdANN zE5U3bf|{C|9!ukgFbdz<-{1GTzC1CtwnjRGYGK#rrj*>=1gM3j;@kk~fB#%iK?lq69~t@dFL-#jmMTY$knQKbvin_?U@?oRZ*nuvF(G3g@3p!tbBr3 z9Q(jkS`dY-qbr7-!di$lEu!I{;nzC-j2|!6Sxz$!*wEeDcKWdX_ss9~^mK8hH>ISc z#H1xH=eKc_54mz0m*smVmY%Ot@GHMhOkg0KX(w0nuP2QI-!pIJf?AzxO{+D5_b8i+ z2di@Dak^yFYer!~K0ZF^-9hp31atHAy^I=%yFVGg3NXo3*Q`qf{G+OOz>v$fdGhXrylWcYupHBVL2|rxJE&MM^TzV*KQnl=qEH zdXrho$}H`uL_9eHPM0G1TZAS*8e4z%b8~Zpr>dF25~(WrLQCDwar! zn1G+n{*?~1{DLAP;Iyj9%0aerxqEoH{FxKlo~lFx`Shu-&S?b&`Dkt$8)&99oN#h* z%xE2g$w|z}h{7bKuRb>zRi<_b14TMfVc2hVdU3K_yzq#Kjx1P`aT#CC=a3cbDhR5T zZ_327SuxEyIrQMbQ4r+hwuhZc&@S^~ss9cJ%*E-a|7epSAu z+=z0JXdh;?RjlXX;Za{--?%TpEGkM1S_FYa3TDuRekfz-qmfclM)dS3c7FRNZEVc2 zv9WP_JnK|x(M!TZkmti`uf(K;5^mZNZVH1mT_R9i{PIvU!yGA*jMT!od|e~%gD$eH!4U1 zhpTRF9i0LwWM&2S6e193KMN^Zh~A5D=+7y4)x-d zYk?)bu|7RL-J9Ko3u1%C>G|^+dy+8lF^falA`UqLI?N=dP%k`BSDr;jMPWDpJLuPO z4L#odiG(WfM96?y^z`-Rzas-0(^*P<`Q{BRMW=xOx%(j)?-B0Ntuyd-gG15dKYkb~ zHD5+Ye|~t{3&O^Lspo z;WYd6e(2-= zaGL|s#ivkdbFK{N3;0*@Lw`~ID8eFQ`G_3@+L^K&0)DU5gSV1Tue z2N98l9a!f$PxJfA>AtS6u1Qbgt)8Kwa7ji<080+PnSc$wl7G+X3qp^OK^z@HMNQqy ziF&IkhY(?FYkRu=dH9p{Fn#06f-g@u1}3KYWQAd5LP9sN8P?nb<(I~&4ok@2F=KF; zEAG$68l;hOjp~1Koa$=;_2+W+&wKC8&u^~{vkWyC2Ge>l z46T*lzmbMNS%ZkJpsI=lBzZSHT;1%*>gtEceGdxXp~}#~fzxU*GYr1l0aXg#aKpW} ze{itte#^g*l@*IOf-e8rJom?jhIEb#jo4t4Y;0^yz=!_WcqPd}VScdETOW8WZZ-5K zir0FGHT7-m@S6F~ObtgX<^LdNWz7EvyCJ77zth5;DK6bTay|j~b@i~?$$KdpY2C{; zwkS9A|F*6D4-M>#rK|!IyRc8y=y8o*S$wXfK^v47Y1Wi9wI5*_~LU8;dQptB% zSZ){@8L{5K-whb*ZERrx%eL+k`70Iqsf#iDdS~?$ZwG>B@ zk))pC;Rx^@IilVnXqW^hN1Nk_Aid94rr?ZD*9#Id{YH&z?Wyzg^A~~IfmeHh%ZRq3reXQc8aNDamYgly_OaeQ!=u9SIJR~3kP=_#q+rSylNlr=8lbiuNmKCeBp@{tLZK0Up*Fp;l znDPq>T=sv-JvA39f8syDutYR8eV!Q}7>b8c1TtD$WHAQX)j>+oD3AZl;{x9@H#Y}h=0W4@ ze>`nn?{mb)Wl$dkW-JJ{=&6Bmz!{5|C_SKK=j|!(%~*%l|G436(Kk)lU^@WUG))X6 zu?{?f_Mbl)Qtqg1x(6o!Kz%6{iqZD{J946YA053N+9Q?BNrKSd@}rK5io(LfLq~u| z@r>4MMz^!uN}Kqm{_07AeC19ZYz&JU0jzO#7-={FV7EGeFdAOb6{}{4fD!{k6b<}v z@_-u54iK_w+x~`>^*YjULWX#7+rKu(ic2ag9FNXGn}6~>aRe~f=MP=+HX9p`#MLR& zuV23wye?j)r7?TWEG9yV85glC|kgg}IQtz0? zYV34CR-qvd4h}4=3SV+OefqTC?~KQDdn)hK9(I`YM2kW!Ri5*;wx_7q)xUD3r-zh=ELxOk!-|saWAF);!_&bA1PDMW;r=W0!T3c~x5cnv>1{h^SU*DtD*|lMb>lK*pLI|LI%k{Cbcw9j2F2I5{ zY;W5)I2`=_E9CF*ABJ`s9TQ_|UuQpECEqP8C+Bi}e9Tk3{P%39D3?wmz+gjC9GjY& zx@_leu3x^^>`*(*vwA2jUXjbwo+H0?B_t0DjweR$xXZ?BBK9(+3xvs zB(XAwVFg;OOXB)W?Kp>dk&~B~6#5vzQdvbstO|pM_IPSx_ma^zF52!T@ccYVT!0kR zwY9_7*KGh4)XoqELF1Y`48a7TBP;@fZ!of_xnaEQJ`9!yHE+`U zRrWUV)#)JwK>92IzzjJCe~X<9ZxGn0xsjpW+ph+c8RNfLO~%R zpyWn(hvXS!@QI-zK2n>|@ZrE?i2%q9uj-tE%_)#|T*s7G zSa<{IQ-+6GzG*}ckUf{B_8TCRKD8>rkU0bz(d!A%Mo~pY&dTZzvck^iVdCmtiw9mc zj&5DR+~8T30<{NeFa`$Ca&SflHE=WZ7cX99v`PUzDC`a`q7rmwgr^){Qo;&|w{3Kk z1f)twG&#G8tt~bK0|Tg{CwFg;?D{?A(|@{tr?k`@Y^8lr5_+26vuDyk&U5{bslmk} zJ!7qdvd?PS`mq3ZMn;Ap1QkKy4(>4AAb(_KV+#RMh#Y7N~KEjTWCqNU1Hd{E|wrdIG?-nFG zk{w(TMXp=QAYGU~TNVomlvclx)Clf}-3&n=C*0*HyGgE$Wsm|HJKtid3-*2j;)(eB zVz*X!qYtk6DL<(uh3#xA?dc_#UjgK)~gZ4g$$O?CtF>3_NoKuY?wSw#v2f4U&%}VBUr$5BxJcB+uZE zlD&QG3^|I+#jyhfn*E)q5dVq#ohEvty{eo~W!G8U*qDAk0y%M#o|#vw;_Pi0*0R@5 zip_QaNpNDUA$A@e9Ys8B!W-A!Qr*NXI5 z5RBv%7Z;JBs@)8gokBcq# z=++=i7uPZGZ=Ic=COLbR44*y?1C>AvG)WfrJ?IJ~667#$ru9ER3Y1cUk#Dmd3USbYCr7hiO&-!ZSvqfG&yf=NRfpPb4F@;36B4P3e z_iMHo_j?OSfXQJT4R5muP-6i1-FotC=3`kn>Hn0T+govXbAE1a#zNEv8vs!xKw1#U zAgl&IkO&J4n*lth5^$s)JWx6miC9-weDvt~6X)E+GE<-&uGZ$TnKAaRnSP}H1}l!t z_(0c~+S|vzealEiMYVXkzYH?+C4}6NT)f+Ryk@Cr@aNmNZ#b0GXBYNg-f#Pi{s+ph ze#P8h!MIjpDA*>rfsY@j^Gn!4`CXmahxVAUq{#Sq$B|euK0b0una1e+%dafU!4VM( zS+SUXNDT;e0-C5wV;D|0(9_fFezw8~##*A5wElwrot)9MgRf-Ad3I-$4UkSk@zb{> z+|qf8+4|Fbw%AZ5;jqp~5Qe00aAD9)?J4RZ#ee`=n?-Gtw!8A^8!RB3DC>cjC{O|J zy23-en)ewI%=jNtQ&Z>K)MlDFYYcrAd~RA;|GUWg8>A>}oN?q=sXIXbd~jeuYx9|o zg(#qUjxQ~o7Y}oX6+l}Boc*R;#pizTpcQ0orQ^IX&K%Ro?wj?^&2}*90*-SwBlI@G zlC3itFyIWGR{x%DZ~XlJ{Zm)PFKS*ZWT}+-!yqxWvI+;8zy!%HAiZ<}r<_L^Tv6)) z;Mp5<%HO}o2H$WTsMP827Mk4Y3C$#LE&_L>W*EF@-B^?ngj+H52;rZeU8`REziyDK zSx)@zGUN80vRA@O$oHQCao~usw=>fs%PT3tLdIlKq<3{2W1E}B8=IOc&AOr|DH3Or z^8C+tVgZDpN)|-=$|))-nT8&~IQ>lz%&t2=sq7~?8CmP(By=Jri3c{%pSQQRB0gIU zBGWyXY){PylN4V0-`FS$ z=&<2W?<#~S5wK*4MbJ%;KmEQ%hp;s_XF8$UK)(Z|S}@?BAfPX3M8>}OE^`n?@8`~145-7Rs~Fq^MM!yw2`EDRZSp#0x9(TI9NS-w1LxLD>(`+p*uzC19O~v z>?2Sk&WGzypq&B>sk0GVukbL4e&7 zDP#{EA0KxC9kT7@f3OlYw+zln=)Z&ptUG5NjWK*&+t|2g{uLU&3+$qRf(s2fxf^Mz zsa=*97S1r=c*0^3&cJ-uU|!Ti?WR#k3wdn5nlqC{pIrAHZwUX@AIC&Q^qZ&%w_bnlzHvr{$veHWm zzb5h~XqgKGc-4yMpSj+`;$k}sh2srkkoW~D>9O-i)fT{=n zCZH#`Ii@D@8{sTUpP*m!d|bJIu-OqX8rZ?URCfIzR|miQxBHtxT{mN#Z7GL_KuFFU%x`IN$>R36J)u~=0NDX+?~)3`C!%@lYzQ= z5KO6G9fT4u8ye1TI-miSR1-f#2k0UTl0W7bIy}{-)zxrdP$1TCF*Cn=!jlikwRYgY zgzE(zJcqWQKU)l^RAZuhF-^TB$;jLMfu{f6%GKU-*A_Ml{E;CDZr?J zwiVpkDtVrKwR3R-Yug3^lD4)sPB}FtG!6K~+uOURr^kdG@9B|uz{QTh)XWUO2>t&f zPAg@brU85O#d8OTle2u%M*{3LFiceB`@_i};Dk_5WgjOeCqG-JfvA5`79{P1;dIT_ z0U@JjUyB5I#j%l*rNg5m@=PHxMA6j1Q(tDIqAoT}7(_>ZDJE0{(5Kd6sHzbzT zRA)36`34vTfSWEr%VG|5w&}PBpf9y8kFp>Z{!2nD==^pbeZJ`)MEi8d ze|y>FN<_JE^q{YQ&UfLVN- zgQHAt_Lc}QxFE&Hk2_(eR{9)0=ZVBY-k`KJDhLOy+NM-SM9{>c$anj#nETDGl*WE} z2h8+Nw+jmkky&+6_>TIA9)UoJ5C(E37?>2|JHci?%{i!MO3utg2GllocF2hGez~zE ztGuHl7aUqZgRY4IW%S&m!7}7+MgXRajt(W@W;*S?Lf$5nR;Y=j^z=wTx9`hZV?Tf9 zg)?;faPFzSyE{U7Tp5Wjb&UOQKt>4MGI6o)AkQ!pMy@m?Q7gOx4tS2-6{duO&;>(L zVcbFh$GD(d|N41-CBW}EhXogvYP7YSAR!N7K13i$u*?%c3K7dPY+J8?r`&L6NsDB9 zKI29p#OGdz>%?#da}N-U`TvffjK5CbkgjIvX;N$47xg{HLxycY!;t#qr#kjpA4binx#P(j}(Clx?FHeVj=`~4jhu%MOx zt=>lWD{c*L*6JRdestTvJo#x3TFJpjg~aa$2B8Z4MUE7*2z+JTWQ`wCU3WT&9**4= zW&rTa#YF()8-(1QB9$x*G&D3GypdaQ!b$;-c!1Ryfx|YB-v|=J?_=s9Vm?P6jg_h< mz*#{?4F7+Q>Z)U3W7a&J7~{r%^a73}Bb4M+WhZ=`InF5*4JoOBw}46e*=kKoIHfkX8X{P(q{|q)Qs4yQKuAL-IcR zy!RX9y?=h5;~8xB+I!74=M%qpPUsU=1$-PT90US^ucRpZ6oEjwgr8qyVZeVYCqg<9 z2)rt{XIc(V4V~%j>}|~~txf42Ts2M6!AFF8ELX{X%06@@;z_7&+*yVhs7@16bgeKpr{w7K`|&CjNJO@O#>`N(!xMq2D8N6&IhKJu3K6AY-{|fPCHBR)`FDakr z%Ipzd)K4q|6RmP9DyKHTl@-S6T2@qyC2fxUsfmB(zF8k7aZcs>NnL^3Gn~64k%yN@ zv(>t6fO}0ZEUB=xdTi;U9fiD4r~LJBp-fI8zNgcqW7X`*#5+#Xo*;B|t1+92a>pTG z<(y=pSH!k>s|UpV_(?vAkW{pix{oh{=-O;m*Gk1jCULRli9|w zq>BJOyY(x&&Ktph1%F??pCGoSd65)FDsRkL(uvc=q$u6PjzpE+b*x7?@7i0Tz zmr2*u63gG|$1IL1#Co>xEyZV)t+zQs+2vyE$G8$L{o)x-U5|cjO^G?0$I5EkY%m{% z%N+#8a17DZX8nkG?UY#5y;1u+kWH|7LMcd@E{0I}$u}#`N>Mp8*dy281$9oGsME5v zJ%ytDto&)_lG20>k#X$4NR^n9$$Y1psfBJKb?uFx*{q7M>m0R2+rKbUJEm&9NZuB} zAtTpVzi;>RJ8z$k-Z#RT$+Fuiq77&2{oRSfHoA_0DtCky#Zfezum3iC%>j1O}-^z zEqQM7IXeX{iFGSM)O0i;k%N_nbEf))iz?izyf{C1iXb34{Rz>fal^uqCjseA@5Ta=hkH2xxJ|?lI~fTa zLMRWawFw>tP1z;8Ju&3_W-VA>^O8LK>0{I;4z!es?l-IWbK8BTH~+P;QbeMLtLuze z2=t@I))hdjCGoF%JLgb=5Fqwd_r%IztiD{1=Y*&qhCx z$0Yr{?R9E0kK?90Ds;oGtVWZk-VcxT68+waE2~v*A#rN6>ukA(yccOt$1OVok4@r0 zr_D!A-IT#<8JS(5YA)8hox0a*x+#lp zk}RUiD*ra4<0Myh#+J4(0G(+HIN8Jj^g@_vpl_;YaWzeoHGX4X>BxbHNo z;@rG-qr~xTEVIpBb*ktr%v!-g0j7-4c;_ey)N6LXa#?)er#~t}JU1cp>w0lnzlQn4 zce{M)x$R;snN!bZQqItyOhS8cRC!5b+Q4FiR(6#WC#?R08Cd4w>I zPrZf>9fi5=4JrFWvF0zoUP^fk{bX4D5`a#bcJEeZWfjRVar-S#VbNPGA~<6+H=jy( zhO3aF2OG#cz46b$Hnclw`FdhF)!uJ8rL4Ijox~k-mxuT}SMi;9AAPTG;5X&2-!~&; z@ZH&f0 z+N%zfBvuD69-@0K&{j|&CK^<0R0a5MN_Gt8VDsIKy20~mCbJLIUo?j?(}5uJ)~|g3 zvUFKmx6eGC*t?jxb+kIzoR7(g2ks4171l2l7I(d?_?6M+O3bM;{qpFS@-zRDYBtf^ z(Woi|?Kb{7{v5 z=V-4hcmoZ?*pzXd%ksve?q^wp;`Nn3@&nYU%)QUhc;w4pVcxe@u<6-)Ll-GiPcU8B zv_?KdeVM0CnkE_QT#@wExP~$64!kadb>Hu`vVS5* zI4isfS(c|9PGlkQ#4P61QN=x)N5isj$mBfn5;R`g3qD|7%=%Hyjq$-7VKGF9jZQ_( zLL&c*mV_{Itx(yAC|+NW!n8=b{yOsXrhMRA{}SKCR@aA12D{24CB*@e{

FU+lI; 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 def factorial(n): ... if n <= 1: - ... return 1 # 0! == 1 and 1! == 1 + ... return 1 ... else: ... return n * factorial(n - 1) ... @@ -63,20 +63,54 @@ |--> 2 * factorial(1) |--> 1 - 5 * (4 * (3 * (2 * 1))) + 120 = 5 * (4 * (3 * (2 * 1))) -**توضیح:** هنگامی factorial(5) فراخوانی می‌شود (``n == 5``)، شرط ``1 => n`` رد و بخش +**توضیح:** هنگامی ``factorial(5)`` فراخوانی می‌شود (``n == 5``)، شرط ``1 => n`` رد و بخش ``else`` اجرا می‌شود. در این مرحله نمونه دیگری از تابع با آرگومان ``4`` فراخوانی‌ می‌شود و اجرای ``factorial(5)`` منتظر پایان اجرای ``factorial(4)`` و دریافت نتیجه آن می‌ماند. به همین ترتیب چندین نمونه از یک تابع اجرا می‌شوند که منتظر دریافت نتیجه از نمونه بعد از خود هستند. در نهایت شرط ``1 => n`` برقرار می‌شود و نمونه ``factorial(1)`` نتیجه خود را به ``factorial(2)`` برمی‌گرداند. به همین ترتیب نتایج بازگشت داده می‌شوند تا به نمونه نخست اجرا شده یعنی ``factorial(5)`` برسد و اجرای مورد نظر کاربر به پایان برسد. -**پیاده‌سازی شیوه بازگشتی شاید به نظر هیجان‌انگیز باشد اما نباید فراموش کرد که میزان حافظه (Memory) زیادی مصرف می‌کند، اجرای آن زمان‌بر خواهد بود، درک جریان اجرای آن اغلب سخت است و اشکال‌زدایی (debug) آن ساده نخواهد بود!** +مدیریت توالی تابع (شیوه بازگشتی) در حافظه با استفاده از ساختمان داده پشته (Stack) [`ویکی‌پدیا `__] انجام می‌شود. هر تابع بازگشتی شامل دو بخش مهم است: * یک عبارت حاوی فراخوانی خود تابع -* یک شرط برای انتخاب بین بازگشت (فراخوانی مجدد) و پایان +* یک شرط برای انتخاب بین فراخوانی مجدد و پایان + +**پیاده‌سازی شیوه بازگشتی شاید به نظر هیجان‌انگیز باشد اما نباید فراموش کرد که میزان حافظه (Memory) زیادی مصرف می‌کند، اجرای آن زمان‌بر خواهد بود، درک جریان اجرای آن اغلب سخت است و اشکال‌زدایی (debug) آن ساده نخواهد بود!** + +تنظیم عمق بازگشتی +~~~~~~~~~~~~~~~~~~~~ + +در زبان برنامه‌نویسی پایتون در عمق پیاده‌سازی توابع بازگشتی (تعداد نمونه‌های فراخوانی شده از تابع و موجود در پشته) یک محدودیت قابل تنظیم وجود دارد. تابع ``()getrecursionlimit`` از ماژول ``sys`` این مقدار را برمی‌گرداند [`اسناد پایتون `__]. این مقدار به صورت پیش‌فرض برابر با ``1000`` می‌باشد که با استفاده از تابع ``(limit)setrecursionlimit`` از ماژول ``sys`` می‌توان آن را تغییر داد [`اسناد پایتون `__]:: + + >>> import sys + + >>> sys.getrecursionlimit() + 1000 + + >>> sys.setrecursionlimit(50) + + >>> sys.getrecursionlimit() + 50 + +با رد شدن از محدودیت عمق توابع بازگشتی یک استثنا ``RecursionError`` گزارش خواهد شد:: + + + >>> factorial(9) + 362880 -در مورد مثال محاسبه فاکتوریل، چنانچه شرط ``1 => n`` برقرار شود، عملیات به انتها می‌رسد. + >>> sys.setrecursionlimit(10) + >>> factorial(9) + Traceback (most recent call last): + File "", line 1, in + File "", line 5, in factorial + File "", line 5, in factorial + File "", line 5, in factorial + [Previous line repeated 5 more times] + File "", line 2, in factorial + RecursionError: maximum recursion depth exceeded in comparison +.. tip:: + علاوه بر این محدودیت، یک محدودیت جدی‌تر دیگری نیز وجود دارد و آن هم میزان فضایی است که توسط سیستم عامل برای پشته در نظر گرفته شده است. با رد شدن از این مقدار فضا، برنامه با خطای زمان اجرا مواجه می‌گردد (``RuntimeError``). From 45ee4b9d2c58a151b3a93e98672b049903323f7b Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sun, 27 Oct 2019 14:01:12 +0330 Subject: [PATCH 055/316] l14: write generators and recursive --- lessons/l14.rst | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ preface.rst | 8 ++++++ 2 files changed, 73 insertions(+) diff --git a/lessons/l14.rst b/lessons/l14.rst index 4115f0c..7653ff9 100644 --- a/lessons/l14.rst +++ b/lessons/l14.rst @@ -112,6 +112,71 @@ .. tip:: علاوه بر این محدودیت، یک محدودیت جدی‌تر دیگری نیز وجود دارد و آن هم میزان فضایی است که توسط سیستم عامل برای پشته در نظر گرفته شده است. با رد شدن از این مقدار فضا، برنامه با خطای زمان اجرا مواجه می‌گردد (``RuntimeError``). +تابع Generator بازگشتی +~~~~~~~~~~~~~~~~~~~~~~ + +در پیاده‌سازی توابع Generator و Coroutine نیز می‌توان شیوه بازگشتی را در نظر گرفت، در این صورت ممکن است نتایج کمی برخلاف انتظار شما باشد. نمونه کد زیر یک شی لیست تو در تو را دریافت و تک تک اعضای درون هر لیست را چاپ می‌کند:: + + >>> def flatten(lists): + ... for sub in lists: + ... if isinstance(sub,list): + ... flatten(sub) + ... else: + ... print(sub) + ... + >>> items = [[1,2,3],[4,5,[5,6]],[7,8,9]] + >>> flatten(items) + 1 + 2 + 3 + 4 + 5 + 5 + 6 + 7 + 8 + 9 + >>> + +اکنون برای تبدیل تابع ``flatten`` به یک Generator کافی است به جای ``print`` از ``yield`` استفاده کنیم:: + + >>> def genflatten(lists): + ... for sub in lists: + ... if isinstance(sub,list): + ... genflatten(sub) + ... else: + ... yield sub + ... + >>> items = [[1,2,3],[4,5,[5,6]],[7,8,9]] + + >>> genflatten(items) + + + >>> list(genflatten(items)) + [] + + +اتفاقی نیفتاد! و خروجی یک لیست خالی است. از درس پیش به خاطر داریم، فراخوانی تابع ``genflatten`` (که در واقع یک تابع Generator است) تنها باعث ایجاد یک شی Generator می‌شود و می‌بایست در نقطه‌ای که تابع خودش را فراخوانی می‌کند نیز مقدمات پردازش خروجی یک شی Generator را فراهم کنیم. اکنون با اصلاح کد بالا:: + + >>> def genflatten(lists): + ... for sub in lists: + ... if isinstance(sub,list): + ... for item in genflatten(sub): + ... yield item + ... else: + ... yield sub + ... + >>> items = [[1,2,3],[4,5,[5,6]],[7,8,9]] + + >>> genflatten(items) + + + >>> list(genflatten(items)) + [1, 2, 3, 4, 5, 5, 6, 7, 8, 9] + + + + diff --git a/preface.rst b/preface.rst index 26249b2..f76cbf0 100644 --- a/preface.rst +++ b/preface.rst @@ -3,6 +3,14 @@ آنچه در این کتاب نوشته می‌شود حاصل یادگیری‌های شخصی از منابع مختلف در دسترس مرتبط با آموزش پایتون می‌باشد؛ یک یادداشت شخصی ولی منسجم! که سعی می‌شود منطبق با مستندات اصلی زبان برنامه‌نویسی پایتون باشد. + +| + +**چرا پایتون؟!** + +همانند تمام زبان‌های برنامه‌نویسی موجود، ماهیت پایتون چیزی بیشتر از یک زبان برنامه‌نویسی نیست. ولی از نظر من پایتون بیشتر از آنکه زبانی برای برنامه‌نویسی باشد، زبانی برای برنامه‌نویس است. + + ---- زیربنا: From 7ba97e94ea72820f344ac66feb21aeff50b6ca0f Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 28 Oct 2019 00:49:29 +0330 Subject: [PATCH 056/316] complete recursive --- _static/l14-fibonacci-relation.png | Bin 0 -> 2523 bytes lessons/l14.rst | 108 ++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 _static/l14-fibonacci-relation.png diff --git a/_static/l14-fibonacci-relation.png b/_static/l14-fibonacci-relation.png new file mode 100644 index 0000000000000000000000000000000000000000..de989f11b9de26241acc0ef85860653f5da5834e GIT binary patch literal 2523 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 XF=;t})P&rEKO?lo-i23UcOd>B49JF= literal 0 HcmV?d00001 diff --git a/lessons/l14.rst b/lessons/l14.rst index 7653ff9..de20bd2 100644 --- a/lessons/l14.rst +++ b/lessons/l14.rst @@ -74,7 +74,48 @@ * یک عبارت حاوی فراخوانی خود تابع * یک شرط برای انتخاب بین فراخوانی مجدد و پایان -**پیاده‌سازی شیوه بازگشتی شاید به نظر هیجان‌انگیز باشد اما نباید فراموش کرد که میزان حافظه (Memory) زیادی مصرف می‌کند، اجرای آن زمان‌بر خواهد بود، درک جریان اجرای آن اغلب سخت است و اشکال‌زدایی (debug) آن ساده نخواهد بود!** +.. note:: + پیاده‌سازی شیوه بازگشتی شاید به نظر هیجان‌انگیز باشد اما نباید فراموش کرد که میزان حافظه (Memory) زیادی مصرف می‌کند، اجرای آن زمان‌بر خواهد بود، درک جریان اجرای آن اغلب سخت است و اشکال‌زدایی (debug) آن ساده نخواهد بود! + + +استفاده از decorator +~~~~~~~~~~~~~~~~~~~~~ + +هنگام استفاده از decorator بر روی توابع بازگشتی باید به این نکته توجه داشته باشید که این decorator بر روی تمامی نمونه‌های فراخوانی شده از تابع اعمال خواهد شد و اینکه تنها یک نمونه از decorator ایجاد می‌شود و تمام نمونه‌‌های تابع به همان یک نمونه ارسال می‌شوند:: + + >>> def logger(func): + ... print('Decorator is created!') + ... def func_wrapper(number): + ... print(f'New factorial call with parameter: {number}') + ... result = func(number) + ... print (f'factorial({number}) ==> {result}') + ... return result + ... return func_wrapper + ... + >>> @logger + ... def factorial(n): + ... if n <= 1: + ... return 1 + ... else: + ... return n * factorial(n - 1) + ... + >>> + >>> factorial(5) + Decorator is created! + New factorial call with parameter: 5 + New factorial call with parameter: 4 + New factorial call with parameter: 3 + New factorial call with parameter: 2 + New factorial call with parameter: 1 + factorial(1) ==> 1 + factorial(2) ==> 2 + factorial(3) ==> 6 + factorial(4) ==> 24 + factorial(5) ==> 120 + 120 + >>> + +*به خروجی نمونه کد بالا حتما توجه نمایید!.* تنظیم عمق بازگشتی ~~~~~~~~~~~~~~~~~~~~ @@ -175,6 +216,71 @@ [1, 2, 3, 4, 5, 5, 6, 7, 8, 9] +Memoization +~~~~~~~~~~~~~ + +**Memoization** یا یادآوری، یک تکنیک برای نگهداری از نتایج به دست آمده به منظور جلوگیری از تکرار محاسبات است [`ویکی‌پدیا `__]. این تکنیک را می‌توان در زبان برنامه‌نویسی پایتون با استفاده از **decorator** پیاده‌سازی کرد. + +برای توضیح این بخش اجازه دهید یک مثال بازگشتی دیگر را بررسی کنیم. محاسبه مقدار فیبوناچی [`ویکی‌پدیا `__] یک عدد مشخص: + +.. image:: /_static/l14-fibonacci-relation.png + :align: center + +:: + + >>> def fibonacci(n): + ... if n <= 1: + ... return n + ... else: + ... return fibonacci(n-1) + fibonacci(n-2) + ... + >>> for number in range(10): + ... print(fibonacci(number)) + ... + 0 + 1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + 34 + + +در این مثال ما از عدد ``9`` جلوتر نرفتیم چرا که محاسبه برای اعداد بزرگتری به مانند ``50`` واقعا زمان‌بر خواهد بود و این فرصتی است تا ما کارایی تکنیک Memoization را محک بزنیم. اکنون تابع بازگشتی فیبوناچی خود را با استفاده از تکنیک Memoization و یک Decorator بهینه‌سازی می‌کنیم:: + + >>> def memoize_fibonacci(func): + ... memory = {} + ... def func_wrapper(number): + ... if number not in memory: + ... memory[number] = func(number) + ... return memory[number] + ... return func_wrapper + ... + >>> @memoize_fibonacci + ... def fibonacci(n): + ... if n <= 1: + ... return n + ... else: + ... return fibonacci(n-1) + fibonacci(n-2) + ... + >>> + +حالا مقدار ``50`` که هیچ، مقدار فیبوناچی برای عدد ``500`` را محاسبه کنید (``(500)fibonacci``). تفاوت در زمان اجرا را خودتان متوجه خواهید شد! + + +به کمک Decorator در این مثال (``memoize_fibonacci``) نتایج حاصل از فراخوانی هر نمونه تابع در جایی ذخیره می‌شود (شی دیکشنری ``memory``) و پیش از فراخوانی مجدد یک نمونه جدید از تابع بررسی می‌شود که آیا قبلا این مقدار محاسبه شده است یا خیر. در صورت وجود جواب از تکرار فراخوانی تابع صرف نظر و مقدار از پیش موجود به عنوان نتیجه برگردانده می‌شود. بنابراین بدیهی است که با جلوگیری از ایجاد نمونه توابع جدید و محاسبات تکراری، سرعت اجرا افزایش یابد. + + + + + + + + + From 0336b2e9732d198195dd1da42d079160081e9c4f Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 28 Oct 2019 22:34:34 +0330 Subject: [PATCH 057/316] write Function Attributes --- lessons/l14.rst | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/lessons/l14.rst b/lessons/l14.rst index de20bd2..e8b19e2 100644 --- a/lessons/l14.rst +++ b/lessons/l14.rst @@ -274,6 +274,104 @@ Memoization به کمک Decorator در این مثال (``memoize_fibonacci``) نتایج حاصل از فراخوانی هر نمونه تابع در جایی ذخیره می‌شود (شی دیکشنری ``memory``) و پیش از فراخوانی مجدد یک نمونه جدید از تابع بررسی می‌شود که آیا قبلا این مقدار محاسبه شده است یا خیر. در صورت وجود جواب از تکرار فراخوانی تابع صرف نظر و مقدار از پیش موجود به عنوان نتیجه برگردانده می‌شود. بنابراین بدیهی است که با جلوگیری از ایجاد نمونه توابع جدید و محاسبات تکراری، سرعت اجرا افزایش یابد. +Function Attributes +--------------------- + +از دروس پیش مشاهده کردیم که اشیا در پایتون بر حسب نوع خود شامل یک سری صفات یا ویژگی‌های (Attributes) پیش‌فرض هستند؛ برای مثال صفت ``__name__`` که دربردارنده نام تابع است [`اسناد پایتون `__]. + +علاوه بر این؛‌ توابع در پایتون می‌توانند صفات دلخواه کاربر را نیز دریافت کنند که به این صورت می‌توان یک سری اطلاعات اضافی را به توابع پیوست کرد [`PEP 232 `__]. به نمونه کد پایین توجه نمایید:: + + >>> def foo(): + ... pass + ... + >>> foo.is_done = True + >>> + >>> if foo.is_done: + ... print('DONE!') + ... + DONE! + >>> + +همانطور که قابل مشاهده است با استفاده از سینتکس زیر می‌توان یک Attribute به تابع اضافه کرد:: + + function_name.attribute_name = attribute_value + +همچنین برای این منظور می‌توان از تابع آماده ``(setattr(object, name, value`` استفاده کرد [`اسناد پایتون `__]. این تابع سه آرگومان دریافت می‌کند؛ شی ای که می‌خواهید یک Attribute به آن اضافه کنید (در اینجا تابع)، نام (از نوع رشته - string) و مقدار Attribute مورد نظر:: + + >>> setattr(foo, 'name', 'Saeid') + >>> setattr(foo, 'age', 32) + >>> + >>> foo.name + 'Saeid' + >>> foo.age + 32 + +این صفات در قالب یک شی دیکشنری ذخیره می‌شوند که با استفاده از صفت ``__dict__`` در دسترس هستند [`اسناد پایتون `__]:: + + >>> foo.__dict__ + {'is_done': True, 'name': 'Saeid', 'age': 32} + +برای دریافت مقدار یک Attribute مشخص می‌توانید از تابع آماده ``([getattr(object, name[, default`` نیز استفاده کرد [`اسناد پایتون `__]. این تابع دو پارامتر اجباری (``object`` و ``name``) و یک پارامتر اختیاری (``default``) دارد. در صورتی که شی مورد نظر (در اینجا تابع) فاقد صفت مورد نظر باشد مقدار default (در صورت ارسال) برگردانده خواهد شد:: + + >>> getattr(foo, 'is_done') + True + >>> getattr(foo, 'is_publish', False) + False + +:: + + >>> getattr(foo, 'is_publish') + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'function' object has no attribute 'is_publish' + + >>> foo.is_publish + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'function' object has no attribute 'is_publish' + +در صورت تلاش برای دریافت صفتی که برای تابع مورد نظر تعریف نشده باشد یک استثنای ``AttributeError`` گزارش خواهد شد. البته همانطور که بیان شد در صورت استفاده از تابع ``getattr`` و تنظیم پارامتر ``default`` این اتفاق رخ نخواهد داد. همچنین برای جلوگیری از بروز این استثنا می‌توان پیش از استفاده از صفت، وجود آن را با استفاده از تابع آماده ``(hasattr(object, name`` بررسی کرد [`اسناد پایتون `__]:: + + >>> if hasattr(foo, 'is_publish'): + ... print(foo.is_publish) + ... else: + ... print(f"{foo.__name__!r} has no attribute 'is_publish'") + ... + 'foo' has no attribute 'is_publish' + >>> + +برای **حذف** یک Attribute نیز می‌توان از تابع آماده ``(delattr(object, name`` استفاده کرد [`اسناد پایتون `__]:: + + >>> delattr(foo, 'age') + >>> + >>> foo.age + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'function' object has no attribute 'age' + +و یا از دستور ``del`` :: + + >>> del foo.is_done + >>> + >>> foo.is_done + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'function' object has no attribute 'is_done' + >>> + +.. note:: + در انتهای این بخش باید خاطر نشان کرد که در صورت تعریف Attribute برای توابع خود و استفاده از decorator، همانطور که در درس پیش نیز توضیح داده شد استفاده از ``functools.wraps@`` فراموش نشود [`درس سیزدهم `__]. + + + + + + + + + + + From b25ed1c11bc79e8e0a47020b7a83e513cd7a6b21 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 28 Oct 2019 22:41:09 +0330 Subject: [PATCH 058/316] fix l13 --- lessons/l13.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lessons/l13.rst b/lessons/l13.rst index 68c502e..3f5ef32 100644 --- a/lessons/l13.rst +++ b/lessons/l13.rst @@ -313,7 +313,7 @@ Decorator در این مثال از تابع ``perf_counter`` [`اسناد پایتون `__] برای محاسبه فواصل زمانی (time intervals) استفاده شده که تنها از نسخه 3.3 به بعد در دسترس می‌باشد [`اطلاعات تکمیلی `__]. -چنانچه درک کد دستور ``print`` در تابع ``wrapper_timer`` برایتان مبهم است به درس هفتم بخش **f-string** مراجعه نمایید [`درس هفتم f-string `__]. +چنانچه درک کد دستور ``print`` در تابع ``wrapper_timer`` برایتان مبهم است به درس هفتم بخش **f-string** مراجعه نمایید [`درس هفتم f-string `__]. From 2563b79cd8810e7a1aba14e5586fb83155cf672e Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 28 Oct 2019 23:20:11 +0330 Subject: [PATCH 059/316] start Built-in Functions section --- lessons/l14.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lessons/l14.rst b/lessons/l14.rst index e8b19e2..75157e4 100644 --- a/lessons/l14.rst +++ b/lessons/l14.rst @@ -363,6 +363,19 @@ Function Attributes در انتهای این بخش باید خاطر نشان کرد که در صورت تعریف Attribute برای توابع خود و استفاده از decorator، همانطور که در درس پیش نیز توضیح داده شد استفاده از ``functools.wraps@`` فراموش نشود [`درس سیزدهم `__]. +Built-in Functions +-------------------- + +مفسر پایتون تعدادی تابع کاربردی را بدون نیاز به import کردن ماژول خاصی در اختیار برنامه‌نویسان قرار می‌دهد. از این توابع با عنوان **Built-in Functions** (توابع آماده یا **توابع داخلی**) یاد می‌شود. فهرست کامل این توابع به همراه توضیح در `اسناد پایتون `__ موجود است. در طی دروس پیشین و حتی همین درس با برخی از آن‌ها آشنا شده‌اید، در این بخش نیز به بررسی چند مورد دیگر می‌پردازیم. + +eval +~~~~~~ + +([[eval(expression[, globals[, locals + + + + From 3c51ab8e9c03e7a3176ddf53a58a81ece78087da Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Tue, 29 Oct 2019 13:26:44 +0330 Subject: [PATCH 060/316] work on Built-in Functions section --- lessons/l14.rst | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/lessons/l14.rst b/lessons/l14.rst index 75157e4..514c05f 100644 --- a/lessons/l14.rst +++ b/lessons/l14.rst @@ -371,7 +371,49 @@ Built-in Functions eval ~~~~~~ -([[eval(expression[, globals[, locals +این تابع یک (و تنها یک) عبارت پایتونی را در قالب شی رشته دریافت، اجرا و نتیجه را برمی‌گرداند [`اسناد پایتون `__]. + +:: + + >>> eval('3*4 + 7.2') + 19.2 + +:: + + >>> import math + >>> x = 2 + >>> eval('math.sin(3.5+x) + 7.2') + 6.494459674429608 + +تعریف این تابع شامل دو پارامتر ``globals`` و ``locals`` نیز می‌شود که ارسال آرگومان به آن‌ها اختیاری است. + + + +exec +~~~~~~ + +این تابع همانند ``eval`` است ولی با این تفاوت که می‌تواند چندین عبارت یا دستور پایتونی را در قالب یک شی رشته دریافت و اجرا کند. خروجی ``exec`` همیشه برابر با ``None`` است [`اسناد پایتون `__]. + +:: + + >>> exec('import math; x=2; print(math.sin(3.5+x) + 7.2)') + 6.494459674429608 + +:: + + >>> exec("for i in range(5): print(i)") + 0 + 1 + 2 + 3 + 4 + +.. note:: + ``exec`` در پایتون نسخه 2x به صورت تابع تعریف نشده است و به صورت یک دستور به کار می‌رود:: + + >>> exec 'import math; x=2; print(math.sin(3.5+x) + 7.2)' + 6.49445967443 + From cf00350c20839c2ee975b98005438c0adc1f4aab Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Tue, 29 Oct 2019 23:16:53 +0330 Subject: [PATCH 061/316] work on Built-in Functions section --- lessons/l14.rst | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/lessons/l14.rst b/lessons/l14.rst index 514c05f..1a18770 100644 --- a/lessons/l14.rst +++ b/lessons/l14.rst @@ -385,7 +385,14 @@ eval >>> eval('math.sin(3.5+x) + 7.2') 6.494459674429608 -تعریف این تابع شامل دو پارامتر ``globals`` و ``locals`` نیز می‌شود که ارسال آرگومان به آن‌ها اختیاری است. +بر اساس تعریف موجود در اسناد پایتون ``([[eval(object[, globals[, locals``، این تابع شامل دو پارامتر ``globals`` و ``locals`` نیز می‌شود که ارسال آرگومان به آن‌ها اختیاری است. هر دو از نوع دیکشنری (dict) هستند که Scope یا حوزه‌های global و local کدی که باید اجرا شود (پارامتر یکم تابع) را ارايه می‌دهند:: + + >>> globals_env = {'x': 7, 'y': 10, 'birds': ['Parrot', 'Swallow', 'Albatross']} + >>> locals_env = {} + >>> a = eval("3 * x + 4 * y", globals_env, locals_env) + >>> a + 61 + @@ -409,11 +416,34 @@ exec 4 .. note:: - ``exec`` در پایتون نسخه 2x به صورت تابع تعریف نشده است و به صورت یک دستور به کار می‌رود:: + ``exec`` در پایتون نسخه 2x به صورت تابع تعریف نشده است و به صورت یک دستور به کار می‌رود [`اسناد پایتون `__]:: >>> exec 'import math; x=2; print(math.sin(3.5+x) + 7.2)' 6.49445967443 +این تابع همانند ``eval`` شامل دو پارامتر ``globals`` و ``locals`` نیز می‌شود:: + + exec(object[, globals[, locals]]) + +:: + + >>> exec("for b in birds: print(b)", globals_env, locals_env) + Parrot + Swallow + Albatross + +که البته در نسخه‌های 2x از سینتکس ``[[exec code[ in globals[,locals`` پیروی می‌شود:: + + >>> exec "for b in birds: print b" in globals_env, locals_env + Parrot + Swallow + Albatross + + +compile +~~~~~~~~~ + + From 71477e3bb32f7fdf4d72965dc26b5734517e8a55 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Fri, 1 Nov 2019 12:19:20 +0330 Subject: [PATCH 062/316] rename donate page and create interpreter page --- _templates/sphinx_minoo_theme/includes/top.html | 2 +- _templates/sphinx_minoo_theme/static/minoo.js | 2 +- donate.rst | 2 +- index.rst | 7 +------ interpreter.rst | 15 +++++++++++++++ 5 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 interpreter.rst diff --git a/_templates/sphinx_minoo_theme/includes/top.html b/_templates/sphinx_minoo_theme/includes/top.html index e6a862e..908739a 100644 --- a/_templates/sphinx_minoo_theme/includes/top.html +++ b/_templates/sphinx_minoo_theme/includes/top.html @@ -26,6 +26,6 @@

diff --git a/_templates/sphinx_minoo_theme/static/minoo.js b/_templates/sphinx_minoo_theme/static/minoo.js index b78a81a..b28c6c0 100644 --- a/_templates/sphinx_minoo_theme/static/minoo.js +++ b/_templates/sphinx_minoo_theme/static/minoo.js @@ -127,7 +127,7 @@ $( document ).ready(function() { if ($(this).text().indexOf("پیش‌گفتار")>=0) { $(this).addClass('reportmenufield'); } - if ($(this).text().indexOf("گزارش هدایای پرداخت شده")>=0) { + if ($(this).text().indexOf("گزارش حمایت‌های مالی")>=0) { $(this).addClass('reportmenufield'); } if ($(this).text().indexOf("خودآزمایی") >= 0) { diff --git a/donate.rst b/donate.rst index 7b6f1a6..bf6de9b 100644 --- a/donate.rst +++ b/donate.rst @@ -6,7 +6,7 @@ :keywords: پایتون, آموزش, آموزش برنامه نویسی, آموزش پایتون, برنامه نویسی, کتاب آموزش, آموزش فارسی, کتاب آزاد -گزارش هدایای پرداخت شده +گزارش حمایت‌های مالی ========================= مبالغ مهم نیستند، از اقدام و پیام تشویق شما دوستان بسیار سپاسگذارم. (*اطلاعات این صفحه به صورت آنی بروز نمی‌شود!*) diff --git a/index.rst b/index.rst index 0ad180c..aff527a 100644 --- a/index.rst +++ b/index.rst @@ -31,12 +31,7 @@ lessons/l14 log donate - -| - -.. raw:: html - - + interpreter | diff --git a/interpreter.rst b/interpreter.rst new file mode 100644 index 0000000..db289b7 --- /dev/null +++ b/interpreter.rst @@ -0,0 +1,15 @@ + +.. meta:: + :description: کتاب آنلاین و آزاد آموزش زبان برنامه‌نویسی پایتون به فارسی + :keywords: پایتون, آموزش, آموزش برنامه نویسی, آموزش پایتون, برنامه نویسی, کتاب آموزش, آموزش فارسی, کتاب آزاد + +محیط تعاملی پایتون +================== + +در این بخش می‌توانید به تمرین پایتون بپردازید. + + +.. raw:: html + + + From 1466765e9ab2d37147c93c36fb6003e2b301bd87 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Fri, 1 Nov 2019 13:32:06 +0330 Subject: [PATCH 063/316] fix donate box --- .../sphinx_minoo_theme/includes/bottom.html | 28 +++++++++- .../sphinx_minoo_theme/includes/top.html | 4 ++ .../sphinx_minoo_theme/static/minoo-rtl.css | 51 ++++++++++++++++++- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/_templates/sphinx_minoo_theme/includes/bottom.html b/_templates/sphinx_minoo_theme/includes/bottom.html index 2f7b6e9..2e155e6 100644 --- a/_templates/sphinx_minoo_theme/includes/bottom.html +++ b/_templates/sphinx_minoo_theme/includes/bottom.html @@ -21,7 +21,31 @@ {% endif %} - - diff --git a/_templates/sphinx_minoo_theme/static/minoo.css b/_templates/sphinx_minoo_theme/static/minoo.css index 22c482b..7ade952 100644 --- a/_templates/sphinx_minoo_theme/static/minoo.css +++ b/_templates/sphinx_minoo_theme/static/minoo.css @@ -326,7 +326,7 @@ margin-top:100px; .donate-badge{ position: fixed; - bottom: 8px; + bottom: 12px; z-index: 999999; left: 40px; display:none; @@ -383,4 +383,16 @@ text-align: inherit; .top-red{display:none !important;} } +ul li p:last-child {margin-bottom: 24px !important;} + +a.side-donate{ + background-color: #66BB6A; + margin: 0px 2px; + color: white; + padding: 2px 10px; +} + +a.hover{ + background-color: #4CAF50; +} From 6f7c3457715e591490fe85d1efab894edb1af873 Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Fri, 28 Feb 2020 16:43:25 +0330 Subject: [PATCH 090/316] works on specials characters rules --- lessons/l15.rst | 141 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 10 deletions(-) diff --git a/lessons/l15.rst b/lessons/l15.rst index e5324ad..e18fa1b 100644 --- a/lessons/l15.rst +++ b/lessons/l15.rst @@ -5,12 +5,12 @@ :keywords: آموزش, آموزش پایتون, آموزش برنامه نویسی, پایتون, تابع, کتابخانه, پایتون, re -درس ۱۵: کتابخانه استاندارد پایتون: re -====================================== +درس ۱۵: کتابخانه استاندارد پایتون: Regular expression در پایتون - re +============================================================================ -**عبارات با قاعده** (**Regular expression**) یا به اختصار **regex**، رشته‌ای حاوی کاراکترهایی خاص و با معنی است که در عملیات‌هایی مانند یافتن (find)، جاگذاری (repleace) و اعتبارسنجی (validation) به شدت کاربرد پیدا کرده است. در واقع با استفاده از regex می‌توان یک الگو (pattern) برای جستجو در متن یا تطابق آن ایجاد کرد. [`ویکی‌پدیا `__] +**عبارات با قاعده** (**Regular expression**) یا به اختصار **RegEx**، رشته‌ای حاوی کاراکترهایی خاص و با معنی است که در عملیات‌هایی مانند یافتن (find)، جاگذاری (repleace) و اعتبارسنجی (validation) به شدت کاربرد پیدا کرده است. در واقع با استفاده از RegEx می‌توان یک الگو (pattern) برای جستجو در متن یا تطابق آن ایجاد کرد. [`ویکی‌پدیا `__] -در این درس به شرح قواعد موجود در regex و همچنین ماژول ``re`` از کتابخانه استاندارد پایتون خواهیم پرداخت [`اسناد پایتون `__]. ماژول ``re`` یک مجموعه ابزار برای کار با regex در پایتون را فراهم آورده است که می‌توان آن را موتور تحلیل regex در پایتون دانست. +در این درس به شرح قواعد موجود در RegEx و همچنین ماژول ``re`` از کتابخانه استاندارد پایتون خواهیم پرداخت [`اسناد پایتون `__]. ماژول ``re`` یک مجموعه ابزار برای کار با RegEx در پایتون را فراهم آورده است که می‌توان آن را موتور تحلیل RegEx در پایتون دانست. @@ -35,29 +35,150 @@ کاراکترهای تطابق (Matching Characters) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -در عمل تطبیق (Match) با regex، اکثر حروف و کاراکتر‌ها معرف خود هستند. برای مثال کلمه ``test`` با همان کلمه test تطابق یا همخوانی پیدا می‌کند. اما برخی کاراکترها هستند که به جای همخوانی با خود، مفهوم یا الگویی خاص را می‌رساند که عبارتند از:: +در عمل تطبیق (Match) با RegEx، اکثر حروف و کاراکتر‌ها معرف خود همان کاراکتر است. برای مثال کاراکتر ``a`` معرف ``a`` است و کلمه ``test`` نیز با همان کلمه ``test`` تطابق یا همخوانی پیدا می‌کند. - . ^ $ * + ? { } [ ] \ | ( ) +با این حال برخی از کاراکترها هستند که به جای همخوانی با خود، مفهوم یا الگویی دیگر را می‌رساند که عبارتند از:: -* **.** + . ^ $ * + ? [] {} \ | () - به معنی «هر کاراکتری» می‌باشد و با هر کاراکتری تطابق یا همخوانی خواهد داشت. +* Period ``.`` + به معنی «هر کاراکتری» می‌باشد و با هر کاراکتری تطابق یا همخوانی خواهد داشت (به جز کاراکتر newline یا ``n\``). -* **^** + + +* Caret ``^`` در یک کاربرد تعین کننده نقطه آغاز تطابق و شروع الگو می‌باشد (کاربرد دیگر آن در ادامه ذکر می‌گردد). + :: + + ^a + a => Matched + abc => Matched + bac => NO Matched ('a' is not in the start) + + :: + + ^ab + abc => Matched + acb => NO Matched (starts with 'a' but not followed by 'b') + + +* Dollar ``$`` + + تعین کننده نقطه پایان تطابق الگو می‌باشد. + + + :: + + a$ + a => Matched + formula => Matched + cab => NO Matched ('a' is not in the end) + + + :: + + ^s...d$ + + به عنوان مثالی دیگر، الگوی بالا معرف هر کلمه پنج کاراکتری است که با کاراکتر ``s`` شروع و با کاراکتر ``d`` پایان می‌پذیرد. + + +* Star ``*`` + + معرف **هیچ** یا **هر تعداد** تکرار الگوی سمت چپ خود می‌باشد. + + + :: + + ma*n + mn => Matched + man => Matched + maaan => Matched + main => NO Matched ('a' is not followed by 'n') + woman => Matched + + +* Plus ``+`` + + معرف **یک** یا **هر تعداد** تکرار الگوی سمت چپ خود می‌باشد. + + + :: + + ma+n + mn => NO Matched (no 'a' character) + man => Matched + maaan => Matched + main => NO Matched ('a' is not followed by 'n') + woman => Matched -* **[ ]** + + +* Question Mark ``?`` + + معرف **هیج** یا **یک** تکرار الگوی سمت چپ خود می‌باشد. + + + :: + + ma?n + mn => Matched + man => Matched + maaan => NO Matched (more than one 'a' character) + main => NO Matched ('a' is not followed by 'n') + woman => Matched + + + +* Square brackets ``[ ]`` از دو کاراکتر ``[`` و ``]`` برای بیان یک دسته یا بازه از کاراکترها استفاده می‌شود که برای این منظور می‌توان تک تک کاراکترها را به صورت صریح نوشت یا با استفاده از کاراکتر ``-`` به سادگی یک بازه را تعیین نمود. + :: + + [abc] + + برای نمونه، الگوی بالا با هر رشته‌ای که حاوی کاراکتر‌های ``b`` ،``a`` یا ``c`` باشد تطابق خواهد داشت [`regex101@ تست آنلاین `__]. + + + :: + + [abc] + a => 1 Matched + ac => 2 Matched + python => NO Matched + abc de ca => 5 Matched + + + همانطور که بیان شد، با استفاده از کاراکتر ``-`` هر دو بخش روبرو در نمونه کد پایین با یکدیگر معادل و برابر هستند:: + + [0-9] == [0123456789] + [1-4] == [1234] + [a-e] == [abcde] + [1-5a-e] == [12345abcde] + [0-39] == [01239] + [a-eA-E] == [abcdeABCDE] + + + .. note:: + باید توجه داشت RegEx ذاتا CASE SENSITIVE است و کوچک یا بزرگ بودن حروف انگلیسی در آن تاثیر دارد. با این حال زبان‌های برنامه‌نویسی از جمله پایتون امکاناتی را برای غیرفعال ساختن این وضعیت فراهم می‌آورند که در ادامه بررسی خواهد شد. + + + **کاربرد دوم کاراکتر ^ (Caret)** + + اکنون زمان آن رسیده است تا با کاربرد دوم کاراکتر Caret ``^`` آشنا شویم: با قرار دادن این کاراکتر به عنوان عضو ابتدای یک ``[ ]`` می‌توان عملکرد یا مفهوم آن را برعکس‌ یا در واقع NOT کرد! برای نمونه الگوی ``[abc^]`` به معنی تطابق با هر کاراکتری است به جز ``b`` ،``a`` و ``c``. [`regex101@ تست آنلاین `__] + + + +* Braces ``{ }`` + با ساختاری مشابه ``{n,m}`` به کار می‌رود که در آن ``n`` و ``m`` به ترتیب بیان کننده حداقل و حداکثر تعداد تکرار الگوی سمت چپ خود می‌باشند. From 26b5cab9d684353a310b2753aa93a0a703d2077f Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Sat, 29 Feb 2020 01:00:31 +0330 Subject: [PATCH 091/316] works on specials characters rules 2 --- lessons/l15.rst | 100 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 12 deletions(-) diff --git a/lessons/l15.rst b/lessons/l15.rst index e18fa1b..2028b93 100644 --- a/lessons/l15.rst +++ b/lessons/l15.rst @@ -38,34 +38,66 @@ در عمل تطبیق (Match) با RegEx، اکثر حروف و کاراکتر‌ها معرف خود همان کاراکتر است. برای مثال کاراکتر ``a`` معرف ``a`` است و کلمه ``test`` نیز با همان کلمه ``test`` تطابق یا همخوانی پیدا می‌کند. -با این حال برخی از کاراکترها هستند که به جای همخوانی با خود، مفهوم یا الگویی دیگر را می‌رساند که عبارتند از:: +با این حال برخی از کاراکترها هستند که به جای همخوانی با خود، مفهوم دیگری را می‌رسانند که عبارتند از:: - . ^ $ * + ? [] {} \ | () + . ^ $ * + ? [] {} | () \ -* Period ``.`` +* Dot ``.`` - به معنی «هر کاراکتری» می‌باشد و با هر کاراکتری تطابق یا همخوانی خواهد داشت (به جز کاراکتر newline یا ``n\``). + به معنی «هر کاراکتری» می‌باشد. یعنی وجود ``.`` در یک الگو (Pattern) باعث انجام عمل تطابق یا همخوانی با هر کاراکتری خواهد شد (به جز کاراکتر newline یا ``n\``). + + .. tip:: + به صورت پیش‌فرض ``.`` در الگوی RegEx کاراکتر newline را شامل نمی‌شود ولی در زبان برنامه‌نویسی پایتون می‌توان با نشانه‌گذاری ``re.DOTALL`` کاری کرد که کاراکتر newline را نیز شامل شود. *نمونه کد مربوط به این بحث در بخش بعدی بررسی خواهد شد.* + + به عنوان نمونه الگوی ``...`` هر سه کاراکتر متوالی را در بر می‌گیرد:: + + ... + + + :: + + 'ab' => no matche + 'abc1234' => 2 matches ('abc', '123') + '01267' => 1 matche ('012') + 'python' => 2 matches ('pyt', 'hon') + '2 0 85 ad' => 3 matches ('2 0', ' 85', ' a') + + [`regex101@ تست آنلاین `__] * Caret ``^`` - در یک کاربرد تعین کننده نقطه آغاز تطابق و شروع الگو می‌باشد (کاربرد دیگر آن در ادامه ذکر می‌گردد). + در یک کاربرد در سمت چپ یک الگو قرار می‌گیرد و تعین کننده الزام شروع با آن الگو (Pattern) می‌باشد (*کاربرد دیگر آن در ادامه ذکر خواهد شد*). :: - ^a - a => Matched - abc => Matched - bac => NO Matched ('a' is not in the start) + ^a + :: - ^ab - abc => Matched - acb => NO Matched (starts with 'a' but not followed by 'b') + 'a' => 1 matche ('a') + 'abc' => 1 matche ('a') + 'bac' => no matche ('a' is not in the start) + + [`regex101@ تست آنلاین `__] + + + :: + + ^ab + + :: + + 'abc' => 1 matche ('ab') + 'acb' => no matche (starts with 'a' but not followed by 'b') + 'ab123 ab456' => 1 matche ('ab' from ab123) + + + [`regex101@ تست آنلاین `__] * Dollar ``$`` @@ -181,6 +213,50 @@ با ساختاری مشابه ``{n,m}`` به کار می‌رود که در آن ``n`` و ``m`` به ترتیب بیان کننده حداقل و حداکثر تعداد تکرار الگوی سمت چپ خود می‌باشند. + :: + + a{2,3} + abc dat => NO Matched + abc daat => 1 Matched (at d'aa't) + aabc daaat => 2 Matched (at 'aa'bc and d'aaa't) + aabc daaaat => 2 Matched (at 'aa'bc and d'aaa'at) + + + [`regex101@ تست آنلاین `__] + + :: + + [0-9]{2,4} + 1 => NO Matched + ab123cde => 1 Matched (at ab'123'cde) + 12 => 1 Matched + 123456789 => 2 Matched (at '1234' and '5678') + 1 2 3 4 => NO Matched + + + [`regex101@ تست آنلاین `__] + + + +* Alternation ``|`` + + این کاراکتر مفهومی معادلی عملگر ``OR`` (یا) دارد که معرف تطابق با الگوی سمت راست **یا** سمت چپ خود می‌باشد. + + + :: + + a|b + cde => NO Matched + ade => 1 Matched (at 'a'de) + acdbea => 3 Matched (at 'a'cd'b'e'a') + + [`regex101@ تست آنلاین `__] + + + +* Group ``()`` + + این کاراکتر From f84199c2a178acde90302b37f296fa1ff909de2c Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Mon, 2 Mar 2020 20:01:42 +0330 Subject: [PATCH 092/316] implement Google Tag Manager --- _templates/sphinx_minoo_theme/layout.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/_templates/sphinx_minoo_theme/layout.html b/_templates/sphinx_minoo_theme/layout.html index d6f7225..d246b73 100644 --- a/_templates/sphinx_minoo_theme/layout.html +++ b/_templates/sphinx_minoo_theme/layout.html @@ -14,10 +14,25 @@ + + + + + {% include "includes/header.html" %} {%- block extrahead %}{% endblock %} + + + + +
{% include "includes/sidebar.html" %} From e45331526a3c770e72c5791e24aea1db43922aff Mon Sep 17 00:00:00 2001 From: sajad Date: Tue, 21 Apr 2020 11:03:09 +0430 Subject: [PATCH 093/316] Remove Link --- _templates/sphinx_minoo_theme/includes/top.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/_templates/sphinx_minoo_theme/includes/top.html b/_templates/sphinx_minoo_theme/includes/top.html index d1e838a..f4e8dd6 100644 --- a/_templates/sphinx_minoo_theme/includes/top.html +++ b/_templates/sphinx_minoo_theme/includes/top.html @@ -40,9 +40,7 @@
From cc6db45821ab2db2b96a46de2c11aadfa10afc01 Mon Sep 17 00:00:00 2001 From: sajad Date: Tue, 21 Apr 2020 11:04:04 +0430 Subject: [PATCH 094/316] remove link --- _templates/sphinx_minoo_theme/includes/sidebar.html | 1 - 1 file changed, 1 deletion(-) diff --git a/_templates/sphinx_minoo_theme/includes/sidebar.html b/_templates/sphinx_minoo_theme/includes/sidebar.html index f940689..5c8501e 100644 --- a/_templates/sphinx_minoo_theme/includes/sidebar.html +++ b/_templates/sphinx_minoo_theme/includes/sidebar.html @@ -59,7 +59,6 @@ {% endif %} -آموزش آنلاین مکتب‌خونه