پایتون برای همه | 25 | توابع ریاضی | جریان اجرا

پایتون برای همه پایتون 3

اشتراک وفاداری (ماهی یک چایی)

می‌توانید از محتویات این باکس بگذرید و یک‌راست به سراغ نوشته اصلی بروید. قبل از خرید اشتراک وفاداری، مزایای آن را از طریق این پیوند مشاهده کنید. لطفا تنها بعد از خواندن «مزایای خرید اشتراک» اقدام به خرید کنید.

توابع ریاضی

>>> import math
>>> 

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

>>> print(math)
<module 'math' (built-in)>

ماژول مقصد شامل توابع و مقادیر مشخص شده‌ایست که دسترسی به آن‌ها را از طریق اسم خاصِ ماژول و اسم خاص تابع ممکن می‌سازد. این دو اسم با یک نقطه از هم جدا می‌شوند. به این قالب dot notation یا «نماد نقطه‌ای» می‌گویند.

>>> ratio = signal_power / noise_power
>>> decibels = 10 * math.log10(ratio)
>>> radians = 0.7
>>> height = math.sin(radians)

اولین مثال، لگاریتم بر پایه‌ی ۱۰ ــِــ نسبت سیگنال به نویز را محاسبه می‌کند. ماژول math تابعی به اسم log را نیز مهیا می‌کند که لگاریتم بر پایه‌ی e می‌گیرد.
مثال دوم سینوس radians را محاسبه می‌کند. نام متغیر radians در اصل می‌گوید که sin و بقیه توابع مربوط به مثلثات (cos و tan و غیره)، آرگویمنت را به رادیان می‌گیرند.

برای تغییر درجه به رادیان می‌توانید آن را بر ۳۶۰ تقسیم و در 2pi ضرب نمایید:

>>> degrees = 45
>>> radians = degrees / 360.0 * 2 * math.pi
>>> math.sin(radians)
0.7071067811865476

عبارت math.pi متغیر pi را از ماژول math می‌گیرد. مقدار این متغیر تقریبا برابر با عدد پی است و تا حدود ۱۵ رقم اعشار دقت دارد.
اگر از مثلثات سر در می‌آورید، نتایج پیشین را با مربع ریشه دو، تقسیم بر دو مقایسه کنید.

math.sqrt(2) / 2.0
0.7071067811865476

اضافه کردن یک تابع

تا اینجای کار از توابعی که در خود پایتون وجود داشت استفاده کردیم، ولی پایتون این امکان را به ما می‌دهد که توابع جدید نیز اضافه کنیم. یک شناسانش تابع، نام یک تابع و گزاره‌های آن را تعیین می‌کند. این گزاره‌ها زمانی که تابع فراخوانده می‌شود اجرا می‌گردند. زمانی که یک تابع را تعریف کردید، می‌توانید از آن به تعداد دفعاتی که عشق‌تان کشید دوباره و دوباره استفاده کنید بدون اینکه مجبور باشید کد آن را راه‌به‌راه بنویسید.

مثال:

def print_lyrics():
    print("I'm a lumberjack, and I'm okay.")
    print('I sleep all night and I work all day.')

کلمه‌ی def در ابتدای کار، یک کلمه‌ی کلیدی (keyword) برای تعریف تابع است. سپس اسم تابع را مشخص می‌کنیم. مثلا در مثال بالا print_lyrics اسم تابع می‌شود. قوانین انتخاب اسمِ متغیرها، برای توابع نیز صادقند. حروف، اعداد و بعضی از علائم مجازند ولی اولین کاراکتر نمی‌تواند که عدد باشد. از کلمات کلیدی برای اسم تابع نبایستی استفاده کنید و بایستی از انتخاب نام یکسان برای یک متغیر و تابع در یک برنامه اجتناب کنید.
پرانتزهای خالی در جلوی یک تابع نشان می‌دهد که این تابع آرگویمنتی را دریافت نمی‌کند. در آینده توابعی خواهیم ساخت که به عنوان ورودی آرگیومنت دریافت می‌کنند.

اولین خط یک تابع را به اسم هدر و بقیه آن را بادی یا بدنه‌ی تابع می‌نامیم. هدر با دو نقطه تمام می‌شود و بدنه با مقداری تورفتگی نسبت هدر در ادامه آورده می‌شود. رسم این است که تورفتگی از چهار فاصله (Space) تشکیل شده باشد. بادی می‌تواند شامل هر مقدار گزاره که نیاز است شود. در اصل محدودیتی در کار نیست.

رشته‌هایی که در گزاره‌ی پرینت آورده می‌شوند بین علامت نقل‌قول قرار می‌گیرند. علامت نقل‌قول به دو صورت ‘رشته’ و “رشته” استفاده می‌شود. البته از سینگل کوت (‘) بیشتر استفاده می‌کنند. گاهی خودِ رشته مثلاً عبارت It’s me در درون خود یک سینگل‌کوت دارد. این سینگل‌کوت باعث می‌شود که پایتون گیج شده و با رسیدن به آن، رشته را تمام شده فرض کند. اینجاست که از دابل‌کوت (“) بایستی استفاده کنیم.

اگر شما یک تابع را در حالت تعاملی پایتون وارد کنید، مفسر علامت (…) را چاپ می‌کند تا به شما نشان دهد نوبت به وارد کردن بدنه‌ی کد در تابع است.

>>> def print_lyrics():
...     print("I'm a lumberjack, and I'm okay.")
...     print('I sleep all night and I work all day.')
...

برای تمام کردن بدنه در حالت تعاملی، Enter را در یک سطر خالی فشار دهید. یعنی بعد از نوشتن آخرین خط از بادی، دو بار اینتر را بزنید.

>>> print(print_lyrics)
<function print_lyrics at 0xb7e99e9c>
>>> print(type(print_lyrics))
<class 'function'>

ما به مقدار print_lyrics فانکشن آبجکت (function object) می‌گوییم. فانکشن آبجکت از نوع تابع به حساب می‌آید.

دستورِ فراخوانی یک تابع دقیقا برابر با نام خود تابع است:

>>> print_lyrics()
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.

زمانی که یک تابع را تعریف کردید، می‌توانید از آن در داخل توابع دیگر نیز بهره ببرید. مثلا می‌توانیم یک تابع با اسم repeat_lyrics بنویسیم و از print_lyrics در آن استفاده کنیم.

def repeat_lyrics():
    print_lyrics()
    print_lyrics()

حالا تابع repeat_lyrics را فراخوانی می‌کنیم:

>>> repeat_lyrics()
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.

البته درست است که آهنگ این مدلی نبود ولی خب حداقل یاد گرفتید که یک تابع چطوری کار می‌کند.

تعریف تابع و استفاده از آن

کدهای قسمتِ قبل را که سر هم کنیم، کل برنامه چیزی شبیه به این خواهد بود:

def print_lyrics():
    print("I'm a lumberjack, and I'm okay.")
    print('I sleep all night and I work all day.')

def repeat_lyrics():
    print_lyrics()
    print_lyrics()

repeat_lyrics()

# Code: http://www.py4e.com/code3/lyrics.py

برنامه شامل دو تابعِ تعریف شده به اسم‌های print_lyrics و repeat_lyrics می‌شود. توابعِ تعریف شده دقیقا مثل سایر گزاره‌ها اجرا می‌شوند ولی نتیجه‌ی اجرایشان ساخته شدنِ فانکشن‌آبجکت‌هاست. گزاره‌های داخل تابع تا زمانی که تابع فراخوانی نشود، اجرا نخواهند شد و خودِ تابع هیچ خروجی‌ای را نمی‌سازد.

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

تمرین ۲: آخرین خط این برنامه یعنی repeat_lyrics()‎ را بچینید و قبل از تعریف توابع قرار دهید. حالا برنامه را اجرا کنید. چه خطایی دریافت می‌کنید؟

آشنا شدن با نوع و خروجی خطاها، باعث می‌شود که شما در آینده و در مواجه به آن‌ها سریع‌تر مشکل را تشخیص دهید.

تمرین ۳: فراخوانی تابع را به پایین اسکریپت برگردانید. حالا تابع print_lyrics را زیر تابع repeat_lyrics قرار دهید. برنامه را اجرا کرده. چه اتفاقی می‌افتد؟

جریان اجرا

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

اجرا همیشه از اولین خط برنامه آغاز و در هر لحظه یک گزاره به ترتیب از بالا به پایین اجرا می‌شود.

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

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

به نظر ساده می‌رسد. ولی خب در جریان اجرای یک تابع ممکن است یک تابع دیگر نیز فراخوانده شود. اوضاع وقتی پیچیده‌تر می‌شود که در جریان اجرای تابع دوم نیز اصلا بعید نیست که یک تابع دیگر فراخوانده و جریان اجرا به سمت آن کج شود.

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

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

این نوشته تحت مجوز کرییتیو کامنز BY – NC و حمایت موسسه تحقیقاتی رامونا ارائه می‌شود. شما می‌توانید با توجه به مفاد این گواهی از آن استفاده کنید.

اولین نفری باشید که نظر می‌گذارد

پاسخ دهید

ایمیل شما نمایش داده نخواهد شد