کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

آموزش Scope و Namespace در پایتون


آموزش حوزه ها و فضاهای نام در زبان برنامه نویسی پایتون


قبل از معرفی کلاس ها، ابتدا باید اطلاعاتی درباره قوانین حوزه های (scope) پایتون را در اختیارتان قرار دهم. تعاریف کلاس با ترفندهایی با فضاهای نام (namespaces) بازی می کنند، و شما برای فهمیدن اینکه چه اتفاقی در حال رخ دادن است، باید بدانید حوزه ها و فضاهای نام چگونه کار می کنند. اتفاقا، داشتن دانش درباره این موضوع برای هر برنامه نویس حرفه ای پایتون مفید است. بیایید با تعدادی از تعاریف شروع کنیم.

آموزش Namespaces در Python


فضای نام یک نگاشت از نام ها به اشیا است. اکثر فضاهای نام در حال حاضر به عنوان دیکشنری های پایتون پیاده سازی شده اند، اما به طور معمول به هیچ وجه قابل توجه نیستند (به جز برای کارایی)، و ممکن است در آینده تغییر کنند. مثال هایی از فضای نام عبارتند از: مجموعه ای از نام های داخلی(built-in) (شامل توابعی مانند abs()، و نام استثناهای داخلی)، نام های سراسری در یک ماژول، و نام های محلی در یک فراخوانی تابع. به این معنا که مجموعه ای از ویژگی های یک شی، یک فضای نام را نیز تشکیل می دهند.

نکته مهمی که باید درباره فضاهای نام بدانید این است که مطلقا هیچ ارتباطی بین نام ها در فضاهای نام مختلف وجود ندارد. برای مثال، ممکن است دو ماژول مختلف، هر دو یک تابع به نام maximize را بدون ابهام تعریف کنند—کاربران ماژول ها باید آن را با نام ماژول، پیشوند سازی کنند.

ضمنا، من از کلمه ‘ویژگی’ برای هر نامی که پس از یک نقطه بیاید استفاده می کنم—برای مثال، در عبارت z.real ، real یک ویژگی شی z است. تاکید می کنم، ارجاع به نام ها در ماژول ها، ارجاع ویژگی است. در این مورد، یک نگاشت مستقیم بین ویژگی های ماژول و نام های سراسری تعریف شده در ماژول رخ می دهد. آنها فضای نام یکسانی را به اشتراک می گذارند.

آموزش Attributes در Python


ویژگی ها می توانند فقط-خواندنی یا قابل نوشتن باشند. در حالت دوم، تخصیص به ویژگی ها امکان پذیر است. ویژگی های ماژول قابل نوشتن هستند: می توانید بنویسید modname.the_answer = 42 . همچنین ممکن است ویژگی های قابل نوشتن توسط عبارت del پاک شوند. برای مثال، del modname.the_answer ویژگی the_answer را از شی ای به نام modname حذف می کند.

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

معمولا،‌ فضای نام ماژول نیز تا زمان اتمام کار مفسر باقی می ماند. عبارات اجرا شده توسط فراخوانی سطح بالای مفسر، که از یک فایل script خوانده شده یا به صورت تعاملی وارد شده است، به عنوان بخشی از یک ماژول به نام __main__ در نظر گرفته می شود. بنابراین آنها فضای نام سراسری خود را دارند. ( در واقع نام های داخلی نیز درون یک ماژول می مانند، این builtins نام دارد.)

فضای نام محلی برای یک تابع، در زمان فراخوانی تابع ساخته می شود، و زمانی که تابع مقداری را باز گرداند یا استثنایی را اعلام کند که درون تابع اداره نشده باشد، پاک می شود. ( در واقع، فراموش کردن روش بهتری برای توصیف چیزی است که واقعا رخ می دهد.) البته، فراخوانی های بازگشتی فضای نام محلی خود را دارند.

آموزش scope در Python


حوزه (scope) یک ناحیه متنی از یک برنامه پایتون است، جایی که فضای نام مستقیما در دسترس است. در اینجا “دسترسی مستقیم” به این معنی است که یک ارجاع فاقد صلاحیت به یک نام، برای پیدا کردن نام در فضای نام اقدام می کند.

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

  • داخلی ترین حوزه، که ابتدا جستجو می شود، در بر دارنده نام های محلی است.
  • حوزه های توابع محصور، که با جستجو از نزدیک ترین حوزه محصور شروع می کند، در بر دارنده نام های غیر محلی و همچنین غیر سراسری است.
  • حوزه یکی مانده به آخر در بر دارنده نام های سراسری ماژول فعلی است.
  • خارجی ترین حوزه (که در انتها جستجو می شود) فضای نامی است که در بر دارنده نام های داخلی است.

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

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

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

اگر چه، تعریف زبان به سمت وضوح نام به صورت ایستا در زمان کامپایل، در حال تغییر است. بنابراین به وضوح نام به صورت پویا تکیه نکنید! (در حقیقت متغیر های محلی در حال حاضر به صورت ایستا تعیین می شود.)

یک تغییر خاص در پایتون این است که -- اگر هیچ عبارت سراسری یا غیر محلی نباشد—تخصیص به نام ها همیشه به داخلی ترین حوزه می رود. تخصیص ها داده را کپی نمی کنند—آنها فقط نام ها را به اشیا اتصال می دهند. درباره پاک کردن نیز همینطور است. عبارت del x ، اتصال x و فضای نام ارجاع یافته توسط حوزه محلی را حذف می کند. در حقیقت تمام عملیاتی که نام های جدیدی را معرفی می کنند از حوزه محلی استفاده می کنند. به خصوص، عبارات import و تعاریف تابع، نام ماژول یا تابع را در حوزه محلی متصل می کند.

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

مثال حوزه ها و فضاهای نام در Python


این مثال چگونگی ارجاع به حوزه ها و فضاهای نام مختلف و نیز چگونگی تاثیرگذاری سراسری و غیر محلی بودن روی اتصال(binding) متغیر ها را نمایش می دهد.

    def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)

خروجی کد مربوط به این مثال به صورت زیر است:

    After local assignment: test spam
    After nonlocal assignment: nonlocal spam
    After global assignment: nonlocal spam
    In global scope: global spam

توجه داشته باشید که چگونه تخصیص محلی (که پیش فرض است) اتصال(binding) spam مربوط به scope_test را تغییر نداد. تخصیص غیر محلی، اتصال spam مربوط به scope_test را تغییر داد، و تخصیص سراسری اتصال سطح ماژول را تغییر داد. همچنین می توانید ببینید که قبل از تخصیص سراسری، هیچ اتصالی از قبل برای spam وجود نداشته است.

1403/05/29 3726 627
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...