بستار در برنامه نویسی پایتون

4 سال پیش

بستار در برنامه نویسی پایتون

در این درس از مجموعه آموزش برنامه نویسی سایت سورس باران، شما با بستار در برنامه نویسی پایتون (Python Closures)، نحوه تعریف بستار و دلایل استفاده از آن آشنا خواهید شد.

پیشنهاد ویژه : پکیج آموزش پایتون

متغیر غیر محلی در یک تابع تو در تو

قبل از اینکه بدانیم بستار چیست، ابتدا باید بفهمیم که یک تابع تو در تو و یک متغیر غیر محلی چیست.

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

در پایتون، این متغیرهای غیر محلی به طور پیش فرض فقط خواندنی هستند و برای اصلاح آنها باید صریحاً آنها را غیر محلی (با استفاده از کلمه کلیدی  non-local) اعلان کنیم.

در زیر مثالی از تابع تو در تو که به یک متغیر غیر محلی دسترسی پیدا می کند، آورده شده است.

def print_msg(msg):
    # This is the outer enclosing function

    def printer():
        # This is the nested function
        print(msg)

    printer()

# We execute the function
# Output: Hello
print_msg("Hello")

 

خروجی

Hello

 

می توانیم ببینیم که تابع ()printer تو در تو قادر به دسترسی به متغیر msg غیر محلی از تابع محصور در آن است.

در مثال بالا ، اگر خط آخر تابع () print_msg به جای فراخوانی تابع ()printer ، آن را برگرداند چه اتفاقی می افتد؟ این بدان معنی است که تابع به شرح زیر تعریف شده است:

def print_msg(msg):
    # This is the outer enclosing function

    def printer():
        # This is the nested function
        print(msg)

    return printer  # returns the nested function


# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()

 

خروجی

Hello

 

این غیرمعمول است

تابع ()print_msg  با رشته “Hello” فراخوانی می شود و تابع بازگشتی به نام ()another محدود می شود. با فراخوانی ()another ، پیام هنوز به خاطر سپرده می شد اگرچه ما در حال حاضر اجرای تابع ()print_msg  را به پایان رسانده بودیم.

به این تکنیک که برخی داده ها (“Hello” در این مورد) به کد متصل می شوند، بستار در پایتون نامیده می شود.

این مقدار در محدوده محصور  حتی وقتی متغیر از محدوده خارج می شود یا اینکه خود تابع از فضای نام فعلی حذف می شود، به یاد می آید.

برای دیدن خروجی، موارد زیر را در پوسته پایتون اجرا کنید.

>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined

 

در اینجا، تابع بازگشتی حتی هنگام حذف تابع اصلی نیز کار می کند.

چه زمانی به بستار در پایتون نیاز است؟

همانطور که از مثال بالا دیده می شود، وقتی تابع تو در تو مقدار را در دامنه محصور خود ارجاع می دهد، یک بستار در پایتون داریم.

معیارهایی که برای ایجاد بستار در پایتون باید رعایت شود، در موارد زیر خلاصه می شود.

  • ما باید یک تابع تو در تو داشته باشیم (تابع درون یک تابع).
  • تابع تو در تو باید به مقداری که در تابع محصور تعریف شده است ، اشاره کند.
  • تابع محصور باید تابع تو در تو را برگرداند.

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

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

وقتی روشهای کمی وجود دارد (در اکثر موارد یک روش) که باید در یک کلاس پیاده سازی شود ، بسته شدن می تواند یک راه حل جایگزین و زیبا ارائه دهد. اما وقتی تعداد ویژگی ها و روش ها بیشتر شد ، بهتر است یک کلاس را پیاده سازی کنید.

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

def make_multiplier_of(n):
    def multiplier(x):
        return x * n
    return multiplier


# Multiplier of 3
times3 = make_multiplier_of(3)

# Multiplier of 5
times5 = make_multiplier_of(5)

# Output: 27
print(times3(9))

# Output: 15
print(times5(3))

# Output: 30
print(times5(times3(2)))

 

خروجی

۲۷
۱۵
۳۰

 

دکوراتورها در پایتون نیز استفاده گسترده ای از بستار ها دارند.

به این نکته اشاره کنیم که مقادیری را که در تابع بستار محصور شده اند، می توان دریافت.

همه اشیا  تابع دارای یک ویژگی __closure__ هستند که یک تاپل از اشیای سلول را در صورتی که یک تابع بستار باشد، باز می ‌گرداند. با ارجاع به مثال بالا، times3 و times5 توابع بستار هستند.

>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)

 

شی cell سلول دارای ویژگی cell_contents است که مقدار بسته را ذخیره می کند.

>>> times3.__closure__[0].cell_contents
۳
>>> times5.__closure__[0].cell_contents
۵

 

منبع.

لیست جلسات قبل آموزش برنامه نویسی پایتون

  1. آموزش نصب و اجرای برنامه نویسی پایتون
  2. کلیدواژه ها و شناسه های برنامه نویسی پایتون
  3. دستورات، تورفتگی ها و کامنت ها در برنامه نویسی پایتون
  4. متغیرها، ثابت ها و لیترال ها در برنامه نویسی پایتون 
  5. انواع داده ها در برنامه نویسی پایتون
  6. تبدیل نوع در برنامه نویسی پایتون
  7. ورودی، خروجی و وارد کردن در برنامه نویسی پایتون
  8. عملگرها در برنامه نویسی پایتون
  9. نام و دامنه در برنامه نویسی پایتون
  10. دستور شرطی if…else در برنامه نویسی پایتون
  11. حلقه for در برنامه نویسی پایتون
  12. حلقه while در برنامه نویسی پایتون
  13. دستورات break و continue در برنامه نویسی پایتون
  14. دستور pass در برنامه نویسی پایتون
  15. توابع در برنامه نویسی پایتون
  16. آرگومان تابع در برنامه نویسی پایتون
  17. تابع بازگشتی در برنامه نویسی پایتون
  18. تابع بی نام/ تابع لامبدا در برنامه نویسی پایتون
  19. متغیرهای سراسری، محلی و غیر محلی در برنامه نویسی پایتون
  20. کلیدواژه global در برنامه نویسی پایتون
  21. ماژول های برنامه نویسی پایتون
  22. پکیج ها در برنامه نویسی پایتون
  23. اعداد و تبدیل نوع داده در برنامه نویسی پایتون 
  24. لیست در برنامه نویسی پایتون
  25. تاپل در برنامه نویسی پایتون 
  26. رشته ها در برنامه نویسی پایتون
  27. مجموعه ها در برنامه نویسی پایتون
  28. دیکشنری در برنامه نویسی پایتون
  29. عملیات ورودی/خروجی در برنامه نویسی پایتون 
  30. دایرکتوری و مدیریت فایل ها در برنامه نویسی پایتون
  31. خطاها و استثناهای توکار در برنامه نویسی پایتون
  32. مدیریت استثناها در برنامه نویسی پایتون
  33. استثناهای تعریف شده توسط کاربر در برنامه نویسی پایتون
  34. برنامه ‌نویسی شی گرا در پایتون
  35. اشیا و کلاس ها در برنامه نویسی پایتون
  36. وراثت در برنامه نویسی پایتون
  37. وراثت چندگانه در برنامه نویسی پایتون
  38. سربارگذاری عملگرها در برنامه نویسی پایتون
  39. تکرار کننده ها در برنامه نویسی پایتون
  40. Generator در برنامه نویسی پایتون

 

0
برچسب ها :
نویسنده مطلب erfan molaei

دیدگاه شما

بدون دیدگاه