سطح مقدماتی (Beginner Level)
مفهوم Scope (محدوده یا حوزه) در پایتون تعیین میکند که متغیرها در کدام قسمت از کد قابل دسترسی و استفاده هستند. درک Scope برای جلوگیری از خطاهای رایج مانند NameError و فهمیدن اینکه چرا مقدار یک متغیر تغییر کرده (یا نکرده)، حیاتی است.
به زبان ساده، Scope شبیه به "محفظه" یا "دیوار شیشهای" است. اگر متغیری را داخل یک اتاق (تابع) تعریف کنید، افراد بیرون اتاق نمیتوانند آن را ببینند.
۱. محدوده محلی (Local Scope)
متغیرهایی که درون یک تابع (Function) تعریف میشوند، دارای محدوده محلی هستند. این متغیرها فقط در داخل همان تابع زنده هستند و به محض تمام شدن اجرای تابع، از حافظه پاک میشوند.
مثال ۱: عدم دسترسی خارج از تابع
در این مثال میبینیم که متغیر تعریف شده در تابع، بیرون از آن وجود ندارد. (کد به صورت Static است چون اجرا کردن خط آخر باعث خطا میشود).
# Static: این کد اگر اجرا شود در خط آخر خطا میدهد
def my_func():
x = 300 # متغیر محلی
print(f"Inside function: {x}")
my_func()
# این خط باعث خطای NameError میشود چون x فقط داخل تابع وجود دارد
# print(x)
مثال ۲: دو متغیر محلی با نام یکسان
شما میتوانید در دو تابع مختلف، متغیرهایی با نام یکسان داشته باشید. آنها هیچ ربطی به هم ندارند.
۲. محدوده سراسری (Global Scope)
متغیرهایی که در بدنه اصلی فایل (خارج از هر تابعی) تعریف میشوند، متغیرهای Global یا سراسری نام دارند. این متغیرها در تمام طول برنامه و حتی داخل توابع قابل "خواندن" (Read) هستند.
مثال ۱: خواندن متغیر Global در تابع
توابع میتوانند مقادیر بیرونی را ببینند.
مثال ۲: تفاوت خواندن و تغییر دادن (Shadowing)
اگر داخل تابع متغیری با نام مشابه متغیر Global بسازید، پایتون یک متغیر جدید محلی میسازد و متغیر بیرونی را تغییر نمیدهد. به این کار Shadowing (سایه انداختن) میگویند.
سطح پیشرفته (Professional Level)
در سطح حرفهای، مدیریت Scope پیچیدهتر میشود. ما با کلمات کلیدی برای تغییر رفتار پیشفرض پایتون و همچنین توابع تو در تو (Nested Functions) سر و کار داریم.
۱. کلمه کلیدی global
همانطور که در بخش مقدماتی دیدیم، شما نمیتوانید مستقیماً یک متغیر Global را از داخل تابع تغییر دهید (فقط یک کپی محلی ساخته میشود). برای تغییر مقدار اصلی متغیر Global، باید از کلمه کلیدی global استفاده کنید.
نکته امنیتی: استفاده بیش از حد از global کد را ناخوانا و دیباگ کردن را سخت میکند.
۲. قانون LEGB (سلسله مراتب جستجو)
وقتی پایتون با نام یک متغیر روبرو میشود، برای پیدا کردن مقدار آن به ترتیب زیر (از چپ به راست) جستجو میکند:
- Local (محلی): داخل تابع فعلی.
- Enclosing (احاطهکننده): داخل توابع پدر (در صورت وجود توابع تو در تو).
- Global (سراسری): سطح ماژول اصلی.
- Built-in (پیشفرض): توابع و متغیرهای داخلی پایتون (مثل
print,len).

۳. کلمه کلیدی nonlocal و توابع تو در تو
وقتی توابع تو در تو (Nested Functions) دارید، تابع داخلی نمیتواند متغیر تابع پدر (Enclosing) را تغییر دهد مگر اینکه از nonlocal استفاده کند. این مفهوم برای ساخت Closureها بسیار مهم است.
مثال: بدون nonlocal (رفتار عادی)
# Static: فقط تعریف تابع
def outer():
x = "Outer"
def inner():
x = "Inner" # یک متغیر لوکال جدید برای inner
inner()
return x # همچنان "Outer" برمیگرداند
مثال: استفاده از nonlocal (تغییر متغیر پدر)
۴. چالشهای Built-in Scope
باید مراقب باشید که نام متغیرهای خود را همنام با توابع داخلی پایتون (Built-in) نگذارید. اگر متغیری به نام len یا sum بسازید، دسترسی به تابع اصلی پایتون را در آن Scope از دست میدهید.