توابع

توابع بخش هایی از برنامه هستند که می توان آنها را دوباره استفاده کرد.آن ها به شما این امکان را می دهند تا به یک بلوک از دستورات یک نام بدهید و سپس هر زمان و به هر تعداد که بخواهید، آن دستورات را اجرا کنید. به این کار فراخوانی (Calling) تابع گفته می شود. ما قبلاً از چند تابع داخلی مانند len و range استفاده کرده ایم.

مفهوم تابع احتمالاً مهم ترین جزء سازندۀ هر نرم افزار غیر ساده ای است (در هر زبان برنامه نویسی). بنابراین در این فصل جنبه های مختلف توابع را بررسی خواهیم کرد.

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

مثال را با نام function1.py ذخیره کنید:

def say_hello():
    # block belonging to the function
    print('hello world')
# End of function

say_hello()  # call the function
say_hello()  # call the function again

خروجی:

$ python function1.py
hello world
hello world

نحوۀ عملکرد

ما با استفاده از نحوی که بالا توضیح داده شد، تابعی به نام say_hello تعریف می کنیم. این تابع هیچ پارامتری دریافت نمی کند و به همین دلیل درون پرانتزها هیچ متغیری تعریف نشده است. پارامترهای توابع در واقع ورودی تابع هستند؛ بنابراین می توانیم مقادیر مختلفی را به تابع بدهیم و نتایج متناسب آن ها را دریافت کنیم.

توجه کنید که می توانیم یک تابع را دو بار فراخوانی کنیم؛ بنابراین مجبور نیستیم یک کد یکسان را دو بار بنویسیم.

پارامترهای تابع

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

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

مثال را تحت عنوان function_param.py ذخیره کنید:

def print_max(a, b):
    if a > b:
        print(a, 'is maximum')
    elif a == b:
        print(a, 'is equal to', b)
    else:
        print(b, 'is maximum')

# directly pass literal values
print_max(3, 4)

x = 5
y = 7

# pass variables as arguments
print_max(x, y)

خروجی:

$ python function_param.py
4 is maximum
7 is maximum

نحوۀ عملکرد

در اینجا تابعی به نام print_max تعریف می کنیم که از دو پارامتر به نام های a و b استفاده می کند. با استفاده از یک دستور سادۀ if..else عدد بزرگ تر را پیدا می کنیم و آن را پرینت می کنیم.

در اولین فراخوانی تابع print_max، اعداد را مستقیماً به عنوان آرگومان وارد می کنیم. در حالت دوم، تابع را با متغیرها به عنوان آرگومان فراخوانی می کنیم. عبارت print_max(x, y) باعث می شود مقدار آرگومان x به پارامتر a و مقدار آرگومان y به پارامتر b نسبت داده می شود. تابع print_max در هر دو حالت به یک شکل مشابه عمل می کند.

متغیرهای محلی

وقتی متغیرهایی را داخل تعریف یک تابع ایجاد می کنید، آن ها هیچ ارتباطی با متغیرهایی با همان نام که خارج از تابع استفاده شده اند ندارند؛ یعنی نام متغیرها در تابع، محلی(local) هستند. به این محدوده، دامنۀ متغیر گفته می شود. هر متغیر دارای دامنه ای است که از محل تعریف آن نام آغاز می شود و به بلوکی که متغیر در آن تعریف شده مربوط است.

مثال را با نام function_local.py ذخیره کنید:

x = 50


def func(x):
    print('x is', x)
    x = 2
    print('Changed local x to', x)


func(x)
print('x is still', x)

خروجی:

$ python function_local.py
x is 50
Changed local x to 2
x is still 50

نحوۀ عملکرد

در اولین خط داخل بدنۀ تابع، زمانی که مقدار نام x را چاپ می کنیم، پایتون از مقدار پارامتری استفاده می کند که در بلوک اصلی برنامه، بالاتر از تابع قرار دارد.

سپس مقدار 2 را به x اختصاص می دهیم. نام x برای تابع محلی است. بنابراین وقتی مقدار x را در تابع تغییر می دهیم، مقدار x که در بلوک اصلی تعریف شده است، تغییری نمی کند.

با آخرین دستور print، مقدار x تعریف شده در بلوک اصلی برنامه را نمایش می دهیم و به این ترتیب تایید می کنیم که انتساب محلی داخل تابع، روی آن تاثیری نداشته است.

دستور global

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

می توانید از مقادیر چنین توابعی که خارج از تابع تعریف شده اند استفاده کنید (البته به شرطی که متغیری با همان نام داخل تابع وجود نداشته باشد). با این حال، این کار توصیه نمی شود و بهتر است از آن اجتناب کنید؛ زیرا برای خوانندۀ برنامه مشخص نخواهد بود که تعریف آن متغیر کجاست. استفاده از دستور global به روشنی نشان می دهد که متغیر در یک بلوک بیرونی تعریف شده است.

مثال را با عنوان function_global.py ذخیره کنید:

x = 50


def func():
    global x

    print('x is', x)
    x = 2
    print('Changed global x to', x)


func()
print('Value of x is', x)

خروجی:

$ python function_global.py
x is 50
Changed global x to 2
Value of x is 2

نحوۀ عملکرد

دستور global برای اعلام این موضوع استفاده می شود که x یک متغیر سراسری است - بنابراین وقتی مقدار x داخل تابع را تغییر می دهیم، این تغییر هنگام استفاده از مقدار x در بلوک اصلی برنامه نیز قابل مشاهده خواهد بود.

می توانید با استفاده از چند متغیر سراسری نیز یک دستور مشابه global مشخص کنید؛ برای مثال: global x, y, z.

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

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

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

مثال را با نام function_default.py ذخیره کنید:

def say(message, times=1):
    print(message * times)

say('Hello')
say('World', 5)

خروجی:

$ python function_default.py
Hello
WorldWorldWorldWorldWorld

نحوۀ عملکرد

تابع say برای چاپ کردن یک رشته به تعداد دفعات مشخص استفاده می شود. اگر برای تعداد دفعات مقداری را وارد نکنیم، رشته به طور پیش فرض فقط یک بار چاپ می شود. این کار را با تعیین مقدار پیش فرض 1 برای پارامتر times انجام داده ایم.

در اولین کاربرد say، فقط رشته را وارد می کنیم و رشته یک بار چاپ می شود. در دومین کاربرد say، هم رشته و هم آرگومان 5 را وارد می کنیم و می گوییم می خواهیم پیام 5 دفعه چاپ شود.

هشدار

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

دلیلش این است که مقادیر بر اساس موقعیتشان به پارامترها اختصاص داده می شوند. برای مثال، def func(a, b=5) معتبراست، اما def func(a=5, b) معتبر نیست.

آرگومان های کلیدی

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

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

مثال را با نام function_keyword.py ذخیره کنید:

def func(a, b=5, c=10):
    print('a is', a, 'and b is', b, 'and c is', c)

func(3, 7)
func(25, c=24)
func(c=50, a=100)

خروجی:

$ python function_keyword.py
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50

نحوۀ عملکرد

تابع func یک پارامتر بدون مقدار پیش فرض و دو پارامتر با مقدار پیش فرض دارد.

در اولین کاربرد، func(3 , 7)، پارامتر a مقدار 3 را می گیرد، پارامتر b مقدار 7 و پارامتر c مقدار پیش فرض 10 را می گیرد.

در دومین کاربرد، func(25, c=24)، متغیر a به دلیل موقعیت آرگومان مقدار 25 را دریافت می کند. سپس، پارامتر c به دلیل نام گذاری اش یعنی آرگومان کلیدی مقدار 24 را می گیرد. متغیر b مقدار پیش فرض 5 را دریافت می کند.

در سومین کاربرد، func(c=50, a=100)، برای تمام مقادیر مشخص شده از آرگومان های کلیدی استفاده می کنیم. توجه داشته باشید که مقدار پارامتر c را قبل از a مشخص کرده ایم، با اینکه در تعریف تابع a قبل از c قرار دارد.

پارامترهای متغیر (VarArgs parameters)

گاهی ممکن است بخواهید تابعی تعریف کنید که بتواند هر تعداد پارامتر دریافت کند؛ یعنی تعداد آرگومان ها متغیر باشد. این کار با استفاده از علامت ستاره انجام می شود. (مثال را با نام function_varargs.py ذخیره کنید):

def total(a=5, *numbers, **phonebook):
    print('a', a)

    #iterate through all the items in tuple
    for single_item in numbers:
        print('single_item', single_item)

    #iterate through all the items in dictionary    
    for first_part, second_part in phonebook.items():
        print(first_part,second_part)

total(10,1,2,3,Jack=1123,John=2231,Inge=1560)

خروجی:

$ python function_varargs.py
a 10
single_item 1
single_item 2
single_item 3
Inge 1560
John 2231
Jack 1123

نحوۀ عملکرد

وقتی یک پارامتر ستاره دار مانند param* تعریف می کنیم، تمام آرگومان های موقعیتی از آن نقطه تا انتهای لیست، به صورت یک تاپل با نام 'param' جمع آوری می شوند.

به همین شکل، وقتی پارامتری با دو ستاره مانند param** را تعریف می کنیم، تمام آرگومان های کلیدی از آن نقطه تا انتهای لیست ، به صورت یک دیکشنری با نام 'param' جمع آوری می شوند.

تاپل ها و دیکشنری ها را در later chapter بررسی خواهیم کرد.

دستور return

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

مثال را تحت عنوان function_return.py ذخیره کنید:

def maximum(x, y):
    if x > y:
        return x
    elif x == y:
        return 'The numbers are equal'
    else:
        return y

print(maximum(2, 3))

خروجی:

$ python function_return.py
3

نحوۀ عملکرد

تابع maximum بیشترین مقدار پارامترهای خود، یعنی اعدادی که به تابع داده شدند، را بر می گرداند. این تابع با استفاده از دستور سادۀ if..else مقدار بزرگتر را پیدا کرده و سپس آن مقدار را باز می گرداند.

توجه داشته باشید که دستور return بدون مقدار، معادل return None است. توجه کنید که None یک نوع ویژه در پایتون است که نشان دهندۀ نبود مقدار است. برای مثال، زمانی استفاده می شود که نشان دهد یک متغیر مقداری ندارد و مقدار آن None است.

هر تابع به طور ضمنی در انتهای خود شامل یک return None است؛ مگر اینکه خودتان یک دستور return نوشته باشید. می توانید این موضوع را با اجرای print(some_function()) مشاهده کنید؛ در حالی که تابع some_function از دستور return استفاده نمی کند. مثلاً:

def some_function():
    pass

دستور pass در پایتون برای نشان دادن یک بلوک خالی از دستورات استفاده می شود.

نکته: یک تابع داخلی به نام max وجود دارد که از قبل قابلیت «پیدا کردن بیشترین مقدار» را پیاده سازی کرده است؛ بنابراین هر زمان امکانش وجود دارد، از همین تابع داخلی استفاده کنید.

DocStrings

پایتون قابلیتی بسیار کاربردی به نام رشته های مستند سازی (documentation strings) دارد که معمولاً با نام کوتاه تر docstrings شناخته می شود. قابلیت Docstrings ابزار مهمی است که باید از آنها استفاده کنید زیرا برنامه بهتر مستند می شود و درک آن را آسان تر می کند. جالب تر اینکه حتی می توانیم هنگام اجرای برنامه، Docstring مربوط به یک تابع را دوباره دریافت کنبم!

مثال را با نام function_docstring.py ذخیره کنید:

def print_max(x, y):
    '''Prints the maximum of two numbers.

    The two values must be integers.'''
    # convert to integers, if possible
    x = int(x)
    y = int(y)

    if x > y:
        print(x, 'is maximum')
    else:
        print(y, 'is maximum')

print_max(3, 5)
print(print_max.__doc__)

خروجی:

$ python function_docstring.py
5 is maximum
Prints the maximum of two numbers.

    The two values must be integers.

نحوۀ عملکرد

رشته ای که در اولین خط منطقی یک تابع قرار می گیرد، docstring آن تابع است. توجه داشته باشید که Docstringها برای modules و classes کاربرد دارند که در فصل های مربوطه به یادگیری آنها خواهیم پرداخت.

قرارداد رایج برای Docstringها به این صورت است که از یک رشتۀ چند خطی استفاده کنیم؛ خط اول با یک حرف بزرگ شروع شده و با نقطه به پایان می رسد. سپس برای خط دوم یک خط خالی قرار می گیرد و از خط سوم، توضیحات کامل تر و با جزئیات تری نوشته می شود. اکیداً توصیه می شود برای تمام توابع غیرساده ای که می نویسید، این قرارداد را در Docstringهای خود رعایت کنید.

می توانیم Docstring تابع print_max را با استفاده از ویژگی __doc__ آن دریافت کنیم. (به دو زیرخط در انتها و ابتدای آن توجه کنید). فقط به خاطر داشته باشید که پایتون با همه چیز مانند یک شئ رفتار می کند و این امر شامل تابع ها نیز می شود. در فصل مربوط به classes دربارۀ اشیا بیشتر یاد خواهیم گرفت.

اگر قبلاً از ()help در پایتون استفاده کرده باشید، در واقع با کاربرد Docstringها مواجه شده اید! کاری که ()help در پایتون انجام می دهد این است که ویژگی __doc__ تابع را دریافت کرده و آن را به شکل خوانا و مرتب نمایش می دهد. می توانید این کار را برای تابع بالا امتحان کنید؛ کافیست help(print_max) را در برنامۀ خود قرار دهید. به یاد داشته باشید که برای خروج از help از کلید q استفاده کنید.

ابزارهای خودکار نیز می توانند به همین روش مستندات را از برنامۀ شما استخراج کنند. بنابراین، اکیداً توصیه می کنم برای هر تابع غیرساده ای که می نویسید از Docstringها استفاده کنید. دستور pydoc که به همراه توزیع پایتون ارائه می شود نیز روشی مشابه ()help دارد و از Docstringها استفاده می کند.

جمع بندی

در این بخش جنبه های مختلف و متعددی از توابع را بررسی کردیم؛ البته توجه داشته باشید که هنوز تمام جوانب توابع را پوشش نداده ایم. با این حال، بیشتر چیزهایی را که در استفادۀ روزمره از توابع پایتون به آنها نیاز خواهید داشت، آموختیم.

در فصل بعد، نحوۀ استفاده و همچنین ایجاد Modules در پایتون را بررسی خواهیم کرد.

results matching ""

    No results matching ""