hody.ir

دوره صفر تا صد پایتون | جلسه ۲۷ آشنایی با دکوراتور ها و کاربرد آن در پایتون

27-آشنایی با دکوراتور ها و کاربرد آن در پایتون

جلسه ۲۷ دوره صفر تا صد پایتون

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

پیش نیاز های آشنایی با دکوراتور ها

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

همه چیز در پایتون یک ‌شی هست ، حتی توابع ، عددها ، استرینگ ها ، لیست ها و …

به عنوان مثال در پایتون می‌توان کارهایی مثل این انجام داد:

def func1():
    print('Hello')

func1()
print(type(func1))

func2 = func1
func2()
print(type(func2))

خروجی:

Hello
<class 'function'>
Hello
<class 'function'>

همانطور که می‌بینید تابع type به ما می‌گوید که شی func1 از کلاس function است.

و همچنین یک reference ( با reference در جلسات قبلی دوره صفر تا صد پایتون آشنا شدیم ) از شی func1 به اسم func2 می‌توان ساخت و از آن بطور عادی استفاده کرد:

نحویه اجرا شدن کد بالا
نحویه اجرا شدن کد بالا

حالا با استفاده از این قابلیت می‌توان کارهای دیگری نیز انجام داد. می‌توان یک تابع کامل ( مثلا a ) را به یک تابع دیگر ( مثلا b ) به عنوان ورودی بدهیم و تابع b می توان آن تابع را فراخوانی کند. کد:

def a(x):
    t = 1
    for i in range(1,x+1):
        t *= i
    print(t)

def b(say):
    print(f"Something {say}")

def c(func):
    for _ in range(10):
        func(10)

c(b)
c(a)

به عنوان مثال در اینجا سه تابع داریم. تابع a فاکتوریل حساب می‌کند ، تابع b متنی را چاپ می‌کند و تابع c تابع ورودی را ۱۰ بار اجرا می‌کند. خروجی:

Something 10
Something 10
Something 10
Something 10
Something 10
Something 10
Something 10
Something 10
Something 10
Something 10
3628800
3628800
3628800
3628800
3628800
3628800
3628800
3628800
3628800
3628800

یک کار دیگر که با استفاده از این قابلیت می‌توان انجام داد ارسال کردن یک تابع به خروجی تابع. مثال ( با توابع تو در تو در جلسات قبلی دوره صفر تا صد پایتون :

def myfunc():
    def sayHello():
        return "Hello"
    return sayHello

a = myfunc()
print(type(a))
print(a())

print(myfunc()())

خروجی:

<class 'function'>
Hello
Hello

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

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

آشنایی با دکوراتور

توابع و متد ها دارای قابلیت فراخوانی شدن هستند و به همین دلیل به آنها می گویند callable objects

در واقع هر شی که دارای متد __call__ ( در جلسات قبلی دوره صفر تا صد پایتون با magic method آشنا شدیم ) باشد قابلیت فراخوانی شدن دارد و یک callable object به حساب می‌آید.

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

دکوراتور ها قبل از فراخوانی تابع موردنظر می‌توانند کار های مختلفی انجام بدهند و پس از انجام آن تابع را فراخوانی کنند. مثال:

def sayHello():
    print("Hello user!")

def x2(func):
    def inner():
        for _ in range(2):
            func()
        print('x2 finished')
    return inner

x2_sayhello = x2(sayHello)
x2_sayhello()

خروجی:

Hello user!
Hello user!
x2 finished

در اینجا تابع x2 یک ورودی تابع دارد و تابع ورودی را ۲ بار اجرا می‌کند و به خروجی ارسال می‌کند. به عنوان مثال ما تابع sayhello را تست کردیم.

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

چرا از دکوراتور ها استفاده کنیم؟

حالا شاید فکر کنید چرا از دکوراتور ها استفاده کنیم بجای اینکه خود تابع را تغییر بدهیم؟

چون:

  • پایتون دارای دکوراتور های آماده بسیار کارایی است و در جلسات بعدی با آنها آشنا می‌شویم.
  • نیاز نیست یک کد را چندین بار در همه توابع تکرار کنیم بلکه از syntax که در ادامه آشنا می‌شویم استفاده می‌کنیم.

Syntax بهتر دکوراتور ها

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

def sayHello():
    print("Hello user!")

def x2(func):
    def inner():
        for _ in range(2):
            func()
        print('x2 finished')
    return inner

sayHello = x2(sayHello)
sayHello()

پایتون برای اینکار یک syntax راحت تر و بهتر دارد. در این syntax جدید باید از علامت @ و اسم دکوراتور را قبل از تابع ای که می‌خواهیم دکوراتور روی آن اعمال شود استفاده می‌کنیم. مثال:

def x2(func):
    def inner():
        for _ in range(2):
            func()
        print('x2 finished')
    return inner

@x2
def sayHello():
    print("Hello user!")

@x2
def sayGoodbye():
    print("Goodbye user!")

sayHello()
sayGoodbye()

خروجی:

Hello user!
Hello user!
x2 finished
Goodbye user!
Goodbye user!
x2 finished

استفاده از ورودی توابع در دکوراتور ها

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

def x2(func):
    def inner(x):
        for _ in range(2):
            func(x)
        print('x2 finished')
    return inner

@x2
def sayHello(name):
    print(f"Hello {name}!")

@x2
def sayGoodbye(name):
    print(f"Goodbye {name}!")

sayHello("Alireza")
sayGoodbye("Alireza")

خروجی:

Hello Alireza!
Hello Alireza!
x2 finished
Goodbye Alireza!
Goodbye Alireza!
x2 finished

اما اگر بخواهیم از این دکوراتور در چندین نوع تابع مختلف استفاده کنیم ممکن است به مشکل بخوریم. زیرا توابع مختلف مقدارهای مختلفی ورودی می‌گیرند. برای همین از list option و dict option در ورودی تابع استفاده می کنیم:

def x2(func):
    def inner(*list_options,**dict_options):
        for _ in range(2):
            func(*list_options,**dict_options)
        print('x2 finished')
    return inner

@x2
def sayHello(name):
    print(f"Hello {name}!")

@x2
def sayGoodbye():
    print(f"Goodbye!")

sayHello("Alireza")
sayGoodbye()

خروجی:

Hello Alireza!
Hello Alireza!
x2 finished
Goodbye!
Goodbye!
x2 finished

این جلسه از دوره صفر تا صد پایتون به پایان رسید. مبحث دکوراتور در پایتون یک مبحث کارا و بدردبخور است که زمانی که با کتابخانه ها آشنا شویم می‌توانیم از دکوراتور های بیشتری استفاده کنیم.

همچنین این دکوراتور ها در static class که در جلسه بعدی دوره صفر تا صد پایتون توضیح داده می‌شوند کارا هستند.

0 0 vote
Article Rating
Subscribe
اطلاع از
guest
2 Comments
قدیمی ترین
جدیدترین بیشترین آرا
Inline Feedbacks
View all comments
trackback

[…] از آشنایی با دکوراتور ها در جلسه قبلی دوره صفر تا صد پایتون ، در این جلسه […]

trackback

[…] در واقع این یکی از روش های استفاده از دکوراتور ها ( با دکوراتور ها در جلسات قبلی دوره صفر تا صد پایتون آشنا شدیم ) در توابع […]