From f5daa7285f13315350fb7d8181a7012304e36c9c Mon Sep 17 00:00:00 2001 From: Saeid Darvish Date: Fri, 28 Jun 2019 19:14:02 +0430 Subject: [PATCH 001/294] 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 002/294] 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 003/294] 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 004/294] 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 005/294] 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 006/294] 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 007/294] 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 008/294] 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 009/294] 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 010/294] 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 011/294] 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 012/294] 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 013/294] 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 014/294] 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 015/294] =?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 016/294] 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 017/294] 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 018/294] 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 019/294] 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 020/294] 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 021/294] 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 022/294] 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 023/294] 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 024/294] 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 025/294] 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 026/294] 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 027/294] 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 028/294] 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 029/294] 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 030/294] 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 031/294] * --- _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 032/294] 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 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

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 033/294] 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 034/294] 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 035/294] 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 036/294] 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 037/294] 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 038/294] 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 039/294] 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 040/294] 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 041/294] 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 068/294] 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 069/294] 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 070/294] 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 071/294] 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 072/294] 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 %} -آموزش آنلاین مکتب‌خونه