🐍 آموزش جامع Python — پست ۷۴
Pattern Matching با
در
🔹 مثال ساده
خروجی:
Python کلیدهای
🔹 بررسی یک کلید خاص
لازم نیست تمام کلیدهای دیکشنری را در الگو بنویسیم:
خروجی:
🔹 ترکیب با شرط
میتوانیم بعد از Pattern Matching از
⚠️ نکته مهم
در Pattern Matching با
مثلاً این الگو:
میتواند با این دیکشنری هم مطابقت داشته باشد:
🧠 خلاصه
🎯 تمرین
کدی بنویسید که دیکشنری زیر را بررسی کند:
اگر
در غیر این صورت:
پست ۷۴ از دوره جامع Python 🐍
Pattern Matching با
dictدر
match میتوانیم ساختار یک دیکشنری (dict) را هم بررسی کنیم.🔹 مثال ساده
user = {"name": "Ali", "age": 20}
match user:
case {"name": name, "age": age}:
print(name)
print(age)
case _:
print("Invalid data")خروجی:
Ali
20
Python کلیدهای
name و age را بررسی میکند و مقدارهای آنها را در متغیرهای name و age قرار میدهد.🔹 بررسی یک کلید خاص
لازم نیست تمام کلیدهای دیکشنری را در الگو بنویسیم:
user = {"name": "Ali", "age": 20, "admin": True}
match user:
case {"admin": True}:
print("Admin user")
case _:
print("Normal user")خروجی:
Admin user
🔹 ترکیب با شرط
میتوانیم بعد از Pattern Matching از
if هم استفاده کنیم:user = {"name": "Ali", "age": 20}
match user:
case {"name": name, "age": age} if age >= 18:
print(f"{name} is an adult")
case _:
print("Other user")⚠️ نکته مهم
در Pattern Matching با
dict، وجود کلیدهای اضافه معمولاً مانع تطبیق نمیشود.مثلاً این الگو:
case {"name": name}:میتواند با این دیکشنری هم مطابقت داشته باشد:
{"name": "Ali", "age": 20}🧠 خلاصه
case {"name": name} → استخراج مقدار name
case {"admin": True} → بررسی مقدار یک کلید🎯 تمرین
کدی بنویسید که دیکشنری زیر را بررسی کند:
user = {
"name": "Sara",
"age": 25,
"admin": True
}اگر
admin برابر True بود، چاپ کند:Admin
در غیر این صورت:
Normal user
پست ۷۴ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۷۵
تطبیق اشیاء با
در پستهای قبل دیدیم که
حالا میخواهیم ببینیم چطور میتوانیم ساختار یک شیء را هم بررسی کنیم.
🔹 مثال
برای این بخش از یک کلاس ساده استفاده میکنیم:
خروجی:
🔹 شرط روی مقدار استخراجشده
میتوانیم بعد از تطبیق، شرط هم قرار دهیم:
خروجی:
⚠️ نکته مهم
هر مقدار موقعیتی به کدام ویژگی کلاس مربوط شود.
در مثال ما:
🧠 خلاصه
🎯 تمرین
کلاس زیر را بسازید:
سپس با
پست ۷۵ از دوره جامع Python 🐍
تطبیق اشیاء با
matchدر پستهای قبل دیدیم که
match میتواند با لیست و دیکشنری کار کند.حالا میخواهیم ببینیم چطور میتوانیم ساختار یک شیء را هم بررسی کنیم.
🔹 مثال
برای این بخش از یک کلاس ساده استفاده میکنیم:
class User:
__match_args__ = ("name", "age")
def __init__(self, name, age):
self.name = name
self.age = age
user = User("Ali", 20)
match user:
case User(name, age):
print(name)
print(age)
case _:
print("Unknown user")
خروجی:
Ali
20
🔹 شرط روی مقدار استخراجشده
میتوانیم بعد از تطبیق، شرط هم قرار دهیم:
match user:
case User(name, age) if age >= 18:
print(f"{name} is an adult")
case User(name, age):
print(f"{name} is a minor")
خروجی:
Ali is an adult
⚠️ نکته مهم
__match_args__ مشخص میکند وقتی مینویسیم:case User(name, age):
هر مقدار موقعیتی به کدام ویژگی کلاس مربوط شود.
در مثال ما:
name → user.name
age → user.age
🧠 خلاصه
match میتواند علاوه بر مقدارهای ساده و ساختارهایی مثل list و dict، با اشیاء کلاسها نیز Pattern Matching انجام دهد.🎯 تمرین
کلاس زیر را بسازید:
class Product:
__match_args__ = ("name", "price")
def __init__(self, name, price):
self.name = name
self.price = price
سپس با
match بررسی کنید:price >= 100 → Expensive
price < 100 → Cheap
پست ۷۵ از دوره جامع Python 🐍
👍1
🐍 آموزش جامع Python — پست ۷۶
محدوده متغیرها |
تا اینجا بیشتر متغیرها را در سطح اصلی برنامه تعریف کردیم.
حالا باید با مفهوم Scope یا محدوده دسترسی متغیرها آشنا شویم.
🔹 متغیر در محدوده اصلی
متغیر
🔹 متغیر داخل شرط
در Python، ایجاد شدن متغیر داخل
🔹 متغیر داخل تابع
اینجا
اگر خارج از تابع بنویسیم:
با خطا مواجه میشویم، چون
🔹 متغیر سراسری
تابع میتواند متغیر سراسری
⚠️ نکته مهم
وجود
🧠 خلاصه
در پستهای بعدی Scope و نحوه کار متغیرها در توابع را دقیقتر بررسی میکنیم.
🎯 تمرین
خروجی کد زیر را پیشبینی کنید:
پست ۷۶ از دوره جامع Python 🐍
محدوده متغیرها |
Scopeتا اینجا بیشتر متغیرها را در سطح اصلی برنامه تعریف کردیم.
حالا باید با مفهوم Scope یا محدوده دسترسی متغیرها آشنا شویم.
🔹 متغیر در محدوده اصلی
name = "Ali"
print(name)
متغیر
name در محدوده اصلی برنامه قرار دارد و از همان محدوده قابل دسترسی است.🔹 متغیر داخل شرط
if True:
age = 20
print(age)
در Python، ایجاد شدن متغیر داخل
if یک Scope جداگانه ایجاد نمیکند؛ بنابراین age در این مثال قابل دسترسی است.🔹 متغیر داخل تابع
def show_name():
name = "Ali"
print(name)
show_name()
اینجا
name داخل تابع تعریف شده است.اگر خارج از تابع بنویسیم:
def show_name():
name = "Ali"
show_name()
print(name)
با خطا مواجه میشویم، چون
name یک متغیر محلی (Local) است.🔹 متغیر سراسری
name = "Ali"
def show_name():
print(name)
show_name()
تابع میتواند متغیر سراسری
name را بخواند.⚠️ نکته مهم
وجود
if بهتنهایی Scope جدید ایجاد نمیکند، اما تابع Scope محلی ایجاد میکند.🧠 خلاصه
Global → محدوده اصلی برنامه
Local → محدوده داخل تابع
if → Scope جداگانه ایجاد نمیکند
در پستهای بعدی Scope و نحوه کار متغیرها در توابع را دقیقتر بررسی میکنیم.
🎯 تمرین
خروجی کد زیر را پیشبینی کنید:
x = 10
if True:
y = 20
print(x)
print(y)
پست ۷۶ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۷۷
تغییر متغیر سراسری با
در پست قبل با Global و Local Scope آشنا شدیم.
حالا میبینیم اگر بخواهیم داخل یک تابع، مقدار یک متغیر سراسری را تغییر دهیم، چه اتفاقی میافتد.
🔹 مشکل چیست؟
خروجی:
چون
🔹 استفاده از
با
خروجی:
🔹 مثال کاربردی
خروجی:
هر بار که تابع اجرا میشود، همان متغیر سراسری
⚠️ نکته مهم
استفاده زیاد از
در برنامههای واقعی، اغلب بهتر است بهجای تغییر مستقیم متغیرهای سراسری، از پارامترها و مقدار بازگشتی (
🧠 خلاصه
🎯 تمرین
خروجی کد زیر را پیشبینی کنید:
پست ۷۷ از دوره جامع Python 🐍
تغییر متغیر سراسری با
globalدر پست قبل با Global و Local Scope آشنا شدیم.
حالا میبینیم اگر بخواهیم داخل یک تابع، مقدار یک متغیر سراسری را تغییر دهیم، چه اتفاقی میافتد.
🔹 مشکل چیست؟
count = 10
def increase():
count = 20
increase()
print(count)
خروجی:
10
چون
count = 20 داخل تابع، یک متغیر محلی جدید ایجاد میکند و متغیر سراسری را تغییر نمیدهد.🔹 استفاده از
globalبا
global به Python میگوییم منظورمان همان متغیر سراسری است:count = 10
def increase():
global count
count = 20
increase()
print(count)
خروجی:
20
🔹 مثال کاربردی
score = 0
def add_score():
global score
score += 10
add_score()
add_score()
print(score)
خروجی:
20
هر بار که تابع اجرا میشود، همان متغیر سراسری
score تغییر میکند.⚠️ نکته مهم
استفاده زیاد از
global معمولاً باعث میشود کد سختتر قابل مدیریت و آزمایش باشد.در برنامههای واقعی، اغلب بهتر است بهجای تغییر مستقیم متغیرهای سراسری، از پارامترها و مقدار بازگشتی (
return) استفاده کنیم که در فصل توابع بهطور کامل یاد میگیریم.🧠 خلاصه
متغیر داخل تابع → Local
متغیر خارج تابع → Global
global → اجازه تغییر متغیر Global داخل تابع
🎯 تمرین
خروجی کد زیر را پیشبینی کنید:
number = 5
def change():
global number
number += 10
change()
change()
print(number)
پست ۷۷ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۷۸
قانون
وقتی Python با یک نام متغیر مواجه میشود، باید پیدا کند که مقدار آن از کجا میآید.
برای این کار از ترتیب LEGB استفاده میکند.
🔹 L — Local
ابتدا داخل محدوده فعلی، معمولاً داخل تابع، جستوجو میشود:
خروجی:
چون
🔹 E — Enclosing
اگر تابعی داخل تابع دیگری باشد، Python در تابع بیرونی هم جستوجو میکند:
خروجی:
🔹 G — Global
اگر در محدودههای محلی پیدا نشود، Python در محدوده اصلی برنامه جستوجو میکند:
خروجی:
🔹 B — Built-in
در نهایت Python در نامهای داخلی خودش جستوجو میکند.
مثلاً:
🧠 ترتیب LEGB
Python این محدودهها را به همین ترتیب بررسی میکند.
⚠️ نکته مهم
اگر یک نام در چند محدوده وجود داشته باشد، نزدیکترین محدوده اولویت دارد.
خروجی
🎯 تمرین
خروجی کد زیر را قبل از اجرا پیشبینی کنید:
پست ۷۸ از دوره جامع Python 🐍
قانون
LEGB در Scopeوقتی Python با یک نام متغیر مواجه میشود، باید پیدا کند که مقدار آن از کجا میآید.
برای این کار از ترتیب LEGB استفاده میکند.
🔹 L — Local
ابتدا داخل محدوده فعلی، معمولاً داخل تابع، جستوجو میشود:
name = "Global"
def show():
name = "Local"
print(name)
show()
خروجی:
Local
چون
name محلی وجود دارد.🔹 E — Enclosing
اگر تابعی داخل تابع دیگری باشد، Python در تابع بیرونی هم جستوجو میکند:
def outer():
name = "Outer"
def inner():
print(name)
inner()
outer()
خروجی:
Outer
🔹 G — Global
اگر در محدودههای محلی پیدا نشود، Python در محدوده اصلی برنامه جستوجو میکند:
name = "Global"
def show():
print(name)
show()
خروجی:
Global
🔹 B — Built-in
در نهایت Python در نامهای داخلی خودش جستوجو میکند.
مثلاً:
print(len("Python"))len یک نام Built-in است.🧠 ترتیب LEGB
L → Local
E → Enclosing
G → Global
B → Built-in
Python این محدودهها را به همین ترتیب بررسی میکند.
⚠️ نکته مهم
اگر یک نام در چند محدوده وجود داشته باشد، نزدیکترین محدوده اولویت دارد.
name = "Global"
def show():
name = "Local"
print(name)
show()
خروجی
Local است، نه Global.🎯 تمرین
خروجی کد زیر را قبل از اجرا پیشبینی کنید:
x = "Global"
def outer():
x = "Outer"
def inner():
x = "Inner"
print(x)
inner()
outer()
پست ۷۸ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۷۹
تغییر متغیر تابع بیرونی با
در پست قبل با بخش Enclosing در قانون
حالا میبینیم اگر بخواهیم داخل یک تابع داخلی، متغیر تابع بیرونی را تغییر دهیم، از
🔹 مثال ساده
خروجی:
بدون
باعث میشود Python آن را بهعنوان استفاده از یک متغیر محلی در
🔹 چند بار تغییر مقدار
خروجی:
هر بار
⚠️ تفاوت
مثلاً:
به متغیر سراسری اشاره میکند، اما:
به متغیر موجود در تابع بیرونی اشاره میکند.
🧠 خلاصه
🎯 تمرین
کد زیر را کامل کنید تا هر بار اجرای
خروجی مورد انتظار:
پست ۷۹ از دوره جامع Python 🐍
تغییر متغیر تابع بیرونی با
nonlocalدر پست قبل با بخش Enclosing در قانون
LEGB آشنا شدیم.حالا میبینیم اگر بخواهیم داخل یک تابع داخلی، متغیر تابع بیرونی را تغییر دهیم، از
nonlocal استفاده میکنیم.🔹 مثال ساده
def outer():
count = 0
def inner():
nonlocal count
count += 1
inner()
print(count)
outer()
خروجی:
1
بدون
nonlocal، دستور:count += 1
باعث میشود Python آن را بهعنوان استفاده از یک متغیر محلی در
inner در نظر بگیرد و خطا ایجاد شود.🔹 چند بار تغییر مقدار
def counter():
count = 0
def increase():
nonlocal count
count += 1
return count
print(increase())
print(increase())
print(increase())
counter()
خروجی:
1
2
3
هر بار
inner اجرا میشود، همان count متعلق به outer تغییر میکند.⚠️ تفاوت
global و nonlocalglobal → متغیر در محدوده اصلی برنامه
nonlocal → متغیر در تابع بیرونی
مثلاً:
global count
به متغیر سراسری اشاره میکند، اما:
nonlocal count
به متغیر موجود در تابع بیرونی اشاره میکند.
🧠 خلاصه
Local → داخل تابع فعلی
Enclosing → تابع بیرونی
global → محدوده اصلی برنامه
nonlocal → تغییر متغیر تابع بیرونی
🎯 تمرین
کد زیر را کامل کنید تا هر بار اجرای
increase() مقدار count را یک واحد افزایش دهد:def counter():
count = 0
def increase():
# کد را اینجا بنویسید
count += 1
print(count)
increase()
increase()
increase()
counter()
خروجی مورد انتظار:
1
2
3
پست ۷۹ از دوره جامع Python 🐍
👍1
🐍 آموزش جامع Python — پست ۸۰
ذخیره تابع در متغیر
در Python، تابعها خودشان یک مقدار (Object) هستند.
بنابراین میتوانیم یک تابع را داخل یک متغیر قرار دهیم و بعد از آن متغیر برای اجرای تابع استفاده کنیم.
🔹 مثال ساده
خروجی:
اینجا:
به این معنی است که
🔹 نکته مهم درباره
تفاوت این دو را دقت کنید:
یعنی خود تابع را در متغیر قرار بده.
اما:
یعنی تابع را همین الان اجرا کن و نتیجه اجرای آن را در متغیر قرار بده.
🔹 مثال با مقدار بازگشتی
خروجی:
🧠 خلاصه
بعد از این:
تابع
🎯 تمرین
تابعی به نام
سپس:
و با استفاده از
پست ۸۰ از دوره جامع Python 🐍
ذخیره تابع در متغیر
در Python، تابعها خودشان یک مقدار (Object) هستند.
بنابراین میتوانیم یک تابع را داخل یک متغیر قرار دهیم و بعد از آن متغیر برای اجرای تابع استفاده کنیم.
🔹 مثال ساده
def greet():
print("Hello!")
my_function = greet
my_function()
خروجی:
Hello!
اینجا:
my_function = greet
به این معنی است که
my_function به همان تابع greet اشاره میکند.🔹 نکته مهم درباره
()تفاوت این دو را دقت کنید:
my_function = greet
یعنی خود تابع را در متغیر قرار بده.
اما:
my_function = greet()
یعنی تابع را همین الان اجرا کن و نتیجه اجرای آن را در متغیر قرار بده.
🔹 مثال با مقدار بازگشتی
def add(a, b):
return a + b
operation = add
result = operation(10, 5)
print(result)
خروجی:
15
🧠 خلاصه
greet → خود تابع
greet() → اجرای تابع
my_function = greet
بعد از این:
my_function()
تابع
greet اجرا میشود.🎯 تمرین
تابعی به نام
square بنویسید که یک عدد دریافت کند و مربع آن را برگرداند.سپس:
operation = square
و با استفاده از
operation تابع را اجرا کنید.پست ۸۰ از دوره جامع Python 🐍
26👍1
🐍 آموزش جامع Python — پست ۸۱
ارسال تابع به تابع دیگر
در Python میتوانیم یک تابع را بهعنوان آرگومان به تابع دیگری ارسال کنیم.
این قابلیت یکی از ویژگیهای مهم توابع در Python است.
🔹 مثال ساده
خروجی:
اینجا:
خود تابع
🔹 تابع با آرگومان
خروجی:
در اینجا
⚠️ نکته مهم
این دو با هم فرق دارند:
ارسال تابع
اما:
ابتدا
🧠 خلاصه
🎯 تمرین
دو تابع بنویسید:
سپس:
خروجی مورد انتظار:
پست ۸۱ از دوره جامع Python 🐍
ارسال تابع به تابع دیگر
در Python میتوانیم یک تابع را بهعنوان آرگومان به تابع دیگری ارسال کنیم.
این قابلیت یکی از ویژگیهای مهم توابع در Python است.
🔹 مثال ساده
def greet():
return "Hello Python"
def execute(function):
print(function())
execute(greet)
خروجی:
Hello Python
اینجا:
execute(greet)
خود تابع
greet را ارسال کردهایم، نه نتیجه اجرای آن.🔹 تابع با آرگومان
def square(x):
return x * x
def calculate(function, number):
return function(number)
result = calculate(square, 5)
print(result)
خروجی:
25
در اینجا
calculate هر تابعی را که بتواند یک عدد دریافت کند، میتواند اجرا کند.⚠️ نکته مهم
این دو با هم فرق دارند:
calculate(square, 5)
ارسال تابع
squareاما:
calculate(square(5), 5)
ابتدا
square(5) اجرا میشود و نتیجه آن ارسال میشود؛ بنابراین در این مثال نوع آرگومان با چیزی که calculate انتظار دارد سازگار نیست.🧠 خلاصه
تابع میتواند:
• در متغیر ذخیره شود
• به تابع دیگری ارسال شود
• توسط تابع دیگری اجرا شود
🎯 تمرین
دو تابع بنویسید:
def double(x):
return x * 2
def apply(function, number):
# کامل کنید
سپس:
print(apply(double, 10))
خروجی مورد انتظار:
20
پست ۸۱ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۸۲
تابع کوتاه با
در Python میتوانیم برای کارهای ساده، تابعی کوتاه را با
🔹 ساختار
مثلاً:
خروجی:
این کد تقریباً معادل این است:
🔹 چند آرگومان
خروجی:
⚠️ نکته مهم
اگر منطق تابع پیچیده باشد، معمولاً
🔹 استفاده همراه با تابع دیگر
خروجی:
اینجا تابع
🧠 خلاصه
🎯 تمرین
یک
خروجی مورد انتظار:
پست ۸۲ از دوره جامع Python 🐍
تابع کوتاه با
lambdaدر Python میتوانیم برای کارهای ساده، تابعی کوتاه را با
lambda تعریف کنیم.🔹 ساختار
lambda arguments: expression
مثلاً:
square = lambda x: x * x
print(square(5))
خروجی:
25
این کد تقریباً معادل این است:
def square(x):
return x * x
🔹 چند آرگومان
add = lambda a, b: a + b
print(add(10, 5))
خروجی:
15
⚠️ نکته مهم
lambda برای توابع ساده و کوتاه مناسب است.اگر منطق تابع پیچیده باشد، معمولاً
def خواناتر و مناسبتر است.🔹 استفاده همراه با تابع دیگر
def calculate(function, number):
return function(number)
result = calculate(lambda x: x * 2, 10)
print(result)
خروجی:
20
اینجا تابع
lambda مستقیماً به calculate ارسال شده است.🧠 خلاصه
def → تعریف معمولی تابع
lambda → تعریف کوتاه یک تابع ساده
🎯 تمرین
یک
lambda بنویسید که عدد را به توان ۳ برساند:cube = ...
print(cube(4))
خروجی مورد انتظار:
64
پست ۸۲ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۸۳
اعمال یک تابع روی همه اعضا با
گاهی میخواهیم یک عملیات یکسان را روی تمام اعضای یک مجموعه انجام دهیم.
🔹 مثال ساده
خروجی:
تابع
🔹 با تابع معمولی
خروجی:
🔹 چرا
در Python 3،
برای تبدیل آن به لیست:
استفاده میکنیم.
⚠️ نکته مهم
خروجی:
🧠 خلاصه
یعنی تابع را روی اعضای
🎯 تمرین
خروجی را قبل از اجرا حدس بزنید.
پست ۸۳ از دوره جامع Python 🐍
اعمال یک تابع روی همه اعضا با
map()گاهی میخواهیم یک عملیات یکسان را روی تمام اعضای یک مجموعه انجام دهیم.
map() برای همین کار استفاده میشود.🔹 مثال ساده
numbers = [1, 2, 3, 4]
result = map(lambda x: x * 2, numbers)
print(list(result))
خروجی:
[2, 4, 6, 8]
تابع
lambda روی تکتک اعضای numbers اجرا شده است.🔹 با تابع معمولی
def square(x):
return x * x
numbers = [2, 3, 4, 5]
result = map(square, numbers)
print(list(result))
خروجی:
[4, 9, 16, 25]
🔹 چرا
list()؟در Python 3،
map() یک iterator برمیگرداند و نتیجهها را بهصورت مستقیم به شکل لیست نمایش نمیدهد.برای تبدیل آن به لیست:
list(result)
استفاده میکنیم.
⚠️ نکته مهم
map() داده اصلی را تغییر نمیدهد:numbers = [1, 2, 3]
result = list(map(lambda x: x * 10, numbers))
print(numbers)
print(result)
خروجی:
[1, 2, 3]
[10, 20, 30]
🧠 خلاصه
map(function, iterable)
یعنی تابع را روی اعضای
iterable اعمال کن.🎯 تمرین
numbers = [5, 10, 15, 20]
result = map(lambda x: x + 5, numbers)
print(list(result))
خروجی را قبل از اجرا حدس بزنید.
پست ۸۳ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۸۴
فیلتر کردن دادهها با
در پست قبل با
اما اگر بخواهیم فقط اعضایی را نگه داریم که یک شرط خاص را دارند، از
🔹 مثال ساده
خروجی:
تابع
اگر نتیجه
🔹 با تابع معمولی
خروجی:
🔹 تفاوت
مثلاً:
⚠️ نکته
🎯 تمرین
خروجی را قبل از اجرا حدس بزنید.
پست ۸۴ از دوره جامع Python 🐍
فیلتر کردن دادهها با
filter()در پست قبل با
map() آشنا شدیم که برای تبدیل اعضای یک مجموعه استفاده میشود.اما اگر بخواهیم فقط اعضایی را نگه داریم که یک شرط خاص را دارند، از
filter() استفاده میکنیم.🔹 مثال ساده
numbers = [1, 2, 3, 4, 5, 6]
result = filter(lambda x: x % 2 == 0, numbers)
print(list(result))
خروجی:
[2, 4, 6]
تابع
lambda برای هر عدد بررسی میکند که زوج است یا نه.اگر نتیجه
True باشد، آن مقدار در نتیجه باقی میماند.🔹 با تابع معمولی
def is_positive(x):
return x > 0
numbers = [-2, 0, 3, -1, 5]
result = filter(is_positive, numbers)
print(list(result))
خروجی:
[3, 5]
🔹 تفاوت
map() و filter()map() → مقدارها را تبدیل میکند
filter() → مقدارها را انتخاب یا حذف میکند
مثلاً:
numbers = [1, 2, 3, 4]
list(map(lambda x: x * 2, numbers))
# [2, 4, 6, 8]
list(filter(lambda x: x % 2 == 0, numbers))
# [2, 4]
⚠️ نکته
filter() هم مانند map() در Python 3 یک iterator برمیگرداند؛ بنابراین برای ساختن لیست میتوانیم از list() استفاده کنیم.🎯 تمرین
numbers = [10, 15, 20, 25, 30]
result = filter(lambda x: x >= 20, numbers)
print(list(result))
خروجی را قبل از اجرا حدس بزنید.
پست ۸۴ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۸۵
ترکیب
در دو پست قبل یاد گرفتیم:
حالا میتوانیم این دو را با هم ترکیب کنیم.
🔹 مثال
فرض کنید فقط اعداد زوج را میخواهیم و سپس آنها را دو برابر کنیم:
خروجی:
ابتدا:
🔹 چرا ترتیب مهم است؟
اگر ابتدا
ابتدا اعداد دو برابر میشوند:
سپس فقط اعداد بزرگتر از
پس ترتیب عملیات روی نتیجه تأثیر دارد.
🧠 خلاصه
میتوانیم خروجی یکی را بهعنوان ورودی دیگری استفاده کنیم.
🎯 تمرین
کدی بنویسید که:
اعداد بزرگتر از
سپس آنها را 3 برابر کند.
خروجی مورد انتظار:
پست ۸۵ از دوره جامع Python 🐍
ترکیب
map() و filter()در دو پست قبل یاد گرفتیم:
map() → تبدیل دادهها
filter() → فیلتر کردن دادهها
حالا میتوانیم این دو را با هم ترکیب کنیم.
🔹 مثال
فرض کنید فقط اعداد زوج را میخواهیم و سپس آنها را دو برابر کنیم:
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
result = map(lambda x: x * 2, even_numbers)
print(list(result))
خروجی:
[4, 8, 12]
ابتدا:
[1, 2, 3, 4, 5, 6]
↓
filter()
↓
[2, 4, 6]
↓
map()
↓
[4, 8, 12]
🔹 چرا ترتیب مهم است؟
اگر ابتدا
map() انجام دهیم:numbers = [1, 2, 3, 4]
result = filter(
lambda x: x > 5,
map(lambda x: x * 2, numbers)
)
print(list(result))
ابتدا اعداد دو برابر میشوند:
[2, 4, 6, 8]
سپس فقط اعداد بزرگتر از
5 باقی میمانند:[6, 8]
پس ترتیب عملیات روی نتیجه تأثیر دارد.
🧠 خلاصه
filter() → انتخاب
map() → تبدیل
میتوانیم خروجی یکی را بهعنوان ورودی دیگری استفاده کنیم.
🎯 تمرین
کدی بنویسید که:
اعداد بزرگتر از
10 را انتخاب کند.سپس آنها را 3 برابر کند.
numbers = [5, 10, 15, 20, 25]
خروجی مورد انتظار:
[45, 60, 75]
پست ۸۵ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۸۶
ترکیب همه دادهها با
تا اینجا:
حالا
برای استفاده از آن باید
🔹 مثال ساده
خروجی:
نحوه محاسبه:
🔹 ضرب اعداد
خروجی:
چون:
🔹 مقدار اولیه
میتوانیم یک مقدار اولیه هم مشخص کنیم:
خروجی:
محاسبه:
⚠️ نکته مهم
اگر لیست خالی باشد و مقدار اولیه نداشته باشیم،
🧠 خلاصه
🎯 تمرین
با
خروجی را قبل از اجرا حدس بزنید.
پست ۸۶ از دوره جامع Python 🐍
ترکیب همه دادهها با
reduce()تا اینجا:
map() → تبدیل دادهها
filter() → فیلتر کردن دادهها
حالا
reduce() را یاد میگیریم.reduce() چند مقدار را بهصورت مرحلهای با یکدیگر ترکیب میکند تا در نهایت به یک مقدار برسد.برای استفاده از آن باید
reduce را از functools وارد کنیم.🔹 مثال ساده
from functools import reduce
numbers = [1, 2, 3, 4]
result = reduce(lambda a, b: a + b, numbers)
print(result)
خروجی:
10
نحوه محاسبه:
1 + 2 → 3
3 + 3 → 6
6 + 4 → 10
🔹 ضرب اعداد
from functools import reduce
numbers = [2, 3, 4]
result = reduce(lambda a, b: a * b, numbers)
print(result)
خروجی:
24
چون:
2 × 3 → 6
6 × 4 → 24
🔹 مقدار اولیه
میتوانیم یک مقدار اولیه هم مشخص کنیم:
from functools import reduce
numbers = [1, 2, 3]
result = reduce(lambda a, b: a + b, numbers, 10)
print(result)
خروجی:
16
محاسبه:
10 + 1 → 11
11 + 2 → 13
13 + 3 → 16
⚠️ نکته مهم
اگر لیست خالی باشد و مقدار اولیه نداشته باشیم،
reduce() نمیداند از چه مقداری شروع کند و خطا ایجاد میشود.🧠 خلاصه
map() → چند مقدار → چند مقدارِ تبدیلشده
filter() → چند مقدار → چند مقدارِ انتخابشده
reduce() → چند مقدار → یک مقدار
🎯 تمرین
با
reduce() مجموع اعداد زیر را محاسبه کنید:from functools import reduce
numbers = [5, 10, 15, 20]
result = reduce(lambda a, b: a + b, numbers)
print(result)
خروجی را قبل از اجرا حدس بزنید.
پست ۸۶ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۸۷
تابع تو در تو | Nested Function
در Python میتوانیم یک تابع را داخل تابع دیگری تعریف کنیم.
به این نوع تابع، Nested Function میگوییم.
🔹 مثال ساده
خروجی:
تابع
🔹 چرا تابع تو در تو؟
یکی از کاربردها، محدود کردن یک تابع کمکی به همان تابعی است که به آن نیاز دارد.
خروجی:
اینجا
🔹 تابع داخلی میتواند مقدار بیرونی را ببیند
خروجی:
تابع
⚠️ نکته مهم
این موضوع با
🧠 خلاصه
🎯 تمرین
تابعی به نام
تابع داخلی باید
پست ۸۷ از دوره جامع Python 🐍
تابع تو در تو | Nested Function
در Python میتوانیم یک تابع را داخل تابع دیگری تعریف کنیم.
به این نوع تابع، Nested Function میگوییم.
🔹 مثال ساده
def outer():
print("Outer function")
def inner():
print("Inner function")
inner()
outer()
خروجی:
Outer function
Inner function
تابع
inner داخل outer تعریف شده و در این مثال فقط از داخل outer قابل استفاده است.🔹 چرا تابع تو در تو؟
یکی از کاربردها، محدود کردن یک تابع کمکی به همان تابعی است که به آن نیاز دارد.
def calculate_total(price, tax):
def calculate_tax():
return price * tax
return price + calculate_tax()
print(calculate_total(100, 0.1))
خروجی:
110.0
اینجا
calculate_tax() فقط برای محاسبه داخل calculate_total() استفاده شده است.🔹 تابع داخلی میتواند مقدار بیرونی را ببیند
def outer():
message = "Hello"
def inner():
print(message)
inner()
outer()
خروجی:
Hello
تابع
inner میتواند متغیر موجود در تابع بیرونی را بخواند.⚠️ نکته مهم
این موضوع با
nonlocal که در پست ۷۹ دیدیم مرتبط است:خواندن متغیر بیرونی → بدون nonlocal
تغییر متغیر بیرونی → معمولاً با nonlocal
🧠 خلاصه
Nested Function
↓
تابع داخل تابع
↓
برای منطق کمکی و محدود به یک محدوده مفید است
🎯 تمرین
تابعی به نام
greet_user بنویسید که داخل آن تابع get_message قرار داشته باشد.تابع داخلی باید
"Hello Python" را برگرداند و تابع بیرونی آن را چاپ کند.پست ۸۷ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۸۸
Closure چیست؟
در پست قبل با تابعهای تودرتو آشنا شدیم.
حالا یک قابلیت مهمتر را بررسی میکنیم: Closure.
Closure زمانی ایجاد میشود که یک تابع داخلی، متغیرهای تابع بیرونی را به خاطر بسپارد؛ حتی بعد از تمام شدن اجرای تابع بیرونی.
🔹 مثال ساده
خروجی:
اینجا
🔹 یک مثال کاربردی
خروجی:
هر تابع مقدار
⚠️ نکته مهم
در Closure، تابع داخلی فقط یک تابع ساده نیست؛ بلکه همراه با اطلاعاتی از محیطی که در آن ساخته شده باقی میماند.
🧠 خلاصه
🎯 تمرین
تابعی به نام
خروجی مورد انتظار:
پست ۸۸ از دوره جامع Python 🐍
Closure چیست؟
در پست قبل با تابعهای تودرتو آشنا شدیم.
حالا یک قابلیت مهمتر را بررسی میکنیم: Closure.
Closure زمانی ایجاد میشود که یک تابع داخلی، متغیرهای تابع بیرونی را به خاطر بسپارد؛ حتی بعد از تمام شدن اجرای تابع بیرونی.
🔹 مثال ساده
def create_greeting(name):
def greet():
return f"Hello {name}"
return greet
message = create_greeting("Ali")
print(message())
خروجی:
Hello Ali
اینجا
create_greeting() تمام شده، اما تابع greet هنوز مقدار name را در دسترس دارد.🔹 یک مثال کاربردی
def multiplier(factor):
def multiply(number):
return number * factor
return multiply
double = multiplier(2)
triple = multiplier(3)
print(double(5))
print(triple(5))
خروجی:
10
15
هر تابع مقدار
factor مربوط به خودش را به خاطر سپرده است.multiplier(2)
↓
double
↓
factor = 2
multiplier(3)
↓
triple
↓
factor = 3
⚠️ نکته مهم
در Closure، تابع داخلی فقط یک تابع ساده نیست؛ بلکه همراه با اطلاعاتی از محیطی که در آن ساخته شده باقی میماند.
🧠 خلاصه
Nested Function
→ تابع داخل تابع
Closure
→ تابع داخلی + دسترسی حفظشده به متغیرهای محیط بیرونی
🎯 تمرین
تابعی به نام
power بسازید که یک توان دریافت کند و یک تابع برگرداند:square = power(2)
print(square(5))
خروجی مورد انتظار:
25
پست ۸۸ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۸۹
تغییر رفتار تابع با
در پستهای قبل دیدیم که میتوانیم تابع را به تابع دیگری ارسال کنیم.
حالا از همین قابلیت برای ساخت Decorator استفاده میکنیم.
Decorator به ما اجازه میدهد بدون تغییر مستقیم کد یک تابع، رفتار آن را گسترش یا تغییر دهیم.
🔹 مثال ساده
حالا میتوانیم آن را روی یک تابع اعمال کنیم:
خروجی:
در واقع:
تابع اصلی را با تابع
🔹 استفاده از
Python برای Decorator یک syntax سادهتر دارد:
نتیجه همان است.
این:
تقریباً معادل این است:
⚠️ نکته مهم
Decorator خودش تابعی است که یک تابع را دریافت میکند و معمولاً تابع دیگری برمیگرداند.
🎯 تمرین
یک Decorator به نام
سپس آن را روی تابع زیر اعمال کنید:
خروجی مورد انتظار:
پست ۸۹ از دوره جامع Python 🐍
تغییر رفتار تابع با
Decoratorدر پستهای قبل دیدیم که میتوانیم تابع را به تابع دیگری ارسال کنیم.
حالا از همین قابلیت برای ساخت Decorator استفاده میکنیم.
Decorator به ما اجازه میدهد بدون تغییر مستقیم کد یک تابع، رفتار آن را گسترش یا تغییر دهیم.
🔹 مثال ساده
def logger(function):
def wrapper():
print("Function started")
function()
print("Function finished")
return wrapper
حالا میتوانیم آن را روی یک تابع اعمال کنیم:
def greet():
print("Hello Python")
greet = logger(greet)
greet()
خروجی:
Function started
Hello Python
Function finished
در واقع:
greet = logger(greet)
تابع اصلی را با تابع
wrapper جایگزین میکند.🔹 استفاده از
@Python برای Decorator یک syntax سادهتر دارد:
def logger(function):
def wrapper():
print("Function started")
function()
print("Function finished")
return wrapper
@logger
def greet():
print("Hello Python")
greet()
نتیجه همان است.
این:
@logger
def greet():
...
تقریباً معادل این است:
def greet():
...
greet = logger(greet)
⚠️ نکته مهم
Decorator خودش تابعی است که یک تابع را دریافت میکند و معمولاً تابع دیگری برمیگرداند.
function
↓
Decorator
↓
wrapper
↓
تابع با رفتار جدید
🎯 تمرین
یک Decorator به نام
before بنویسید که قبل از اجرای تابع، عبارت زیر را چاپ کند:Starting...
سپس آن را روی تابع زیر اعمال کنید:
@before
def hello():
print("Hello!")
خروجی مورد انتظار:
Starting...
Hello!
پست ۸۹ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۹۰
Decorator برای توابع دارای آرگومان
در پست قبل یک Decorator ساده ساختیم که روی تابعی بدون آرگومان کار میکرد.
اما در عمل، توابع معمولاً آرگومان دارند.
برای اینکه Decorator بتواند با انواع مختلف تابعها کار کند، از
🔹 مثال
حالا:
خروجی:
🔹 چرا
در اینجا:
و:
آنها را دوباره به تابع اصلی ارسال میکند.
🔹 چرا
برای آرگومانهای نامدار:
همه آنها را به تابع اصلی منتقل میکند.
⚠️ نکته مهم
اگر مقدار بازگشتی تابع اصلی را برنگردانیم، نتیجه تابع ممکن است از بین برود.
پس معمولاً در Decorator مینویسیم:
🧠 خلاصه
🎯 تمرین
Decorator زیر را کامل کنید:
سپس آن را روی تابع زیر امتحان کنید:
خروجی مورد انتظار:
پست ۹۰ از دوره جامع Python 🐍
Decorator برای توابع دارای آرگومان
در پست قبل یک Decorator ساده ساختیم که روی تابعی بدون آرگومان کار میکرد.
اما در عمل، توابع معمولاً آرگومان دارند.
برای اینکه Decorator بتواند با انواع مختلف تابعها کار کند، از
*args و **kwargs استفاده میکنیم.🔹 مثال
def logger(function):
def wrapper(*args, **kwargs):
print("Function started")
result = function(*args, **kwargs)
print("Function finished")
return result
return wrapper
حالا:
@logger
def add(a, b):
return a + b
result = add(10, 5)
print(result)
خروجی:
Function started
Function finished
15
🔹 چرا
*args؟*args آرگومانهای موقعیتی را دریافت میکند:add(10, 5)
در اینجا:
args → (10, 5)
و:
function(*args)
آنها را دوباره به تابع اصلی ارسال میکند.
🔹 چرا
**kwargs؟برای آرگومانهای نامدار:
@logger
def greet(name, language="English"):
return f"{name} - {language}"
print(greet(name="Ali", language="Persian"))
kwargs آرگومانهای نامدار را دریافت میکند و:function(*args, **kwargs)
همه آنها را به تابع اصلی منتقل میکند.
⚠️ نکته مهم
اگر مقدار بازگشتی تابع اصلی را برنگردانیم، نتیجه تابع ممکن است از بین برود.
پس معمولاً در Decorator مینویسیم:
result = function(*args, **kwargs)
return result
🧠 خلاصه
*args → آرگومانهای موقعیتی
**kwargs → آرگومانهای نامدار
function(*args, **kwargs)
→ ارسال دوباره آرگومانها به تابع اصلی
🎯 تمرین
Decorator زیر را کامل کنید:
def logger(function):
def wrapper(*args, **kwargs):
print("Starting...")
# تابع اصلی را اجرا کنید
# نتیجه را برگردانید
return wrapper
سپس آن را روی تابع زیر امتحان کنید:
@logger
def multiply(a, b):
return a * b
print(multiply(4, 5))
خروجی مورد انتظار:
Starting...
20
پست ۹۰ از دوره جامع Python 🐍
1
🐍 آموزش جامع Python — پست ۹۱
حفظ مشخصات تابع با
در پستهای قبل یاد گرفتیم چگونه Decorator بسازیم.
اما یک مشکل مهم وجود دارد:
وقتی یک تابع را با Decorator میپیچیم، ممکن است اطلاعات اصلی تابع مثل نام و توضیحات آن با اطلاعات
🔹 مثال
خروجی معمولاً:
یعنی مشخصات تابع اصلی از دست رفتهاند.
🔹 راهحل:
از
حالا:
خروجی:
🔹
این Decorator اطلاعات مهم تابع اصلی را روی
بنابراین بهتر است هنگام ساخت Decoratorهای واقعی، معمولاً از
🧠 خلاصه
🎯 تمرین
Decorator زیر را طوری کامل کنید که نام تابع اصلی حفظ شود:
سپس بررسی کنید:
پست ۹۱ از دوره جامع Python 🐍
حفظ مشخصات تابع با
functools.wrapsدر پستهای قبل یاد گرفتیم چگونه Decorator بسازیم.
اما یک مشکل مهم وجود دارد:
وقتی یک تابع را با Decorator میپیچیم، ممکن است اطلاعات اصلی تابع مثل نام و توضیحات آن با اطلاعات
wrapper جایگزین شود.🔹 مثال
def logger(function):
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
@logger
def greet():
"""Say hello to the user."""
return "Hello"
print(greet.__name__)
print(greet.__doc__)
خروجی معمولاً:
wrapper
None
یعنی مشخصات تابع اصلی از دست رفتهاند.
🔹 راهحل:
wrapsاز
functools، ابزار wraps را وارد میکنیم:from functools import wraps
def logger(function):
@wraps(function)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
حالا:
@logger
def greet():
"""Say hello to the user."""
return "Hello"
print(greet.__name__)
print(greet.__doc__)
خروجی:
greet
Say hello to the user.
🔹
@wraps(function) چه میکند؟این Decorator اطلاعات مهم تابع اصلی را روی
wrapper حفظ میکند؛ از جمله اطلاعاتی مانند:__name__
__doc__
بنابراین بهتر است هنگام ساخت Decoratorهای واقعی، معمولاً از
@wraps(function) استفاده کنیم.🧠 خلاصه
Decorator
↓
wrapper
↓
@wraps(function)
↓
حفظ اطلاعات تابع اصلی
🎯 تمرین
Decorator زیر را طوری کامل کنید که نام تابع اصلی حفظ شود:
from functools import wraps
def my_decorator(function):
@wraps(function)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
سپس بررسی کنید:
@my_decorator
def hello():
"""Hello function"""
return "Hello"
print(hello.__name__)
print(hello.__doc__)
پست ۹۱ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۹۲
استفاده از چند Decorator برای یک تابع
در Python میتوانیم بیش از یک Decorator را روی یک تابع قرار دهیم.
این کار زمانی مفید است که بخواهیم چند رفتار مستقل را به یک تابع اضافه کنیم.
🔹 مثال ساده
خروجی:
🔹 ترتیب Decoratorها مهم است
وقتی مینویسیم:
Python آن را تقریباً مانند این در نظر میگیرد:
یعنی Decoratorها از پایین به بالا اعمال میشوند:
پس ابتدا
🔹 اما هنگام اجرای تابع چه اتفاقی میافتد؟
وقتی مینویسیم:
اجرای Wrapperها از بالا به پایین وارد میشود:
مثلاً:
خروجی:
چرا؟
چون ابتدا
سپس داخل آن:
اجرا میشود که در اینجا همان
بعد
و بعد از تمام شدن تابع اصلی:
🧠 یک قانون مهم برای حفظ کردن
اگر داشته باشیم:
ترتیب اعمال Decoratorها:
اما هنگام اجرای تابع، ورود به Wrapperها:
و هنگام خروج، ترتیب برعکس میشود:
به همین دلیل Decoratorها شبیه لایههای تو در تو عمل میکنند.
🔹 مثال کاربردی
میتوانیم یک Decorator برای ثبت اجرا و یکی برای بررسی دسترسی داشته باشیم:
خروجی:
چون:
⚠️ نکته مهم
جای Decoratorها را نمیتوان همیشه بدون تغییر نتیجه جابهجا کرد.
مثلاً:
لزوماً با:
رفتار یکسانی ندارد.
پس ترتیب Decoratorها بخشی از منطق برنامه است.
🧠 خلاصه
تقریباً معادل:
بنابراین:
🎯 تمرین
دو Decorator بسازید:
سپس هر دو را روی این تابع قرار دهید:
ترتیب خروجی را قبل از اجرا حدس بزنید.
پست ۹۲ از دوره جامع Python 🐍
استفاده از چند Decorator برای یک تابع
در Python میتوانیم بیش از یک Decorator را روی یک تابع قرار دهیم.
این کار زمانی مفید است که بخواهیم چند رفتار مستقل را به یک تابع اضافه کنیم.
🔹 مثال ساده
from functools import wraps
def first(function):
@wraps(function)
def wrapper():
print("First")
function()
return wrapper
def second(function):
@wraps(function)
def wrapper():
print("Second")
function()
return wrapper
@first
@second
def hello():
print("Hello")
hello()
خروجی:
First
Second
Hello
🔹 ترتیب Decoratorها مهم است
وقتی مینویسیم:
@first
@second
def hello():
...
Python آن را تقریباً مانند این در نظر میگیرد:
hello = first(second(hello))
یعنی Decoratorها از پایین به بالا اعمال میشوند:
hello اصلی
↓
second
↓
first
پس ابتدا
second تابع hello را میگیرد و سپس نتیجه آن به first داده میشود.🔹 اما هنگام اجرای تابع چه اتفاقی میافتد؟
وقتی مینویسیم:
hello()
اجرای Wrapperها از بالا به پایین وارد میشود:
first.wrapper
↓
second.wrapper
↓
hello اصلی
مثلاً:
def first(function):
def wrapper():
print("First START")
function()
print("First END")
return wrapper
def second(function):
def wrapper():
print("Second START")
function()
print("Second END")
return wrapper
@first
@second
def hello():
print("Hello")
hello()
خروجی:
First START
Second START
Hello
Second END
First END
چرا؟
چون ابتدا
first.wrapper اجرا میشود:First START
سپس داخل آن:
function()
اجرا میشود که در اینجا همان
second.wrapper است:Second START
بعد
second.wrapper تابع اصلی را اجرا میکند:Hello
و بعد از تمام شدن تابع اصلی:
Second END
First END
🧠 یک قانون مهم برای حفظ کردن
اگر داشته باشیم:
@A
@B
@C
def function():
...
ترتیب اعمال Decoratorها:
C → B → A
اما هنگام اجرای تابع، ورود به Wrapperها:
A → B → C → function
و هنگام خروج، ترتیب برعکس میشود:
function → C → B → A
به همین دلیل Decoratorها شبیه لایههای تو در تو عمل میکنند.
🔹 مثال کاربردی
میتوانیم یک Decorator برای ثبت اجرا و یکی برای بررسی دسترسی داشته باشیم:
from functools import wraps
def log(function):
@wraps(function)
def wrapper(*args, **kwargs):
print("Function called")
return function(*args, **kwargs)
return wrapper
def check_access(function):
@wraps(function)
def wrapper(*args, **kwargs):
print("Access checked")
return function(*args, **kwargs)
return wrapper
@log
@check_access
def delete_file():
print("File deleted")
delete_file()
خروجی:
Function called
Access checked
File deleted
چون:
delete_file = log(check_access(delete_file))
⚠️ نکته مهم
جای Decoratorها را نمیتوان همیشه بدون تغییر نتیجه جابهجا کرد.
مثلاً:
@first
@second
لزوماً با:
@second
@first
رفتار یکسانی ندارد.
پس ترتیب Decoratorها بخشی از منطق برنامه است.
🧠 خلاصه
@first
@second
def hello():
...
تقریباً معادل:
hello = first(second(hello))
بنابراین:
اعمال Decorator → از پایین به بالا
ورود به Wrapperها → از بالا به پایین
خروج از Wrapperها → از پایین به بالا
🎯 تمرین
دو Decorator بسازید:
before → قبل از اجرای تابع "Before" چاپ کند.after → بعد از اجرای تابع "After" چاپ کند.سپس هر دو را روی این تابع قرار دهید:
def hello():
print("Hello")
ترتیب خروجی را قبل از اجرا حدس بزنید.
پست ۹۲ از دوره جامع Python 🐍
🐍 آموزش جامع Python — پست ۹۳
Decorator عمومی با
در پست ۹۰ یاد گرفتیم چگونه با
حالا یک نکته مهمتر را میبینیم: یک Decorator عمومی میتواند روی تابعهایی با تعداد و نوع آرگومانهای متفاوت کار کند.
🔹 یک Decorator برای چند تابع
حالا همین Decorator را روی چند تابع متفاوت استفاده میکنیم:
خروجی:
🔹 نقش
در این مثال:
مثلاً:
یا:
یا:
و سپس:
همان آرگومانها را به تابع اصلی منتقل میکند.
🧠 چرا این موضوع مهم است؟
بدون
اما با این الگو:
میتوانیم یک Decorator عمومی داشته باشیم.
⚠️ نکته
این Decorator فقط به دلیل
🎯 تمرین
Decorator
سپس هر سه تابع را با آرگومانهای مختلف اجرا کنید.
پست ۹۳ از دوره جامع Python 🐍
Decorator عمومی با
*args و **kwargsدر پست ۹۰ یاد گرفتیم چگونه با
*args و **kwargs یک Decorator را برای تابعهای دارای آرگومان آماده کنیم.حالا یک نکته مهمتر را میبینیم: یک Decorator عمومی میتواند روی تابعهایی با تعداد و نوع آرگومانهای متفاوت کار کند.
🔹 یک Decorator برای چند تابع
from functools import wraps
def logger(function):
@wraps(function)
def wrapper(*args, **kwargs):
print("Function started")
result = function(*args, **kwargs)
print("Function finished")
return result
return wrapper
حالا همین Decorator را روی چند تابع متفاوت استفاده میکنیم:
@logger
def greet(name):
return f"Hello {name}"
@logger
def add(a, b):
return a + b
@logger
def welcome(name, language="English"):
return f"{name} - {language}"
print(greet("Ali"))
print(add(10, 5))
print(welcome("Sara", language="Persian"))
خروجی:
Function started
Function finished
Hello Ali
Function started
Function finished
15
Function started
Function finished
Sara - Persian
🔹 نقش
*args و **kwargsدر این مثال:
def wrapper(*args, **kwargs):
wrapper میتواند آرگومانهای مختلفی دریافت کند.مثلاً:
greet("Ali")یا:
add(10, 5)
یا:
welcome("Sara", language="Persian")و سپس:
function(*args, **kwargs)
همان آرگومانها را به تابع اصلی منتقل میکند.
🧠 چرا این موضوع مهم است؟
بدون
*args و **kwargs ممکن بود مجبور شویم برای هر نوع تابع، Decorator متفاوتی بنویسیم.اما با این الگو:
تابع با ۱ آرگومان ─┐
تابع با ۲ آرگومان ─┼→ یک Decorator
تابع با آرگومان نامدار ─┘
میتوانیم یک Decorator عمومی داشته باشیم.
⚠️ نکته
این Decorator فقط به دلیل
*args و **kwargs عمومی شده است؛ اما منطق داخل Decorator هنوز باید با هدف آن سازگار باشد.🎯 تمرین
Decorator
logger را روی این سه تابع امتحان کنید:@logger
def square(x):
return x * x
@logger
def multiply(a, b):
return a * b
@logger
def greet(name, message="Hello"):
return f"{message}, {name}"
سپس هر سه تابع را با آرگومانهای مختلف اجرا کنید.
پست ۹۳ از دوره جامع Python 🐍