Kahibaro
Discord Login Register

محدودهٔ متغیرها (محلی در برابر سراسری)

تفاوت محدودهٔ متغیرها

در پایتون هر متغیر «جایی» دارد که در آن قابل استفاده است. به این «جا» می‌گوییم محدودهٔ متغیر (Scope). در این بخش روی دو نوع محدوده تمرکز می‌کنیم:

درک درست این دو نوع محدوده کمک می‌کند از خطاهای گیج‌کننده جلوگیری کنید و کد تمیزتری بنویسید.


متغیر سراسری (Global)

متغیر سراسری متغیری است که بیرون از همهٔ توابع تعریف شده باشد.

x = 10   # متغیر سراسری
def show_x():
    print(x)   # از x سراسری استفاده می‌کند
show_x()       # خروجی: 10
print(x)       # خروجی: 10

اینجا x بیرون از تابع تعریف شده، پس «سراسری» است و هم در تابع show_x و هم بعد از آن قابل استفاده است.


متغیر محلی (Local)

متغیر محلی متغیری است که داخل یک تابع تعریف می‌شود:

def test():
    y = 5      # متغیر محلی
    print("داخل تابع:", y)
test()
print("بیرون تابع:", y)   # خطا: NameError

متغیر y فقط درون تابع test وجود دارد. وقتی تابع تمام می‌شود، y دیگر در دسترس نیست.


تداخل نام‌ها: وقتی محلی و سراسری همنام می‌شوند

اگر داخل تابع متغیری با همان نام یک متغیر سراسری تعریف کنید، متغیر محلی روی آن نام درون تابع «سایه» می‌اندازد.

x = 10   # سراسری
def test():
    x = 5    # محلی؛ روی x سراسری سایه می‌اندازد
    print("داخل تابع:", x)
test()
print("بیرون تابع:", x)

خروجی:

این دو x در واقع دو متغیر جدا هستند که فقط نام یکسان دارند.


چرا نمی‌توانیم به‌سادگی سراسری را داخل تابع تغییر دهیم؟

اگر فقط بخواهید مقدار یک متغیر سراسری را بخوانید، مشکلی نیست. اما اگر بخواهید تغییرش دهید، پایتون فرض می‌کند که شما یک متغیر محلی جدید ساخته‌اید.

count = 0
def wrong():
    count = count + 1   # خطا!
    print(count)
wrong()

این کد خطا می‌دهد، چون:

پس: وجود count = ... داخل تابع، باعث می‌شود count در آن تابع محلی محسوب شود.


استفاده از `global` برای تغییر متغیر سراسری

اگر واقعاً لازم شود یک متغیر سراسری را از داخل تابع تغییر دهید، باید از کلمهٔ کلیدی global استفاده کنید و صریحاً بگویید که منظور شما متغیر سراسری است.

count = 0   # سراسری
def increase():
    global count   # از count سراسری استفاده کن
    count = count + 1
increase()
increase()
print(count)   # خروجی: 2

خط global count به پایتون می‌گوید:

هرجا در این تابع از count استفاده می‌کنم، منظورم همان متغیر سراسری است، نه یک متغیر محلی جدید.

چرا استفاده زیاد از `global` بد است؟

هرچند global وجود دارد، ولی استفادهٔ زیاد از آن معمولاً ایدهٔ خوبی نیست:

الگوی بهتر این است که:

def increase(count):
    return count + 1
count = 0
count = increase(count)
count = increase(count)
print(count)   # خروجی: 2

در این روش:

محدودهٔ توابع تو در تو (کمی عمیق‌تر)

گاهی داخل یک تابع، تابع دیگری تعریف می‌کنیم:

x = 10  # سراسری
def outer():
    x = 20  # محلی برای outer
    def inner():
        x = 30  # محلی برای inner
        print("داخل inner:", x)
    inner()
    print("داخل outer:", x)
outer()
print("بیرون همه:", x)

محدوده‌ها به‌صورت «لایه‌لایه» کار می‌کنند:

  1. محلی تابع فعلی
  2. محدودهٔ توابع بیرونی (در صورت وجود)
  3. سراسری
  4. توابع و نام‌های داخلی پایتون

در مثال بالا:

(جزئیات کامل این مدل جستجو معمولاً با نام LEGB شناخته می‌شود، که اگر نیاز باشد در بخش‌های پیشرفته‌تر می‌توانید با آن آشنا شوید.)


اشتباه‌های رایج مبتدیان دربارهٔ محدوده

۱. انتظار داشتن از متغیر محلی که بیرونِ تابع هم کار کند

def make_number():
    n = 5
make_number()
print(n)   # خطا: NameError

راه درست: اگر لازم است مقدار را بیرون استفاده کنید، از تابع برگردانید (return) و بیرون در متغیری ذخیره کنید.

def make_number():
    n = 5
    return n
x = make_number()
print(x)   # خروجی: 5

۲. فراموش کردن اثر `global`

value = 100
def change():
    global value
    value = 0
change()
print(value)   # خروجی: 0

این نوع کدها اگر زیاد شوند، فهمیدن این‌که چرا مقدار value عوض شده، سخت خواهد شد.


چند تمرین ذهنی (بدون حل آماده)

برای تمرین، به این کدها فکر کنید و سعی کنید روی کاغذ حدس بزنید چه خروجی دارند:

۱.

x = 1
def a():
    x = 2
    print("a:", x)
def b():
    print("b:", x)
a()
b()
print("main:", x)

۲.

x = 1
def a():
    global x
    x = 2
def b():
    x = 3
    print("b:", x)
a()
b()
print("main:", x)

۳.

def outer():
    msg = "hello"
    def inner():
        print(msg)
    inner()
outer()

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

Views: 6

Comments

Please login to add a comment.

Don't have an account? Register now!