دکوراتور در برنامه نویسی پایتون
دکوراتور در برنامه نویسی پایتون
یک دکوراتور یک عملکرد را می گیرد ، برخی از قابلیت ها را اضافه می کند و آن را برمی گرداند. در این درس از مجموعه آموزش برنامه نویسی سایت سورس باران، شما یاد خواهید گرفت که چگونه می توانید یک دکوراتور در برنامه نویسی پایتون ایجاد کنید و چرا باید از آن استفاده کنید.
پیشنهاد ویژه : پکیج آموزش صفر تا صد پایتون
دکوراتور در برنامه نویسی پایتون
پایتون ویژگی جالبی به نام دکوراتورها برای افزودن قابلیت به کد موجود دارد.
به این برنامه metaprogramming نیز گفته می شود زیرا بخشی از برنامه سعی می کند قسمت دیگری از برنامه را در زمان کامپایل اصلاح کند.
پیش نیازهای یادگیری دکوراتورها در پایتون
به منظور درک در مورد دکوراتور، ابتدا باید چند نکته اساسی را در پایتون بدانیم.
ما باید با این واقعیت آگاه باشیم که همه چیز در پایتون ( حتی کلاس ها)، اشیا هستند. اسامی که ما تعریف می کنیم به سادگی شناسه های متصل به این اشیا هستند. توابع نیز از این قاعده مستثنی نیستند، آنها نیز اشیا هستند (دارای صفات). نامهای مختلف می توانند به یک شی تابع تخصیص داده شود.
به عنوان مثال.
1 2 3 4 5 6 7 8 |
def first(msg): print(msg) first("Hello") second = first second("Hello") |
خروجی
1 2 |
Hello Hello |
هنگامی که کد را اجرا می کنید ، هر دو تابع اول و دوم خروجی یکسانی دارند. در اینجا، نام های اول و دوم به همان شی تابع اشاره دارند.
حالا همه چیز عجیب و غریب می شود.
توابع را می توان به عنوان آرگومان یک تابع دیگر منتقل کرد.
اگر از توابعی مانند filter ،map و reduce در پایتون استفاده کرده باشید، با این موضوع آشنایی دارید.
چنین توابعی را که توابع دیگر را به عنوان آرگومان می گیرند، توابع مرتبه بالاتر نیز می نامند. در اینجا مثالی از چنین توابعی آورده شده است.
1 2 3 4 5 6 7 8 9 10 11 |
def inc(x): return x + 1 def dec(x): return x - 1 def operate(func, x): result = func(x) return result |
ما تابع را به شرح زیر فراخوانی می کنیم.
1 2 3 4 |
>>> operate(inc,3) 4 >>> operate(dec,3) 2 |
به علاوه، یک تابع می تواند تابع دیگری را برگرداند.
1 2 3 4 5 6 7 8 9 10 |
def is_called(): def is_returned(): print("Hello") return is_returned new = is_called() # Outputs "Hello" new() |
خروجی
1 |
Hello |
در اینجا، ()iis_returned یک تابع تو در تو است که هر بار ()is_called فراخوانی شود تعریف شده و برمی گردد.
دکوراتورها در پایتون
در واقع ، هر شیئی که متد ویژه ()__call __ را اجرا کند ، قابل فراخوانی است. بنابراین ، در اساسی ترین مفهوم دکوراتور یک قابل فراخوانی است که قابل فراخوانی قابل را برمی گرداند.
در واقع ، یک دکوراتور یک تابع را می گیرد، برخی از قابلیت ها را به آن اضافه می کند و آن را برمی گرداند.
1 2 3 4 5 6 7 8 9 |
def make_pretty(func): def inner(): print("I got decorated") func() return inner def ordinary(): print("I am ordinary") |
وقتی کدهای زیر را بصورت پوسته اجرا می کنید،
1 2 3 4 5 6 7 8 |
>>> ordinary() I am ordinary >>> # let's decorate this ordinary function >>> pretty = make_pretty(ordinary) >>> pretty() I got decorated I am ordinary |
در مثالی که در بالا نشان داده شده، ()make_pretty یک دکوراتور است. در مرحله تخصیص، داریم که:
1 |
pretty = make_pretty(ordinary) |
تابع ()ordinary دکوریت میشود و به تابع برگشت داده شده pretty گفته می شود.
می توانیم ببینیم که تابع دکوراتور برخی از قابلیت های جدید را به تابع اصلی اضافه کرده است. این شبیه بسته بندی هدیه است. دکوراتور به عنوان یک بسته بندی عمل می کند. ماهیت شیئی که تزئین شده است (هدیه واقعی داخل) تغییری نمی کند. اما اکنون، بسیار زیبا به نظر می رسد (از زمانی که تزئین شده است).
به طور کلی، ما یک تابع را دکوریت می کنیم و دوباره آن را استفاده می کنیم.
1 |
ordinary = make_pretty(ordinary). |
این یک ساختار مشترک است و به همین دلیل، پایتون برای ساده سازی این یک نحو دارد.
ما می توانیم از نماد @ به همراه نام تابع دکوراتور استفاده کنیم و آن را بالای تعریف تابع برای دکوریت شدن قرار داد. مثلا،
1 2 3 |
@make_pretty def ordinary(): print("I am ordinary") |
برابر است با
1 2 3 |
def ordinary(): print("I am ordinary") ordinary = make_pretty(ordinary) |
تابع های دکوراتور با پارامترها در پایتون
دکوراتور فوق ساده بود و فقط با توابعی کار می کرد که هیچ پارامتری نداشتند. اگر توابعی داشته باشیم که پارامترهایی مانند موارد زیر داشته باشند
1 2 |
def divide(a, b): return a/b |
این تابع دارای دو پارامتر a و b است. ما می دانیم که اگر در b به صورت مقدار 0 پاس داده شود، خطایی ایجاد می کند.
1 2 3 4 5 6 |
>>> divide(2,5) 0.4 >>> divide(2,0) Traceback (most recent call last): ... ZeroDivisionError: division by zero |
حالا بیایید یک دکوراتور بسازیم تا این مورد را که باعث خطا می شود بررسی کند.
1 |
def smart_divide(func): |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def smart_divide(func): def inner(a, b): print("I am going to divide", a, "and", b) if b == 0: print("Whoops! cannot divide") return return func(a, b) return inner @smart_divide def divide(a, b): print(a/b) |
در صورت بروز خطا، این پیاده سازی جدید None را برمی گرداند.
1 2 3 4 5 6 7 |
>>> divide(2,5) I am going to divide 2 and 5 0.4 >>> divide(2,0) I am going to divide 2 and 0 Whoops! cannot divide |
به این ترتیب ، ما می توانیم توابعی را که پارامتر می گیرند، دکوریت کنیم.
یک ناظر دقیق متوجه می شود که پارامترهای تابع تو در تو ()inner در داخل دکوراتور همان پارامترهای تابعی است که دکوریت می کند. با در نظر گرفتن این نکته، اکنون می توانیم دکوراتور کلی ایجاد کنیم که با هر تعداد پارامتر کار می کنند.
در پایتون، این کار به صورت تابع (function(*args, **kwargs) انجام می شود. به این ترتیب، args انبوهی از استدلالهای موقعیتی و kwargs دیکشنری آرگومان های کلمه کلیدی خواهند بود. نمونه ای از چنین دکوراتورها:
1 2 3 4 5 |
def works_for_all(func): def inner(*args, **kwargs): print("I can decorate any function") return func(*args, **kwargs) return inner |
زنجیر کردن دکوراتورها در پایتون
چندین دکوراتور را می توان در پایتون زنجیر زد.
این بدان معناست که یک تابع را می توان چندین بار با دکوراتورهای مختلف (یا همان) دکوریت کرد. ما به سادگی دکوراتورها را بالاتر از تابع مورد نظر قرار می دهیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def star(func): def inner(*args, **kwargs): print("*" * 30) func(*args, **kwargs) print("*" * 30) return inner def percent(func): def inner(*args, **kwargs): print("%" * 30) func(*args, **kwargs) print("%" * 30) return inner @star @percent def printer(msg): print(msg) printer("Hello") |
خروجی
1 2 3 4 5 6 7 |
****************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Hello %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ****************************** |
نحو بالا برای:
1 2 3 4 |
@star @percent def printer(msg): print(msg) |
برابر است با:
1 2 3 |
def printer(msg): print(msg) printer = star(percent(printer)) |
نظم و ترتیب ما در زنجیر کزددن دکوراتوز مهم است. اگر ما دستور را معکوس کرده بودیم ،
1 2 3 4 |
@percent @star def printer(msg): print(msg) |
خروجی
1 2 3 4 5 6 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ****************************** Hello ****************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
لیست جلسات قبل آموزش برنامه نویسی پایتون
- آموزش نصب و اجرای برنامه نویسی پایتون
- کلیدواژه ها و شناسه های برنامه نویسی پایتون
- دستورات، تورفتگی ها و کامنت ها در برنامه نویسی پایتون
- متغیرها، ثابت ها و لیترال ها در برنامه نویسی پایتون
- انواع داده ها در برنامه نویسی پایتون
- تبدیل نوع در برنامه نویسی پایتون
- ورودی، خروجی و وارد کردن در برنامه نویسی پایتون
- عملگرها در برنامه نویسی پایتون
- نام و دامنه در برنامه نویسی پایتون
- دستور شرطی if…else در برنامه نویسی پایتون
- حلقه for در برنامه نویسی پایتون
- حلقه while در برنامه نویسی پایتون
- دستورات break و continue در برنامه نویسی پایتون
- دستور pass در برنامه نویسی پایتون
- توابع در برنامه نویسی پایتون
- آرگومان تابع در برنامه نویسی پایتون
- تابع بازگشتی در برنامه نویسی پایتون
- تابع بی نام/ تابع لامبدا در برنامه نویسی پایتون
- متغیرهای سراسری، محلی و غیر محلی در برنامه نویسی پایتون
- کلیدواژه global در برنامه نویسی پایتون
- ماژول های برنامه نویسی پایتون
- پکیج ها در برنامه نویسی پایتون
- اعداد و تبدیل نوع داده در برنامه نویسی پایتون
- لیست در برنامه نویسی پایتون
- تاپل در برنامه نویسی پایتون
- رشته ها در برنامه نویسی پایتون
- مجموعه ها در برنامه نویسی پایتون
- دیکشنری در برنامه نویسی پایتون
- عملیات ورودی/خروجی در برنامه نویسی پایتون
- دایرکتوری و مدیریت فایل ها در برنامه نویسی پایتون
- خطاها و استثناهای توکار در برنامه نویسی پایتون
- مدیریت استثناها در برنامه نویسی پایتون
- استثناهای تعریف شده توسط کاربر در برنامه نویسی پایتون
- برنامه نویسی شی گرا در پایتون
- اشیا و کلاس ها در برنامه نویسی پایتون
- وراثت در برنامه نویسی پایتون
- وراثت چندگانه در برنامه نویسی پایتون
- سربارگذاری عملگرها در برنامه نویسی پایتون
- تکرار کننده ها در برنامه نویسی پایتون
- Generator در برنامه نویسی پایتون
- بستار در برنامه نویسی پایتون
دیدگاه شما