مدرسه زبان برنامه‌نویسی PYTHON

وبلاگی جهت معرفی - آموزش و تحلیل زبان برنامه نویسی ‍پایتون

مدرسه زبان برنامه‌نویسی PYTHON

وبلاگی جهت معرفی - آموزش و تحلیل زبان برنامه نویسی ‍پایتون

۵ مطلب در دی ۱۴۰۳ ثبت شده است

این بدان معناست که هر زمان که نمونه_function را فراخوانی می کنیم، اساساً تابع add_one تعریف شده در دکوراتور را فراخوانی می کنیم.

 

هنگام استفاده از دکوراتورها، ممکن است بخواهیم تابع تزئین شده زمانی که از تابع wrapper فراخوانی می شود، آرگومان ها را دریافت کند.

به عنوان مثال، اگر تابعی داشته باشیم که به دو پارامتر نیاز دارد و مجموع آنها را برمی گرداند:

def add(a,b):
    return a + b

print(add(1,2)) # 3

و اگر از دکوراتور استفاده کنیم که 1 به خروجی اضافه کند:

 

def add_one_decorator(func):
    def add_one():
        value = func()
        return value + 1

    return add_one

@add_one_decorator
def add(a,b):
    return a + b

add(1,2)
# TypeError: add_one_decorator.<locals>.add_one() takes 0 positional arguments but 2 were given

هنگام انجام این کار، با یک خطا مواجه می شویم: تابع wrapper (add_one) هیچ آرگومان نمی گیرد اما ما دو آرگومان ارائه می دهیم.

برای رفع این مشکل، باید هر آرگومان دریافتی از add_one را هنگام فراخوانی آن به تابع تزئین شده منتقل کنیم:

def add_one_decorator(func):
    def add_one(*args, **kwargs):
        value = func(*args, **kwargs)
        return value + 1

     return add_one

 @add_one_decorator
 def add(a,b):
     return a+b

 print(add(1,2)) # 4

ما از *args و **kwargs استفاده می کنیم تا نشان دهیم که تابع add_one wrapper باید بتواند هر مقدار از آرگومان های موقعیتی (args) و آرگومان های کلمه کلیدی (kwargs) را دریافت کند.

args لیستی از تمام کلمات کلیدی موقعیتی داده شده خواهد بود، در این مورد [1،2].

kwargs یک فرهنگ لغت با کلیدها به عنوان آرگومان های کلیدواژه مورد استفاده و مقادیر به عنوان مقادیر اختصاص داده شده به آنها، در این مورد یک فرهنگ لغت خالی خواهد بود.

نوشتن func(*args، **kwargs) نشان می‌دهد که می‌خواهیم func را با همان آرگومان‌های موقعیتی و کلیدواژه‌ای که دریافت شد، فراخوانی کنیم.

این تضمین می کند که همه آرگومان های موقعیتی و کلیدواژه ارسال شده به تابع تزئین شده به تابع اصلی منتقل می شوند.

چرا دکوراتورها در پایتون مفید هستند؟ نمونه کد واقعی
اکنون که نگاهی به دکوراتورهای پایتون انداختیم، بیایید چند نمونه واقعی از مفید بودن دکوراتورها را ببینیم.

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

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

در اینجا یک مثال ساده از اینکه چگونه می توانیم یک لاگر ساده (با استفاده از بسته لاگ داخلی پایتون) ایجاد کنیم تا اطلاعات مربوط به برنامه خود را در حین اجرا در فایلی به نام main.log ذخیره کنیم:

ثبت ورود به سیستم

import logging

def function_logger(func):
    logging.basicConfig(level = logging.INFO, filename="main.log")
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        logging.info(f"{func.__name__} ran with positional arguments: {args} and keyword arguments: {kwargs}. Return value: {result}")
        return result

    return wrapper

@function_logger
def add_one(value):
    return value + 1

print(add_one(1))

هر زمان که تابع add_one اجرا شود، یک گزارش جدید به فایل main.log اضافه می شود:

INFO:root:add_one ran with positional arguments: (1,) and keyword arguments: {}. Return value: 2

 

Cashing

اگر برنامه ای داشته باشیم که نیاز به اجرای یک تابع چندین بار با آرگومان های یکسان داشته باشد و مقدار یکسان را برگرداند، می تواند به سرعت ناکارآمد شود و منابع غیر ضروری را اشغال کند.

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

در پایتون، این را می توان با استفاده از دکوراتور @lru_cache از ماژول functools که با پایتون نصب می شود، پیاده سازی کرد.

LRU به Least Recently Used اشاره دارد، به این معنی که هر زمان که تابع فراخوانی شد، آرگومان های استفاده شده و مقدار بازگشتی ذخیره می شوند. اما به محض اینکه تعداد این ورودی ها به حداکثر اندازه رسید که به طور پیش فرض 128 است، کمترین ورودی اخیر حذف خواهد شد.

from functools import lru_cache

@lru_cache
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

در این مثال، تابع فیبوناچی آرگومان n را می گیرد و اگر کمتر از 1 باشد، n ​​را برمی گرداند، در غیر این صورت مجموع تابع فراخوانی شده با n-1 و n-2 را برمی گرداند.

بنابراین، اگر تابع با n=10 فراخوانی شود، 55 را برمی گرداند:

print(fibnoacci(10))
# 55

در این حالت وقتی تابع fibonacci(10) را صدا می زنیم، تابع fibonacci(9) و fibonacci(8) را صدا می کند و به همین ترتیب تا زمانی که به 1 یا 0 برسد.

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

fibonacci(50)
fibonacci(100)

ما می توانیم از حافظه پنهان ورودی هایی که ذخیره شده اند استفاده کنیم. بنابراین وقتی فیبوناچی (50) را صدا می زنیم، می تواند پس از رسیدن به 10، فراخوانی تابع فیبوناچی را متوقف کند و هنگامی که ما فیبوناچی (100) را صدا می زنیم، می تواند پس از رسیدن به 50، فراخوانی تابع را متوقف کند و برنامه را بسیار کارآمدتر می کند.

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

امکان استفاده ساده از نحو @، استفاده از ماژول ها و بسته های اضافی را آسان می کند.

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

اگر از محتوای آموزشی من لذت می برید، بلاگ من را برای محتوای بیشتر پایتون بررسی کنید.

همیشه در حال یادگیری. پیروز و برقرار باشید - سعید دامغانیان

۰ نظر موافقین ۰ مخالفین ۰ ۲۹ دی ۰۳ ، ۱۷:۳۱
سعید دامغانیان

توجه داشته باشید که در این مثال، وقتی inner_function را برمی‌گردانیم، آن را فراخوانی نکردیم.

ما فقط مرجع را به آن برگرداندیم تا بتوانیم بعداً آن را ذخیره و فراخوانی کنیم:

returned_function = outer_function()
# outer_funciton is called

returned_function()
# inner_function is called

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

نحوه ایجاد دکوراتور در پایتون


پذیرش توابع به عنوان آرگومان، تعریف توابع در توابع دیگر و برگرداندن آنها دقیقاً همان چیزی است که برای ایجاد دکوراتورها در پایتون باید بدانیم. ما از دکوراتورها برای افزودن قابلیت های اضافی به عملکردهای موجود استفاده می کنیم.

به عنوان مثال، اگر می‌خواهیم یک دکوراتور ایجاد کنیم که 1 را به مقدار بازگشتی هر تابع اضافه کند، می‌توانیم این کار را به این صورت انجام دهیم:

def add_one_decorator(func):
    def add_one():
        value = func()
        return value + 1

    return add_one

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

def example_function():
    return 1

final_value = add_one_decorator(example_function)
print(final_value()) # 2

در این مثال، تابع add_one_decorator را فراخوانی می کنیم و مرجع را به example_function منتقل می کنیم.

وقتی تابع add_one_decorator را فرا می‌خوانیم، یک تابع جدید به نام add_one ایجاد می‌کند که درون آن تعریف شده و یک مرجع به این تابع جدید برمی‌گرداند. ما این تابع را در متغیر final_value ذخیره می کنیم.

بنابراین، هنگام اجرای تابع final_value، تابع add_one فراخوانی می شود.

تابع add_one تعریف شده در add_one_decorator سپس example_function را فراخوانی می کند، مقدار آن را ذخیره می کند و یکی به آن اضافه می کند.

در نهایت، این منجر به بازگشت 2 و چاپ به کنسول می شود.

فرآیند نحوه اجرای کد

توجه داشته باشید که چگونه برای تغییر مقدار بازگشتی آن و افزودن عملکرد به آن، مجبور نبودیم که example_function اصلی را تغییر دهیم. این چیزی است که دکوراتورها را بسیار مفید می کند!

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

نحوه استفاده از سینتکس @ در پایتون

کاراکتر @

همانطور که در بالا دیدیم، زمانی که می خواهیم از دکوراتورها استفاده کنیم، باید تابع دکوراتور را فراخوانی کنیم و تابعی را که می خواهیم تغییر دهیم، عبور دهیم.

در پایتون، می‌توانیم از نحو @ برای کارآمدتر بودن استفاده کنیم.

 

@add_one_decorator
def example_function():
    return 1

با نوشتن @add_one_decorator در بالای تابع ما، معادل زیر است:

example_function = add_one_decorator(example_function)

 

۰ نظر موافقین ۰ مخالفین ۰ ۲۹ دی ۰۳ ، ۱۷:۲۴
سعید دامغانیان

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

دکوراتورها به شما این توانایی را می دهند که رفتار توابع را بدون تغییر کد منبع آنها تغییر دهید و روشی مختصر و انعطاف پذیر برای افزایش و گسترش عملکرد آنها ارائه می دهد.

در این مقاله، من به پیچیدگی‌های نحوه استفاده از دکوراتورها در پایتون می‌پردازم و نمونه‌هایی از کاربرد آنها را نشان می‌دهم.

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

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

 

دکوراتورها در پایتون

 

توابع ورودی ها را می گیرند، از آن برای اجرای مجموعه ای از کدها استفاده می کنند و یک خروجی را برمی گرداند

در پایتون یک تابع به صورت زیر نوشته می شود:

 

def add_one(num):
    return num + 1

 

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

final_value = add_one(1)
print(final_value) # 2

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

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

نحوه پاس دادن توابع به عنوان آرگومان


معمولاً هنگام فراخوانی توابع با آرگومان‌ها، مقادیری مانند اعداد صحیح، شناورها، رشته‌ها، فهرست‌ها، دیکشنری‌ها و دیگر انواع داده‌ها را ارسال می‌کنیم.

اما، کاری که می توانیم انجام دهیم این است که یک تابع را نیز به عنوان آرگومان ارسال کنیم:

def inner_function():
    print("inner_function is called")

def outer_function(func):
    print("outer_function is called")
     func()

outer_function(inner_function)
# outer_function is called
# inner_function is called

در این مثال ما دو تابع ایجاد می کنیم: inner_function و outer_function.

outer_function یک پارامتر به نام func دارد که پس از فراخوانی خود آن را فراخوانی می کند.

 

دکوریتورها در پایتون

 

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

در مورد آن فکر کنید که چگونه می توانیم با توابع مانند هر مقدار یا متغیر دیگری رفتار کنیم.

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

بنابراین، outer_function می تواند یک تابع را به عنوان یک پارامتر دریافت کند و هنگام اجرا آن را فراخوانی کند.

نحوه برگرداندن توابع
یکی دیگر از مزایای استفاده از توابع به عنوان اشیاء این است که می توانیم آنها را در توابع دیگر تعریف کرده و آنها را نیز برگردانیم:

def outer_function():
    print("outer_function is called")

    def inner_function():
            print("inner_function is called")

    return inner_function

 

۰ نظر موافقین ۰ مخالفین ۰ ۲۹ دی ۰۳ ، ۱۷:۱۸
سعید دامغانیان

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

# This function adds two numbers 
# By: Saeed Damghanian
def add(x, y):
    return x + y

# This function subtracts two numbers
def subtract(x, y):
    return x - y

# This function multiplies two numbers
def multiply(x, y):
    return x * y

# This function divides two numbers
def divide(x, y):
    return x / y


print("Select operation.")
print("1.Add")
print("2.Subtract")
print("3.Multiply")
print("4.Divide")

while True:
    # take input from the user
    choice = input("Enter choice(1/2/3/4): ")

    # check if choice is one of the four options
    if choice in ('1', '2', '3', '4'):
        try:
            num1 = float(input("Enter first number: "))
            num2 = float(input("Enter second number: "))
        except ValueError:
            print("Invalid input. Please enter a number.")
            continue

        if choice == '1':
            print(num1, "+", num2, "=", add(num1, num2))

        elif choice == '2':
            print(num1, "-", num2, "=", subtract(num1, num2))

        elif choice == '3':
            print(num1, "*", num2, "=", multiply(num1, num2))

        elif choice == '4':
            print(num1, "/", num2, "=", divide(num1, num2))
        
        # check if user wants another calculation
        # break the while loop if answer is no
        next_calculation = input("Let's do next calculation? (yes/no): ")
        if next_calculation == "no":
          break
    else:
        print("Invalid Input")

یک نمونه خروجی اجرا شده:

Select operation.
1.Add
2.Subtract
3.Multiply
4.Divide
Enter choice(1/2/3/4): 3
Enter first number: 15
Enter second number: 14
15.0 * 14.0 = 210.0
Let's do next calculation? (yes/no): no

 

۱ نظر موافقین ۰ مخالفین ۰ ۲۱ دی ۰۳ ، ۲۰:۰۰
سعید دامغانیان

جنراتورها : تعریف و کاربرد


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

 

آموزش جنراتورها در پایتون

 

۲ نظر موافقین ۰ مخالفین ۰ ۲۱ دی ۰۳ ، ۱۹:۵۳
سعید دامغانیان