پارامترها و آرگویمنتها
بعضی از توابع توکاریشدهای که تاکنون استفاده کردهایم، به آرگیومنت احتیاج داشتند. به عنوان نمونه زمانی که math.sin را فراخوانی میکنیم، یک عدد به عنوان آرگیومنت به آن میفرستیم. گاهی توابع بیش از یک آرگیومنت را دریافت میکنند. مثلا math.pow دو آرگیومنت میگیرد، ۱) پایه و ۲) توان.
در داخل تابع، آرگیومنتها به متغیرهایی – که آنها را پارامتر مینامیم – اختصاص داده میشوند. بهتر است نگاهی به مثال زیر بیندازیم. در این مثال کاربر یک تابع که یک آرگیومنت دریافت میکند را تعریف کرده است:
1 2 3 |
def print_twice(bruce): print(bruce) print(bruce) |
این تابع یک آرگیومنت را به پارامتری که نامش bruce است تخصیص داده است. در مثال بالا زمانی که تابع فراخوانده میشود، مقدار پارامتر (هر چیزی که باشد) دو بار چاپ میشود.
این تابع با هر مقداری که قابل چاپ باشد، کار خواهد کرد.
1 2 3 4 5 6 7 8 9 10 |
>>> print_twice('Spam') Spam Spam >>> print_twice(17) 17 17 >>> import math >>> print_twice(math.pi) 3.141592653589793 3.141592653589793 |
قوانینی که برای توابع توکاریشده صادق است، برای توابعی که کاربر تعریف کرده نیز صدق میکند، در نتیجه از هر عبارتی به عنوان آرگیومنت برای تابع print_twice میتوانیم بهره ببریم.
1 2 3 4 5 6 |
>>> print_twice('Spam '*4) Spam Spam Spam Spam Spam Spam Spam Spam >>> print_twice(math.cos(math.pi)) -1.0 -1.0 |
آرگیومنت قبل از اینکه تابع فراخوانده شود، بررسی میشود. مثلا در مثال ما “Spam ‘*4 و همچنین math.cos(math.pi) تنها یک بار وارسی میشوند.
همچنین میتوانید از متغیر به عنوان یک آرگیومنت بهره ببربید:
1 2 3 4 |
>>> michael = 'Eric, the half a bee.' >>> print_twice(michael) Eric, the half a bee. Eric, the half a bee. |
نام متغیری که ما به عنوان آرگیومنت (michael) به تابع میفرستیم، هیچ دخل و تصرفی در نام پارامتر ما (bruce) ندارد. به عبارتی مقداری که فراخوانی میشود – در اینجا michael – مهم نیست که چه باشد، چون تابع با پارامتری که با آن تعریف شده – در اینجا bruce – کار میکند. به عبارت ساده در تابع print_twice ما همه را bruce مینامیم، حالا هر آرگیومنتی که میخواد وارد تابع شود تفاوتی ایجاد نمیکند، چرا که نامش در داخل تابع، bruce خواهد بود.
توابع نتیجهده و توابع بینتیجه
برخی از توابع، مانند تابع ریاضی، نتیجه را صادر کرده و برمیگرداند. من به این توابع، «توابع باثمر» یا «نتیجهده» میگویم. باقی توابع، مانند print_twice، کاری را انجام میدهند، ولی نتیجهای را برنمیگردانند. به آنها «توابع بینتیجه» یا «وُید» میگویند.
زمانی که یک تابع نتیجهده را احضار میکنید، تقریبا همیشه قرار است با نتیجهای که برمیگرداند کاری را انجام دهید. به عنوان مثال آن را به یک متغیر اختصاص دهید یا به عنوان بخشی از عبارت از آن بهره ببرید:
1 2 |
x = math.cos(radians) golden = (math.sqrt(5) + 1) / 2 |
زمانی که یک تابع را در حالت تعاملی فرا میخوانید، پایتون نتیجهی برگردانده شده را نمایش میدهد:
1 2 |
>>> math.sqrt(5) 2.23606797749979 |
ولی در یک اسکریپت اوضاع متفاوت است. اگر در یک اسکریپت شما اطلاعات برگردانده شده توسط تابع را در داخل یک متغیر ذخیره نکنید، هیچ چیزی از آن تابع دستگیرتان نمیشود و تمام اطلاعاتش پودر شده و به هوا میرود:
1 |
math.sqrt(5) |
در اسکریپت بالا، ریشهی دوم عدد ۵ گرفته میشود ولی از آنجایی که این مقدار در هیچ متغیری ذخیره نمیشود یا بر روی خروجی چاپ نمیگردد، این محاسبه به هیچ کاری نمیآید.
توابع بینتیجه شاید چیزی را بر روی صفحهْ نمایش دهند یا تاثیرات دیگری بر روند برنامه بگذارند ولی آنها نتیجهای را برنمیگردانند. اگر سعی کنید که نتیجه را به یک متغیر اختصاص دهید، مقداری که دریافت میکنید None خواهد بود. به مثال زیر دقت کنید:
1 2 3 4 5 |
>>> result = print_twice('Bing') Bing Bing >>> print(result) None |
مقدار None برابر با رشتهی “None” نیست بلکه مقدار ویژهایست که نوع خاصِ خود را دارد.
1 2 |
>>> print(type(None)) <class 'NoneType'> |
برای بازگرداندن یک مقدار از یک تابع، ما از گزاره return در تابعِ خود استفاده میکنیم. به عنوان مثال میتوانیم یک تابع بسیار ساده برای جمع دو عدد با نام addtwo به شکل زیر بنویسیم که دو عدد را به عنوان آرگیومنت گرفته و سپس پارامترهایش را با هم جمع زده و مقدارِ حاصل از این معادله را برمیگرداند:
1 2 3 4 5 6 7 8 |
def addtwo(a, b): added = a + b return added x = addtwo(3, 5) print(x) # Code: http://www.py4e.com/code3/addtwo.py |
زمانی که این اسکریپت اجرا میشود، گزارهی print عدد 8 را چاپ خواهد کرد چرا که تابع addtwo با دو آرگیومنت 5 و 3 فراخوانی شده است. در درون تابع پارامترهای a و b به ترتیب 3 و 5 میشوند. تابع جمع دو عدد را محاسبه میکند و در متغیر محلی خود با نام added ذخیره میکند. منظور از «متغیر محلی» متغیریست که در درون تابع تعریف میشود و بیرون از تابع اعتباری ندارد. سپس از گزارهی return استفاده کرد و مقدار محاسبه شما را به کدِ فراخوان به عنوان نتیجهی تابع باز میگرداند. کدِ فرخوان همان عبارتیست که تابع در آن فراخوانی شده است. سپس نتیجهی برگرداننده شده به متغیر x اختصاص داده شده و در نهایت چاپ میشود.
چرا از توابع استفاده میکنیم؟
خُرد کردن برنامه به توابع مختلف چه مزیتهایی دارد؟ در اینجا به دلایلی که به خاطرش ما یه برنامه را به تابعها میشکنیم، مرور میکنیم:
ساخت یک تابع جدید به شما امکان نامگذاری بر روی دستهای از گزارهها را میدهد. به این صورت برنامهی شما خواناتر شده، بهتر درک میشود و راحتتر میتواند اشکالزدایی شود.
توابع، اندازهی برنامهی ما را کوچکتر میکنند. عدم نیاز به تکرار یک سری گزاره که تحت نامی به عنوان تابع در برنامه تعریف کردهایم، به ما این امکان را میدهد که برنامههای خود را بدون از دست دادن کارایی کوچکتر کنیم. در آینده نیز اگر لازم باشد که سلسله گزارهها را دستکاری کنیم، فقط کافیست که همان تابع را تغییر دهیم و نتیجهی این تغییر را در سرتاسر برنامه ببینیم.
تقسیم یک برنامهی بزرگ به توابع به شما امکان اشکالزدایی قسمتهای مختلف را در آن واحد میدهد. سپس میتوانید این قسمتها را سر هم کنید و در نهایت کل بدنهی برنامه را بسازید.
توابعی که خوب طراحی شدهاند، میتوانند توسط برنامههای زیادی مورد استفاده قرار بگیرند. زمانی که یک تابع را نوشتید و اشکالزدایی کردید، میتوانید با خیال راحت از آن در سایر برنامههای خود نیز استفاده کنید.
در ادامهی این کتاب، ما اغلب از توابع برای توضیح یک مفهوم استفاده میکنیم. بخشی از مهارت ساخت و استفاده از توابع، تببین یک ایده یا مفهوم توسط آن است. مثلا شما یک ایده دارید: «پیدا کرد کوچکترین مقدار از یک لیست». در اینجا ما به مهارتی برای ساخت یک تابع – که این ایده را در عمل پیاده کند – احتیاج داریم. در ادامه به شما کد مربوط به چنین تابعی را – که ما min میخوانیمش – نشان خواهیم داد. این تابع لیستی از مقادیر را به عنوان آرگیومنت گرفته و کوچکترین مقدار آن لیست را برمیگرداند.
اشکالزدایی
اگر از یک برنامهی ویرایش متن برای نوشتن اسکریپتهای خود استفاده میکنید، احتمالا به مشکل استفاده از اسپیس یا Tab برخواهید خورد. اکثر برنامهها وقتی در حال نوشتن اسکریپت پایتوناید، این موضوع را تشخیص میدهند و جای Tab را با فاصله عوض میکنند ولی بعضی خیر. برای همین بهتر است که خودتان دست به کار شوید و به جای Tab از فاصله استفاده کنید.
اسپیس و Tab معمولا قابل مشاهده نیستند و همین موضوع اشکالزدایی در باب این مشکل را سخت میکند. بهتر است از ویرایشگری استفاده کنید که وظیفهی تو رفتگی گزارهها را خودش برعهده میگیرد.
اشکالزدایی – بهخصوص زمانی که قسمت اشتباهی از برنامه را اجرا میکنید – زمان زیادی را از شما خواهد گرفت. مطمئن شوید که در حال اصلاح کدی میباشید که اجرایش میکنید. اگر مطمئن نیستید که اشکال از کدام قسمتِ کد است میتوانید چیزی مثل print(“hello”) را در آن قسمت کد قرار دهید تا مطمئن شوید جای درستی را ویرایش میکنید. اگر hello را در حین اجرا نمیبینید، پس جای غلطی را اشکالزدایی میکنید.
واژگال فصل
الگوریتم / Algorithm:
یک پروسهی عمومی برای حل دستهای از مسائل.
آرگیومنت / Argument:
مقداری که به یک تابع ارسال میشود. این مقدار به پارامتر متناظر در تابع اختصاص پیدا میکند.
بدنه / Body:
سلسله گزارههای موجود در یک تابع.
ترکیب / Composition:
استفاده از یک عبارت به عنوان بخشی از یک عبارت بزرگتر، یا یک گزاره به عنوان بخشی از یک گزارهی بزرگتر.
قطعی / Deterministic:
قطعی بودن پاسخ هر برنامه در برابر ورودی یکسان.
نماد نقطهای / Dot Notation:
متن یا سینتکسی که توسط آن یک تابع را از یک ماژول دیگر فراخوانی میکنیم. به این صورت که ابتدا نام ماژول را آورده و سپس بعد از نقطه، نام تابع موجود در آن را میآوریم.
جریانِ اجرا / Flow of Execution:
ترتیبی که در آن گزارهها در جریان راهاندازی برنامه، اجرا میشوند.
تابع نتیجهده / Fruitful Function:
تابعی که یک مقدار را برمیگرداند.
تابع / Function:
سلسلهای از گزارهها تحت عنوانِ یک نام که عملیات بهدردبخوری را انجام میدهد. یک تابع ممکن است که آرگیومنت بگیرد یا نگیرد. همچنین ممکن است نتیجهای را برگرداند یا برنگرداند.
فراخوانی تابع / Function Call:
گزارهای که یک تابع را اجرا میکند. این گزاره شامل نام تابع و لیست آرگیومنتهای احتمالی که تابع دریافت میکند میشود.
تعریف تابع / Function Definition:
گزارهای که یک تابع جدید را با اختصاص نام، پارامتر و گزارههایی که قرار است اجرا شوند، میسازد.
فاکنشن آبجکت / Function Object:
مقداری که توسط یک تابع ساخته میشود. نام تابع، یک متغیر است که به یک فانکشن آبجکت اشاره دارد.
هدر / Header:
اولین خط در تعریف یک تابع.
درونریزی گزاره / Import Statement:
گزارهای که فایل ماژول را میخواند و یک ماژول آبجکت میسازد.
ماژول آبجکت / Module Object:
مقداری که توسط گزارهی import ساخته میشود. این مقدار دسترسی را به دادهها و کدهای تعریف شده در یک ماژول مقدور میسازد.
پارامتر / Parameter:
نامی که در داخل یک تابع استفاده میشود و به مقداری که از طریق آرگیومنت به تابع داده شده اشاره دارد.
شبه تصادفی / Pseudorandom:
سلسلهای از اعداد که به نظر تصادفی میآیند ولی توسط عوامل قطعی در برنامه ساخته شدهاند.
مقدار بازگردانده شده / Return Value:
نتیجهی یک تابع. اگر فراخوانی یک تابع به عنوان یک عبارت استفاده شده باشد، مقداری بازگردانده شده توسط تابع، مقدار عبارت خواهد بود.
تابع بینتیجه / Void Function:
تابعی که مقداری را برنمیگرداند.
تمرینها
تمرین ۴: هدف کلیدواژه def در پایتون چیست؟
الف) یک اصطلاح که معنی آن «عجب کد باحالیـه» است.
ب) نشاندهنده شروع یک تابع است.
پ) نشاندهنده این موضوع است که کدهای تو رفتهی بعدی برای آینده ذخیره میشوند.
ج) گزینهی ب و پ هر دو صحیح است.
د) هیچکدام از موارد بالا.
تمرین ۵: برنامهی زیر، چه عبارتی را چاپ خواهد کرد؟
1 2 3 4 5 6 7 8 9 |
def fred(): print("Zap") def jane(): print("ABC") jane() fred() jane() |
الف) Zap ABC jane fred jane
ب) Zap ABC Zap
پ) ABC Zap jane
ج) ABC Zap ABC
د) Zap Zap Zap
تمرین ۶: برنامه پرداخت اضافه برای کسانی که بیشتر کار کردهاند را بازنویسی کرده و تابعی با نام computepay بسازید که دو پارامتر hours و rate را دریافت و سپس مقدار را محاسبه میکند.
1 2 3 |
Enter Hours: 45 Enter Rate: 10 Pay: 475.0 |
تمرین ۷: برنامه نمرهدهیِ فصل قبل را دو مرتبه بنویسید و از یک تابع به اسم computegrade استفاده کنید. این تابع بایستی که نمره را به عنوان پارامتر دریافت کرده و نتیجه را به صورت A یا B یا … برگرداند.
1 2 3 4 5 6 |
Score Grade > 0.9 A > 0.8 B > 0.7 C > 0.6 D <= 0.6 F |
1 |
Program Execution: |
1 2 |
Enter score: 0.95 A |
1 2 |
Enter score: perfect Bad score |
1 2 |
Enter score: 10.0 Bad score |
1 2 |
Enter score: 0.75 C |
1 2 |
Enter score: 0.5 F |
این نوشته تحت مجوز کرییتیو کامنز BY – NC و حمایت موسسه تحقیقاتی رامونا ارائه میشود. شما میتوانید با توجه به مفاد این گواهی از آن استفاده کنید.