آشنایی با دستور global در زبان برنامه نویسی پایتون


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

def setScope():
    scope = "local"
scope = "global"
setScope()
print(scope)

این برنامه را در فایل setScope.py ذخیره می کنیم. اجرای برنامه از خط سوم آغاز می شود، و در ابتدا یک متغیر گلوبال با شناسه ی scope که به استرینگ "global" منتسب شده است ایجاد می شود. سپس فانکشن ()setScope فراخوانی می شود. با فراخوانی این فانکشن یک متغیر لوکال جدید با همان شناسه ی scope ایجاد می شود که به استرینگ "local" منتسب شده است. می بینید که نام این دو متغیر یکسان است، اما هویت آن ها متفاوت از یکدیگر است. متغیر لوکال با پایان یافتن کار فانکشن از حافظه ی کامپیوتر حذف می شود. دستور پایانی این برنامه مقدار متغیر scope گلوبال را چاپ می کند:

global

همان طور که می بینید فراخوانی فانکشن ()setScope هیچ تأثیری روی متغیر scope گلوبال ندارد. حال فرض کنید بخواهیم مقدار این متغیر گلوبال را در داخل فانکشن ()setScope تغییر دهیم. برای این کار از دستور global استفاده می کنیم و برنامه را به صورت زیر بازنویسی می کنیم:

def setScope():
    global scope
    scope = "local"  # This is a global variable.
scope = "global"
setScope()
print(scope)

این برنامه را در فایلی با نام setGlobalScope.py ذخیره می کنیم. اجرای برنامه از خط چهارم آغاز می شود و یک متغیر گلوبال با شناسه ی scope ایجاد و به استرینگ "global" منتسب می شود. سپس فانکشن ()setScope فراخوانی می شود. دستور اول در بدنه ی این فانکشن با کیورد global آغاز می شود و در ادامه ی آن شناسه ی متغیر scope آمده است. این دستور به مفسر پایتون اعلام می کند که "در این فانکشن شناسه ی scope به یک متغیر گلوبال ارجاع می دهد و بنابراین هیچ متغیر لوکالی با این شناسه نساز."

با این کار وقتی در دستور بعدی در بدنه ی فانکشن متغیر scope به مقدار "local" منتسب می شود، این همان متغیر گلوبال است و متغیر لوکال جدیدی با شناسه ی scope ایجاد نمی شود. در پایان برنامه دستور پرینت اجرا می شود و مقدار متغیر scope را چاپ می کند:

local

همان طور که می بینید این بار بر خلاف برنامه ی قبل با فراخوانی فانکشن ()setScope مقدار متغیر گلوبال scope تغییر پیدا می کند. برای این که بدانیم آیا یک متغیر لوکال است یا گلوبال چهار قاعده وجود دارد:
1- اگر یک متغیر در دامنه ی گلوبال تعریف و استفاده شود (یعنی خارج از دستور تعریف تمام فانکشن های برنامه)، در این صورت آن متغیر گلوبال است.
2- اگر در بدنه ی یک فانکشن کیورد global پیش از شناسه ی یک متغیر بیاید آن متغیر گلوبال است.
3- اگر متغیری در شرایط بالا صدق نکند و در دستور انتسابی در یک فانکشن مورد استفاده قرار گیرد، یک متغیر لوکال است.
4- اما اگر متغیر در بدنه ی تابع استفاده شود، ولی در دستور انتسابی استفاده نشود باز هم متغیر گلوبال است.

برای درک بهتر این قواعد برنامه ی زیر را در نظر بگیرید:

def setGlobalScope():
    global scope
    scope = "global" # this is the global

def setScope():
    scope = "local" # this is the local
    
def printScope():
    print(scope) # this is the global
    
scope = None # this is the global
setGlobalScope()
setScope()
printScope()

برنامه ی فوق را در فایلی تحت عنوان sameName.py ذخیره می کنیم. مفسر پایتون اجرای برنامه را از دستور scope = None شروع می کند که یک متغیر گلوبال با نام scope و بدون مقدار ایجاد می کند. سپس با فراخوانی فانکشن ()setGlobalScope، از آن جا که یک دستور global برای شناسه ی scope در ابتدای این فانکشن آمده است، مقدار این متغیر گلوبال به استرینگ "global" تغییر پیدا می کند. سپس فانکشن ()setScope فراخوانی می شود. متغیر scope که در بدنه ی این فانکشن مورد استفاده قرار گرفته است در دو قاعده ی اول صدق نمی کند و طبق قاعده ی سوم -چون متغیر scope در یک دستور انتسابی آمده است- پس یک متغیر لوکال است و پس از پایان کار این فانکشن مقدار آن از حافظه پاک خواهد شد.

آخرین دستور این برنامه فراخوانی فانکشن ()printScope است. در این فانکشن از متغیری با نام scope به عنوان آرگومان تابع پرینت استفاده شده است تا مقدار آن چاپ شود. از آن جا که این متغیر در یک دستور انتسابی در این فانکشن نیامده است، یک متغیر گلوبال است و مقدار نهایی متغیر گلوبال scope را نشان می دهد. بنابراین در نهایت خروجی این برنامه به صورت زیر است:

global

برای هر متغیری که در یک فانکشن ظاهر می شود تنها دو حالت وجود دارد: متغیر مورد نظر یا لوکال است یا گلوبال. به عبارت دیگر در یک فانکشن نمی توان به طور هم زمان دو متغیر با یک شناسه داشته باشیم که یکی لوکال باشد و دیگری گلوبال. اگر بخواهیم مقدار یک متغیر گلوبال را در یک فانکشن تغییر دهیم باید حتماً از دستور global استفاده کنیم. اگر در فانکشنی از یک متغیر لوکال استفاده کنیم، بدون آن که ابتدا آن را به آبجکتی منتسب کرده باشیم، با اعلام خطای مفسر پایتون رو به رو خواهیم شد. برای مثال برنامه ی زیر که اسکریپت آن را در فایل error.py ذخیره می کنیم در نظر بگیرید:

def printScope():
    print(scope) # Error!
    scope = "local scope" # this is the  local
    
scope = "global scope" # this is the  global
printScope()

با اجرای برنامه ی بالا با خطای زیر مواجه می شویم:

============= RESTART: D:/sokanacademy/Python/error.py =============
Traceback (most recent call last):
  File "D:/sokanacademy/Python/error.py", line 6, in 
    printScope()
  File " D:/sokanacademy/Python/error.py ", line 2, in printScope
    print(scope) # Error!
UnboundLocalError: local variable 'scope' referenced before assignment
>>>

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

دانلود فایل‌های تمرین
لیست نظرات
کاربر میهمان
دیدگاه شما چیست؟
کاربر میهمان
sAmo
sAmo
سلام. چرا با این که در سایت عضو هستم، برنامه آموزشی که انتخاب کردم در داشبوردم باقی نمی ماند و هر بار باید برنامه را انتخاب و شروع کنم؟
ادمین سایت
ادمین سایت
با سلام خدمت شما کاربر گرامی
سیستم به این شکل نیست که شما دوره یی را انتخاب کرده و در داشبورد شما باقی بماند.

ارادتمند
تیم سکان آکادمی

در پاسخ به

محمدهادی
محمدهادی
سوال دوم. گزینه ی سوم باید نوشته بشه قرار نگیرد
ادمین سایت
ادمین سایت
با سلام و تشکر از توجه شما
اصلاح گردید

در پاسخ به

RMA
RMA
کی ادامه آموزش رو میذارید؟
نرگس اسدی
نرگس اسدی
سلام
ان شاءالله به زودی

در پاسخ به

کاربر میهمان
کاربر میهمان
سلام , ادامه آموزش رو کی تو سایت درج میکنید؟
و اینکه چند وقت به چند وقت این بخش آپدیت میشه؟