چالش روزانه · ۲۲ مهر ۱۴۰۵

چالش پایتون ۲: متغیری که هم هست و هم نیست

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

x = 10

def show():
    print(x)
    x = 20

show()
خروجی کدام است؟

نمایش پاسخ و توضیح

پاسخ درست: گزینهٔ ج — UnboundLocalError

چرا ۱۰ چاپ نمی‌شود؟

تصمیم دربارهٔ اینکه یک نام محلی است یا سراسری، هنگام اجرای تابع گرفته نمی‌شود؛ پایتون آن را هنگام کامپایل بدنهٔ تابع می‌گیرد.

چون داخل show جایی x = 20 آمده، پایتون x را برای کل تابع یک متغیر محلی در نظر می‌گیرد؛ حتی برای خط‌هایی که قبل از آن انتساب هستند. بنابراین print(x) می‌خواهد x محلی را بخواند که هنوز مقداری نگرفته است و نتیجه خطای زیر است:

UnboundLocalError: cannot access local variable 'x' where it is not associated with a value

این NameError نیست، چون نام x وجود دارد؛ فقط هنوز به مقداری «بسته» (bound) نشده است. (UnboundLocalError در واقع زیرکلاس NameError است، اما پیام دقیق همان اولی است.)

راه‌حل‌ها

اگر واقعاً می‌خواهید متغیر سراسری را تغییر دهید، از global استفاده کنید؛ هرچند بهتر است مقدار را از ورودی بگیرید و با return برگردانید:

x = 10

def show():
    global x
    print(x)
    x = 20

show()
print(x)

حالا خودت اجرا کن و تغییرش بده

x = 10

def show():
    print(x)
    x = 20

show()