آموزش پایتون کلید ورود به دنیای هوش مصنوعی (گام دوم - قسمت هفدهم- توابع)

سلام رفقا

آموزش پایتون کلید ورود به دنیای هوش مصنوعی هست چرا که بسیاری از کتابخانه ها با همین زبان نوشته شده و دسترسی شمارا به منابع ارزشمند بیشتر می کنه. اگه تازه شروع کردی پایتون یاد بگیری برو به جلسه اول (در این لینک) گام به گام بیا جلو.

از این لینک می تونی چارت آموزش پایتون رو ببینی و اینکه ما الان کجا هستیم توی تصویر زیر نشون داده شده.


توی قسمت قبل در مورد دیکشنری ها صحبت کردیم که از این لینک می تونید ببینید. توی این قسمت از آموزش پایتون میریم سراغ تابع ها در قسمت ششم یک مختصری راجبش صحبت کردیم اینجا مفصل تر می گیم. همراه باشید دمتون گرم :قلب

توابع در پایتون چی هستن و به چه دردی می خورن ؟!

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

همونطور که می دونید، پایتون توابع داخلی بسیاری مثل ()print و غیره را در اختیار شما قرار داده. با این حال شما می تونید توابع خودتان رو هم بسازید. این توابع را، توابع تعریف شده توسط کاربر یا user-defined می نامند.

تعریف یک تابع

شما می تونید توابع را برای فراهم کردن عملکردهای مورد نیاز تعریف کنید. در زیر قوانین ساده جهت تعریف تابع در پایتون اومده.

  1. قطعه کد تابع باید با کلیدواژه ی def آغاز بشه. به دنبال اون اسم تابع و پرانتز درج می شه ( () ).
  2. پارامترهای ورودی یا آرگومان ها باید داخل پرانتز قرار داده بشه.
  3. اولین دستور تابع می تونه یک دستور اختیاری باشه - function_docstring.
  4. قطعه کد داخل ساختمان یا بدنه ی تابع با دو نقطه آغاز می شود، سپس دستوراتی که زیر آن قرار می گیرند، همگی توگذاشته می شوند.
  5. دستور return اجرای تابع رو متوقف کرده نتیجه را برمی گردونه (جمع بندی یک سری عملیات و یا کارهایی رو نمایش می ده) . دستور return None نیز یعنی هیچ مقداری را به عنوان خروجی برنگردونه.

نحوه تعریف تابع

def functionname( parameters ):
   "function_docstring"
   function_suite
   return [expression]

همونطور که در کد بالا مشاهده می کنید تعریف تابع با کلمه کلیدی def شروع شده، سپس نام تابع، داخل پرانتز پارامتر های تابع، علامت : و در ادامه دستوراتی که با فراخوانی تابع باید اجرا شوند.

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

مثال

تابع زیر یک پارامتر ورودی رشته دریافت کرده و آن را چاپ می کنه.

def printme( str ):
   "This prints a passed string into this function"
   print str
   return

فراخوانی تابع

یعنی چطوری یک تابعی که قبلا تعریف کردی رو صدا بزنی.

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

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print str
   return;

# Now you can call printme function
printme("I'm first call to user defined function!")
printme("Again second call to the same function")

وقتی که کد بالا اجرا شد، خروجی زیر ایجاد میشه:

I'm first call to user defined function!
Again second call to the same function

ارسال پارامتر با reference در برابر ارسال با مقدار

تمامی پارامترها در زبان پایتون با reference ارسال می شوند. یعنی اگر شما پارامتر را درون تابع تغییر دهید، این پارامتر همچنین در تابع فراخوانی شده نیز تغییر خواهد کرد.یعنی وقتی داخل تابع چیزی رو تغییر بدی بیرونشم تغییر می کنه. برای مثال:

# Function definition is here
def changeme( mylist ):
   "This changes a passed list into this function"
   mylist.append([1,2,3,4]);
   print "Values inside the function: ", mylist
   return

# Now you can call changeme function
mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

ما داخل تابع ۱و۲و۳و۴ رو اضافه کردیم ولی وقتی بیرون تابع به متغیر نگاه می کنیم می بینیم به اونم اضافه شده. نتیجه:

Values inside the function:  [10, 20, 30, [1, 2, 3, 4]]
Values outside the function:  [10, 20, 30, [1, 2, 3, 4]]

تو مثال دیگه آرگومانی که با reference ارسال شده و reference آن درون تابع فراخوانی شده تغییر می کنه:

# Function definition is here
def changeme( mylist ):
   "This changes a passed list into this function"
   mylist = [1,2,3,4]; # This would assig new reference in mylist
   print "Values inside the function: ", mylist
   return

# Now you can call changeme function
mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

پارامتر mylist، نسبت به تابع changeme محلی (local) هست، تغییر mylist درون تابع تاثیری در mylist نمیذاره. ( به نظرتون چرا ؟! کامنت کنید) تابع در واقع هیچ کاری انجام نداده و خروجی زیر ایجاد میشه:

Values inside the function:  [1, 2, 3, 4]
Values outside the function:  [10, 20, 30]

آرگومان های تابع

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

  • آرگومان های اجباری
  • آرگومان های keyword
  • آرگومان های پیشفرض
  • آرگومان های variable-length

آرگومان های الزامی

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

جهت فراخوانی ()printme، شما نیاز خواهید داشت دقیقا یک آرگومان به آن ارسال کنید، در غیر اینصورت خطای syntax همانند زیر ایجاد خواهد شد:

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print str
   return;

# Now you can call printme function
printme()

خروجی ( که ارور می ده چون می گه یک ورودی نیاز داشت)

Traceback (most recent call last):
   File "test.py", line 11, in <module>
      printme();
TypeError: printme() takes exactly 1 argument (0 given)

آرگومان های Keyword

آرگومان های keyword در فراخوانی توابع مورد استفاده قرار می گیره. هنگامی که از آرگومان های keyword در فراخوانی تابع استفاده می کنید، فراخواننده، آرگومان ها را به وسیله ی اسم آن (پارامتر) شناسایی می کنه. این کار به شما اجازه میده ترتیب آرگومان ها را تغییر بدید، زیرا که مفسر پایتون میتونه با استفاده از کلیدواژه ای ارائه شده، مقادیر رو به پارامترها match (وصل) کند.

مثال زیر فراخوانی keyword در تابع ()printme نشان داده شده است یعنی می فهمه که my string را باید به متغیر Str اختصاص بده و می برش داخل تابع و چاپش می کنه :

#!/usr/bin/python

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print str
   return;

# Now you can call printme function
printme( str = "My string")

خروجی

My string

مثال زیر تصویر واضح تری را ترسیم می کند. توجه داشته باشید که ترتیب پارامترها مشکلی ایجاد نمی کند ترتیب پارامترهارو عوض کردم بازم جواب داد.

#!/usr/bin/python

# Function definition is here
def printinfo( name, age ):
   "This prints a passed info into this function"
   print "Name: ", name
   print "Age ", age
   return;

# Now you can call printinfo function
printinfo( age=50, name="saeed" )

خروجی

Name:  saeed
Age  50

آرگومان پیشفرض

یکی از قابلیت های زبان پایتون امکان مشخص کردن مقادیر پیش فرض برای توابع است، در صورتیکه هیچ مقداری به آرگومان فراخوانی شده اختصاص داده نشود، آرگومان پیشفرض مقدار آن را مشخص می کند. در مثال زیر در صورتی که مقدار age تعیین نشود مقدار پیشفرض آن چاپ می شود:

#!/usr/bin/python

# Function definition is here
def printinfo( name, age = 35 ):
   "This prints a passed info into this function"
   print "Name: ", name
   print "Age ", age
   return;

# Now you can call printinfo function
printinfo( age=50, name="miki" )
printinfo( name="miki" )

خروجی

Name:  miki
Age  50
Name:  miki
Age  35

آرگومان های با طول متغیر variable-length

گاهی لازمه یک تابع رو با آرگومان های بیشتری نسبت به اونچه در زمان تعریف تابع مشخص کردید، پردازش و فراخوانی کنید. این دست از آرگومان ها در اصطلاح آرگومان های با طول متغیر (variable length) خوانده می شوند و برخلاف آرگومان های الزامی و پیش فرض، در تعریف تابع ذکر نمی شوند.

def functionname([formal_args,] *var_args_tuple ):
   "function_docstring"
   function_suite
   return [expression]

علامت ستاره (*) قبل از نام متغیر قرار می گیره و مقادیر تمامی آرگومان هایی که keyword نیستند را در خود نگه میداره. این تاپل (tuple) در صورتیکه آرگومان اضافه ای در فراخوانی تابع تعیین نشه، خالی باقی میمونه. درواقع یعنی اینکه هر چی دلمون خواست موقع صدازدن اون تابع می فرستم داخلش

#!/usr/bin/python

# Function definition is here
def printinfo( arg1, *vartuple ):
   "This prints a variable passed arguments"
   print "Output is: "
   print arg1
   for var in vartuple:
      print var
   return;

# Now you can call printinfo function
printinfo( 10 )
printinfo( 70, 60, 50 )

خروجی

Output is:
10
Output is:
70
60
50

توابع Anonymous

این توابع anonymous نام دارند یعنی بی نام (در واقع اسمی ندارن) و به صورت استاندارد با کلمه کلیدی def تعریف نمی شوند. شما می تونید برای ایجاد توابع کوچک anonymous از کلمه کلیدی lambda استفاده کنید. مثلا در مثال زیر اومدیم دوتا متغیر رو باهم جمع کردیم به تعریفش دقت کنید.

  • فرم lambda میتونه هر تعداد آرگومان دریافت کنه، ولی تنها یک مقدار رو بر می گردونه. lambda ها نمی تونن حاوی چندین عبارت و دستور باشن.
  • تابع anonymous نمیتونه به صورت مستقیم برای چاپ فراخوانی بشه چرا که نیاز به یک عبارت داره.
  • توابع lambda دارای namespace های داخلی خود هستند و تنها به متغیر های موجود در لیست پارامترها و آن هایی که در global تعریف شده اند دسترسی دارند.
  • هر چند اینطور به نظر میرسه که lambda ها نسخه تک خطی توابع هستند، آن ها همانند عبارت inline در C نیستند.

شکل دستوری

lambda [arg1 [,arg2,.....argn]]:expression

مثال زیر فرم lambda و نحوه کارکرد آن را نشان می دهد:

#!/usr/bin/python

# Function definition is here
sum = lambda arg1, arg2: arg1 + arg2;

# Now you can call sum as a function
print "Value of total : ", sum( 10, 20 )
print "Value of total : ", sum( 20, 20 )

خروجی

Value of total :  30
Value of total :  40

عبارت return

عبارت return برای خروج از یک تابع است، که میتونه به طور دلخواه حاوی مقداری برای برگرداندن به فراخوانی تابع باشه. در صورت نیاز برای برگشت مقدار توسط تابع می توان از کلمه کلیدی return استفاده کرد. مثال زیر نحوه برگرداندن مقدار توسط return را نشون می ده:

#!/usr/bin/python

# Function definition is here
def sum( arg1, arg2 ):
   # Add both the parameters and return them."
   total = arg1 + arg2
   print "Inside the function : ", total
   return total;

# Now you can call sum function
total = sum( 10, 20 );
print "Outside the function : ", total

خروجی

Inside the function :  30
Outside the function :  30

روش کار توابع در پایتون


اسکوپ (Scope) متغیرها

مفهومش اینکه که هر متغیری کجای برنامه اعتبار داره.

تمامی متغیرهای موجود در برنامه ممکنه در همه جای برنامه در دسترس نباشند. این موضوع به مکانی که متغیر تعریف شده بستگی داره.

اسکوپ (Scope) یک متغیر تعیین می کنه که یک متغیر در کدام بخش از برنامه قابل دسترسی می باشد. در پایتون دو Scope برای متغیرها وجود داره:

  • متغیرهای Global
  • متغیرهای Local

متغیرهای Local در برابر Global

متغیرهایی که درون بدنه تابع (داخل تابع) تعریف می شوند دارای محدوده local و آن هایی که بیرون از تابع تعریف می شوند دارای محدوده global می باشند.

یعنی متغیرهای local تنها درون تابعی که تعریف شده اند قابل دسترسی هستن، در حالی که متغیرهای global در سراسر بدنه برنامه با تمامی توابع در دسترس هستند. وقتی که شما یک تابع رو فراخوانی می کنید، متغیرهایی که درون اون تعریف شدن به scope آورده می شوند:

#!/usr/bin/python

total = 0; # This is global variable.
# Function definition is here
def sum( arg1, arg2 ):
   # Add both the parameters and return them."
   total = arg1 + arg2; # Here total is local variable.
   print "Inside the function local total : ", total
   return total;

# Now you can call sum function
sum( 10, 20 );
print "Outside the function global total : ", total

خروجی

Inside the function local total :  30
Outside the function global total :  0