توابع
تا اینجا برنامههای ما یک تکه بلند بودند. تابع به شما اجازه میدهد کد را به قطعههای کوچک نامدار بشکنید و هر قطعه را هر جا لازم شد دوباره به کار ببرید. این نقطهای است که برنامهنویسی حرفهای شروع میشود.
۱. چرا تابع
فرض کنید در سه جای برنامهتان باید تشخیص دهید عددی اول است یا نه. بدون تابع، همان ده خط را سه بار کپی میکنید. حالا اگر باگی در آن ده خط پیدا شود، باید سه جا را اصلاح کنید و حتماً یکی را فراموش میکنید.
تابع سه چیز به شما میدهد:
- عدم تکرار. کد یک بار نوشته میشود و هر جا لازم شد صدا زده میشود.
- نامگذاری.
is_prime(n)در یک نگاه فهمیده میشود، ده خط حلقه و شرط نه. - تقسیم مسئله. مسئله بزرگ به چند مسئله کوچک تبدیل میشود که هر کدام جدا قابل حل و قابل آزمایشاند.
۲. اولین تابع
# 'def' defines a function. The body is indented, exactly like a loop body.
# Defining a function does NOT run it.
def hello():
print('Hello World!')
# The function only runs when we CALL it, with parentheses.
hello()
hello()
hello()
اولین تابع: نمونه 01_first_function.py
Hello World! Hello World! Hello World!
شرح مثال
- کلمه کلیدی
def، بعد نام تابع، بعد پرانتز، بعد دونقطه. بدنه تو رفته است، مثل بدنهifوfor. - تعریف تابع آن را اجرا نمیکند. فقط به پایتون میگوید «این دستور را با این نام یاد بگیر».
- برای اجرا باید صدایش بزنید: نام تابع با پرانتز. بدون پرانتز، فقط به خود تابع اشاره میکنید و هیچ اتفاقی نمیافتد.
- نام تابع همان قواعد نام متغیر را دارد: حروف کوچک، کلمات با زیرخط، و معنادار. معمولاً فعل است، چون تابع کاری انجام میدهد.
۳. پارامتر و آرگومان
تابعی که همیشه یک کار ثابت انجام دهد محدود است. با پارامتر میشود به تابع اطلاعات داد.
# A parameter is a variable that receives a value when the function is called.
def hello(name):
print('Hello', name)
# 'Matin', 'Maryam' and 'Raha' are the arguments.
hello('Matin')
hello('Maryam')
hello('Raha')
# A function may have several parameters; their ORDER matters.
def introduce(name, city):
print(f'{name} lives in {city}.')
introduce('Ali', 'Rasht')
پارامترها: نمونه 02_parameters.py
| اصطلاح | یعنی | در مثال |
|---|---|---|
| پارامتر | نام متغیر در تعریف تابع | name |
| آرگومان | مقدار واقعی موقع صدا زدن | 'Matin' |
ترتیب آرگومانها مهم است. اگر بنویسید
introduce('Rasht', 'Ali')، تابع میگوید «Rasht در Ali
زندگی میکند». پایتون نمیفهمد اشتباه کردهاید. در فصل بعد راهی
میبینید که این خطا را از بین میبرد.
۴. دستور return
تا اینجا توابع ما فقط چاپ میکردند. return نتیجه را به جایی
که تابع صدا زده شده برمیگرداند، تا بشود با آن کار کرد.
# 'return' sends a value back to the place where the function was called.
def add(number1, number2):
total = number1 + number2
return total
# The returned value can be stored ...
c = add(3, 2)
print(c)
d = add(7, 4)
print(d)
# ... or used directly.
print(add(3, 2))
print(add(1, 2) + add(3, 4))
# 'return' also ENDS the function immediately.
def first_positive(a, b):
if a > 0:
return a
return b # only reached when a is not positive
print(first_positive(-5, 8))
برگرداندن مقدار: نمونه 03_return.py
5 11 5 10 8
شرح مثال
- مقدار برگشتی را میشود در متغیر ذخیره کرد، مستقیم چاپ کرد، یا در یک محاسبه بزرگتر به کار برد.
returnتابع را فوراً تمام میکند. هیچ خطی بعد از آن اجرا نمیشود.- به همین دلیل در
first_positiveنیازی بهelseنیست: اگر شرط برقرار باشد، اجرا باreturn aتمام شده است. - یک تابع میتواند چند
returnداشته باشد، ولی فقط یکی از آنها اجرا میشود.
۵. تابع بدون return و مقدار None
# A function that only prints does NOT give a value back:
# its result is the special value None.
def show_sum(a, b):
print(a + b)
result = show_sum(2, 3)
print(result) # None
# A function that returns can be reused in other calculations.
def get_sum(a, b):
return a + b
result = get_sum(2, 3)
print(result * 10) # 50
# Rule of thumb: compute with 'return', display with 'print' - not both.
print در برابر return: نمونه 04_return_none.py
5 None 50
print و return دو چیز کاملاً متفاوتند.
print چیزی را به کاربر نشان میدهد و
return چیزی را به برنامه پس میدهد.
تابعی که فقط چاپ میکند، نتیجهاش None است و نمیشود
با آن حساب کرد. قانون: محاسبه با return، نمایش با
print، و ترجیحاً نه هر دو در یک تابع.
None نوع خاصی در پایتون است که یعنی «هیچ مقداری». هر تابعی که return نداشته باشد، به طور خودکار None برمیگرداند. به خاطر دارید که list.sort() هم همین کار را میکرد.
۶. تابعی که تصمیم میگیرد
# A function that compares two numbers and returns the bigger one.
# (Python already has max(); we write it here to practise.)
def bigger(num1, num2):
if num1 > num2:
return num1
return num2
user_input = input('Enter the first number: ')
a = float(user_input)
user_input = input('Enter the second number: ')
b = float(user_input)
print('Max:', bigger(a, b))
بزرگتر از دو عدد: نمونه 05_max_of_two.py
دقت کنید که تابع هیچ ارتباطی با input ندارد. تابع فقط دو
عدد میگیرد و یکی برمیگرداند. گرفتن ورودی کار برنامه اصلی است. این
جدایی بسیار مهم است: تابعی که ورودی نمیگیرد و چاپ
نمیکند، در هر برنامه دیگری هم قابل استفاده است.
۷. برگرداندن مقدار بولی
# Three ways of writing the same function, from the longest to the shortest.
def is_even_v1(number):
if number % 2 == 0:
return True
else:
return False
def is_even_v2(number):
if number % 2 == 0:
return True
return False # the else is not needed: return already exits
def is_even_v3(number):
return number % 2 == 0 # the comparison IS already True or False
number = 4
# A function that returns a bool can be used directly inside an if.
if is_even_v3(number):
print('Even')
else:
print('Odd')
print(is_even_v1(7), is_even_v2(7), is_even_v3(7))
سه سبک نوشتن یک تابع: نمونه 06_is_even.py
شرح مثال
- هر سه نسخه دقیقاً یک کار میکنند. نسخه سوم پایتونیترین است: خود مقایسه یک مقدار بولی است، پس مستقیم برگردانیدش.
- نوشتن
if x == True: return True else: return Falseنشانه تازهکار بودن است. آن را کوتاه کنید. - نام توابعی که بولی برمیگردانند معمولاً با
is_یاhas_شروع میشود. این قرارداد به خواننده میگوید انتظار جواب بله یا خیر داشته باشد. - چنین تابعی مستقیم داخل
ifمینشیند و کد را بسیار خوانا میکند.
۸. تابع تشخیص عدد اول
# The prime test of session 08, turned into a reusable function.
def is_prime(number):
# 0, 1 and the negative numbers are not prime.
if number < 2:
return False
for i in range(2, number):
if number % i == 0:
return False # a divisor was found -> stop immediately
return True # no divisor was found
user_input = input('Enter a number: ')
n = int(user_input)
if is_prime(n):
print('Prime!')
else:
print('Not prime.')
# The same function on a whole list of numbers.
numbers = [13, 11, 6, 8, 2, 7, 21, 1, 0, -3]
for num in numbers:
print(num, is_prime(num))
تابع عدد اول: نمونه 07_is_prime.py
این همان الگوریتم فصل هشتم است، ولی حالا داخل تابع. مقایسه کنید:
نسخه فصل هشتم به متغیر پرچم و break نیاز داشت. اینجا
return جای هر دو را میگیرد و کد کوتاهتر و روشنتر است.
این یکی از مزیتهای پنهان تابع است.
۹. استفاده از تابع در حلقه
# Once the function exists, answering a bigger question is easy.
def is_prime(number):
if number < 2:
return False
# Testing up to the square root is enough: a divisor bigger than the root
# always has a partner smaller than the root.
i = 2
while i * i <= number:
if number % i == 0:
return False
i += 1
return True
count = 0
for number in range(50000, 100000):
if is_prime(number):
count += 1
print('Number of primes between 50000 and 100000:', count)
شمردن اعداد اول: نمونه 08_count_primes.py
شرح مثال
- وقتی تابع آماده باشد، پاسخ به سؤال بزرگتر فقط چهار خط است. این قدرت واقعی تابع است.
- یک بهینهسازی مهم اینجا اضافه شده: به جای امتحان کردن همه اعداد تا
number، فقط تا جذر آن میرویم. شرطi * i <= numberهمین را میگوید. - چرا جذر کافی است؟ چون اگر عددی مقسومعلیهی بزرگتر از جذرش داشته باشد، حتماً یک مقسومعلیه کوچکتر از جذر هم دارد که قبلاً پیدایش کردهایم.
- این بهینهسازی برای عددهای بزرگ تفاوت بین چند ثانیه و چند دقیقه است. هر دو نسخه را اجرا کنید و زمانش را ببینید.
۱۰. تابعی که تابع دیگر را صدا میزند
# A function may call another function. Here pow() is built on top of mul().
def mul(num1, num2):
'Multiply two whole numbers using repeated addition.'
result = 0
for i in range(num2):
result += num1
return result
def power(num1, num2):
'Raise num1 to the power num2 using repeated multiplication.'
result = 1
for i in range(num2):
result = mul(result, num1)
return result
a = int(input('Enter the base: '))
b = int(input('Enter the exponent: '))
print(power(a, b))
تابع روی تابع: نمونه 09_function_calls_function.py
شرح مثال
- ضرب را با جمع مکرر میسازیم، بعد توان را با ضرب مکرر. هر لایه روی لایه قبلی سوار میشود.
- این همان شکلی است که همه نرمافزارهای بزرگ ساخته میشوند: توابع ساده در پایین، توابع پیچیدهتر روی آنها.
- آن رشته زیر خط
defیک مستند است و توضیح میدهد تابع چه کار میکند. در فصل سیزدهم شکل استاندارد و سهگیومهایاش را میبینید. - توجه: انباره
mulاز صفر شروع میشود چون جمع است، و انبارهpowerاز یک، چون ضرب است. همان قاعده فصل ششم.
۱۱. کجا تابع را تعریف کنیم
پایتون فایل را از بالا به پایین میخواند. پس تابع باید پیش از اولین جایی که صدا زده میشود تعریف شده باشد. در عمل، همه توابع را بالای فایل مینویسند و کد اصلی را پایین.
# Right: define first, call later.
def greet(name):
return f'Hello {name}'
print(greet('Ali'))
# Wrong: this would raise NameError, because greet2 does not exist yet.
# print(greet2('Ali'))
# def greet2(name):
# return f'Hello {name}'
ترتیب تعریف و صدا زدن
استثنا: یک تابع میتواند تابعی را صدا بزند که پایینتر تعریف شده است،
به شرطی که موقع اجرا هر دو تعریف شده باشند. چون بدنه
تابع فقط هنگام صدا زدن اجرا میشود، نه هنگام تعریف. در فصل بعد با
الگوی main() این را مرتب میکنیم.
پوشه S11-functions-basics شامل نمونههای
01_first_function.py تا 10_multiplication.py.
خلاصه فصل
| ابزار | وظیفه آن |
|---|---|
def name(): | تعریف تابع. اجرا نمیشود تا صدا زده شود |
name() | صدا زدن تابع |
| پارامتر | متغیر داخل تعریف تابع |
| آرگومان | مقدار واقعی موقع صدا زدن |
return x | پس دادن نتیجه و تمام کردن فوری تابع |
None | نتیجه تابعی که return ندارد |
return a == b | راه پایتونی برگرداندن بولی |
is_ در نام | قرارداد نامگذاری توابعی که بولی برمیگردانند |
| ترتیب تعریف | تابع باید پیش از صدا زده شدن تعریف شده باشد |
تمرینهای فصل یازده
- تابع
square(n)را بنویسید که مربع یک عدد را برگرداند. - تابع
celsius_to_fahrenheit(c)را بنویسید و با سه مقدار امتحانش کنید. - تابع
is_leap(year)را بنویسید که برای سال کبیسهTrueبرگرداند. - تابع
count_vowels(text)را بنویسید که تعداد حروف صدادار یک جمله را برگرداند. - تابع
average(a, b, c)را بنویسید که میانگین سه عدد را برگرداند. - تابع
factorial(n)را بنویسید و با آن ترکیبC(n, k) = n! / (k! * (n-k)!)را حساب کنید. - تابع
reverse_text(text)را بدون استفاده از برش بنویسید. - تابع
is_palindrome(text)را با کمک تابع تمرین قبل بنویسید.