متغیرهای local و global در ptyhon – { جلسه دوازدهم دوره پایتون }
مقدمه
در ادامه سلسله جلسات آموزش پایتون قصد داریم این جلسه به مبحثی بپردازیم که شاید بعضی اوقات برای ما مشکل ایجاد کند و به همین خاطر نیازمند درک دقیق و درستی از آن هستیم. موضوع این جلسه متغیرهای local و global در برنامه نویسی پایتون می باشد. قبل از ادامه این مطلب حتما لازم است که جلسات پیش نیاز مربوط به این جلسه را از لینک زیر مطالعه کنید:
منظور از local و global چیست ؟
قبل از این که توضیح دهیم منظورمان از متغیرهای local و global چیست ، بیایید توضیح دهیم اصلا خود کلمات local و global به چه معنا است.
کلمه local را در فارسی “محلی” تعریف کرده اند. برای درک بهتر این کلمه میتوانید حوزه این کلمه را مثل یک محله در نظر بگیرید. جایی که تعداد کوچکی خانه و خیابان وجود دارد. شاید یکی دو سوپر مارکت باشد و جایی به نسبت کوچک است.
در مقابل کلمه local ، کلمه Global تعریف می شود که در فارسی این کلمه را به “سراسری ” یا جهانی ترجمه کرده اند. کلمه Global را میتوان مشابه با یک شهر گرفت. شهر یک ناحیه بسیار بزرگ تر است. پر از خیابان است. خودش از چندین محله تشکیل شده اند.
در برنامه نویسی هم از این دو کلمه استفاده می کنند و حوزه های کاری و عملکرد متغیرها را local و global تعریف می کنند. شاید دیده باشید که می گویند “متغیرهای محلی یا سراسری در ++C” . ما در ادامه این مطلب سعی میکنیم از واژه های local و Global استفاده کنیم. علت هم این است که به نظر نویسنده ترجمه های انجام شده اگر چه صحیح می باشد ، اما حق مطلب را نمیتوانند به خوبی ادا کنند.
متغیرهای local و global در پایتون
مشابه با سایر زبان های برنامه نویسی ، در پایتون نیز متغیرهای local و global وجود دارند. این دو کلمه در واقع حوزه کاری متغیرها را مشخص می کنند. اما منظورمان از متغیرهای local و global چیست؟
منظورمان از متغیرهای global این است که از این گونه متغیرها میتوانیم در تمامی اجزای برنامه استفاده کنیم و همه جای برنامه نیز این متغیر را می شناسند. در مقابل آن متغیرهای local صرفا در یک حوزه مشخص میتوانند کار کنند و فقط بخشی از برنامه آن را می شناسد و بقیه اجزای برنامه آن را نمی شناسند. دقیقا مشابه با افراد در یک محله یا یک شهر. بیایید برای درک بهتر این موضوع مثالی را ارایه دهیم :
فرض کنید یک محله داریم و در آن محله آقای “محمدی” فرد معروفی است. آقای محمدی اگر به یک سوپر مارکتی برود ، همه او را می شناسند و به او نسیه می دهند. چون یک فرد آشنا است میتواند با تمامی افراد آن محله سلام و علیک داشته باشد.
اما اگر همین آقای محمدی به خارج از محله برود و بخواهد از سوپر مارکت های شهر نسیه بگیرد. به نظر شما به او نسیه می دهند ؟ قطعه نه ! چون او را نمی شناسند. اگر به افراد غریبه سلام کند ممکن است کسی پاسخ سلام او را ندهد. علت این است که آقای محمدی صرفا در محله خود آقای محمدی است و در جاهای دیگر کسی او را نمی شناسد.
اما فرض کنید که یک فرد مشهور داریم. مثلا “مهران مدیری” طنز پرداز خوب کشورمان را در نظر بگیرید. به این فرد در تمامی شهر نسیه می دهند. چون همه او را می شناسند. علاوه بر آن اگر آقای مدیری به محله آقای محمدی برود نیز ، همچنان میتواند از مغازه داران نسیه بگیرد و به همه سلام دهد. چون تمامی افراد آن محله نیز آقای مدیری را می شناسند.
مثال بالا دقیقا مفهوم متغیرهای local و global را بیان می کند. در مثال بالا آقای محمدی نقش یک متغیر local و آقای مدیری نقش یک متغیر global را دارد. حال بیایید همه آن چه که در بالا گفته شد را در قالب کد پایتون مشاهد کنید تا به درک بهتری برسیم. کد زیر را در نظر بگیرید:
my_var1 = 3 my_var2 = True def fucn_1(x): new_var = 2 if x == 4: return new_var print(new_var)
در کد بالا ما سه متغیر داریم. دو متغیر my_var1 و my_var2 که در ابتدای برنامه تعریف شده اند. متغیر new_var نیز در داخل تابع func_1 تعریف شده است. در انتهای برنامه ما خواسته ایم که مقدار متغیر new_var که داخل تابع تعریف شده است را ببینیم. اگر این کد را اجرا کنیم به نظر شما چه اتفاقی می افتد ؟ (لطفا یک بار خودتان این کد را تست کنید و سپس ادامه این مطلب را بخوانید.)
اگر این کد را اجرا کنیم ، با خطا ی زیر روبرو می شویم:
NameError: name 'new_var' is not defined
همانطور که میبینید با خطای NameError مواجه شده ایم و پایتون به ما می گوید که new_var تعریف نشده است. در حالی که ما آن راتعریف کرده ایم. علت چیست ؟
علت هم این است که متغیر new_var در داخل تابع تعریف شده است و فقط میتوانیم از آن در داخل همان تابع استفاده کنیم. در واقع حوزه کاری متغیر new_var محدود به همان تابع می شود و نه بیشتر . به این متغیر و کلا متغیرهایی از این نوع ، متغیرهای local می گویند.
این متغیرهای دقیقا مثل همان آقای محمدی هستند. تا وقتی که کدی را بخواهیم در داخل آن تابع اجرا کنیم ، از این متغیرها میتوانیم استفاده کنیم. ولی اگر بخواهیم بخش های دیگر کد را اجرا کنیم ، انگار نه انگار که چنین متغیری وجود دارد. همانگونه که وقتی آقای محمدی به شهر می رفت کسی او را نمی شناخت. این متغیر هم وقتی به شهر می رود (یعنی میخواهیم در سایر بخش های برنامه از آن استفاده کنیم) کسی او را نمی شناسد و به همین علت پایتون به ما خطا می دهد.
اگر در کد بالا کمی تغییر ایجاد کنیم و کد را به صورت زیر در بیاوریم :
my_var1 = 3 my_var2 = True def func_1(x): new_var = 2 print(new_var) if x == 4: return new_var func_1(4)
و اگر کد بالا را اجرا کنیم ، در این صورت خروجی برنامه مقدار 2 را به ما نشان می دهد. چون از متغیر new_var در داخل همان تابع استفاده کرده ایم و داخل همان تابع هم این متغیر شناخته شده است.
حال کد بالا را به صورت زیر تغییر می دهیم :
my_var1 = 3 my_var2 = True def func_1(x): new_var = 2 print(new_var) if x == 4: return new_var def otherFunc(): new_var = 5 print(new_var) otherFunc()
در کد بالا یک تابع دیگر تعریف کرده ایم و دقیقا متغیری هم نام با new_var دوباره تعریف کرده ایم و این بار مقدار آن را 5 قرار داده ایم. سپس تابع جدید را صدا زده ایم. با اجرای این برنامه میبینیم که خروجی مقدار 5 را چاپ می کند. یعنی مقداری که در تابع جدید تعریف کرده ایم و اصلا با مقدار موجود در تابع func_1 کار ندارد. در واقع وقتی تابع func_1 صدا زده می شود یک متغیر new_var ساخته می شود و وقتی که تابع تمام شد هم آن متغیر از بین میرود. دوباره وقتی تابع otherfunc صدا زده می شود دوباره یک متغیر new_var ساخته می شود و در انتها تابع هم حذف می شود.
بیایید یک متغیر new_var هم با مقدار 20 در ابتدای برنامه ایجاد کنیم. یعنی کد به صورت زیر در آید:
my_var1 = 3 my_var2 = True new_var = 20 def func_1(x): new_var = 2 print(new_var) if x == 4: return new_var def otherFunc(): new_var = 5 print(new_var) otherFunc()
نتیجه اجرای کد بالا چیست ؟ ما تابع otherFunc را صدا زده ایم و در آن تابع مقدار new_var را چاپ کرده ایم. کدام مقدار به ما نشان داده می شود؟ نتیجه چه خواهد بود ؟ ( لطفا قبل از خواندن ادامه این مطلب خودتان یک بار این موضوع را تست کنید. )
نتیجه اجرای کد بالا عدد 5 است. متغیری که در تابع otherFunc صدا زده شده است ، مقدارش نمایش داده می شود. علت هم این است که در یک تابع متغیری که داخل خود تابع تعریف شده است ، اولویتش بالاتر از متغیری که در خارج از آن تعریف شده است. دقیقا مثل همان آقای محمدی ! اگر آقای محمدی و آقای مدیری همزمان به یک مغازه بروند و از مغازه دار نسیه بخواهند و مغازه دار بخواهد فقط به یک نفر از آنها نسیه بدهد ، احتمالا به آقای محمدی نسیه می دهد. علت هم این است که مغازه دار آقای محمدی را از نزدیک می شناسد و برای او اولویت بیشتری قایل است. در حالی که آقای مدیری را صرفا در تلویزیون دیده است.
بیایید کمی شیطنت کنیم و کد را به صورت زیر عوض کنیم :
my_var1 = 3 my_var2 = True new_var = 20 def func_1(x): new_var = 2 if x == 4: return new_var def otherFunc(): new_var = 5 func_1(3) print(new_var)
در کد بالا مقدار new_var در انتهای برنامه چاپ کرده ایم. قبل از آن هم تابع func_1 صدا زده شده است که مقدار new_var را برابر 2 قرار میدهد. اما نتیجه چیست ؟ مثل دفعات قبل ابتدا خودتان به این موضوع فکر کنید.
خروجی این برنامه برابر 20 است. علت هم این است که new_var موجود در تابع func_1 صرفا یک متغیر local است و پس از آن اجرای آن تابع دیگر وجود ندارد که بخواهیم مقدارش را نشان دهیم. به جای آن مقدار new_var که در ابتدای برنامه تعریف شده است ، نشان داده می شود. متغیر new_var ای که در ابتدای برنامه تعریف کرده ایم یک متغیر global می باشد. پس منطقی است که مقدار آن متغیر هم نشان داده شود.
اما اگر خواستیم مقدار new_var توسط آن تابع واقع تغییر داده شود باید چکار کنیم ؟ یعنی در مثال بالا میخواستیم new_var که در خروجی چاپ می شود همان 2 شود. در این حالت چه کاری میتوانیم انجام دهیم ؟
برای این کار کافی است متغیر new_var موجود در تابع را به حالت global در آوریم. یعنی به پایتون بگوییم که متغیر new_var یک متغیر global است و هر جا که مقدارش عوض شد ، مقدار new_var عوض خواهد شد. در واقع این با کمک کلمه کلیدی global دیگر میگوییم هر متغیری با همین نام در هر جای برنامه مقدارش عوض شد ، مقدار همان متغیر اصلی عوض می شود. در واقع دیگر یک new_var بیشتر وجود ندارد و آن هم همین است که در ابتدای برنامه تعریف شده است. بقیه new_var ها هم دقیقا همین متغیر هستند.
با کمک کلمه کلیدی global میتوانیم global بودن یک متغیر را به داخل توابع نیز ببریم. یعنی global بودن آن را گسترده تر کنیم.دیگر اگر داخل یک تابع ، یک متغیر تعریف کردیم و خواستیم مقدارش را نمایش دهیم ، اولویت بندی ای وجود ندارد که مثلا اولویت متغیر داخل تابع بالاتر است. متغیر داخل تابع دیگر همان متغیر خارج از تابع است و هیچ اولویتی ندارد.
اگر کد بالا به صورت زیر در آید :
my_var1 = 3 my_var2 = True new_var = 20 def func_1(x): global new_var new_var = 2 if x == 4: return new_var def otherFunc(): new_var = 5 func_1(3) print(new_var)
نتیجه خروجی برابر با 2 خواهد بود. چون در این کد در خط 6 متغیر new_var به global تبدیل شده است و متغیری که در خط 7 مقدارش تغییر کرده است ، همان متغیری است که در ابتدای برنامه تعریف شده است و فرقی ندارد.
قبل از پایان جلسه اجازه دهید این بحث را با یکدگیر کمی مرور کنیم تا از پیچیدگی آن کاسته شود :
1- اگر یک متغیر فقط در داخل یک تابع تعریف شده باشد ، فقط در همان تابع میتوانیم از آن استفاده کنیم.
2- اگر یک متغیر هم در داخل یک تابع تعریف شده باشد و هم در یک جای دیگر برنامه ، اگر بخواهیم از آن متغیر در داخل آن تابع استفاده کنیم ، متغیری که در داخل تابع است اولویت بیشتری دارد و تغییرات روی آن متغیر اعمال می شود. ولی اگر بخواهیم در خارج تابع از آن متغیر استفاده کنیم ، متغیری که در خارج از تابع تعریف شده است ، مقدارش دچار تغییر می شود.
3- با کلمه کلیدی global میتوانیم حوزه کاری یک متغیر را به صورت کامل گسترش دهیم و تمامی توابع و بخش های برنامه هم این متغیر را می شناسند و اگر مقدار این متغیر در یک تابع خاص تغییر کند ، مقدار متغیر اصلی تغییر می کند. در واقع دیگر دو متغیر نداریم و همه متغیرها ، یک متغیر هستند.
ما در این جلسه در مورد متغیرهای local و global با یکدیگر صحبت کردیم. برای درک بهتر این جلسه حتما تمرینات زیر را انجام دهید و نتیجه را در قسمت کامنت ها بیاورید تا تمرین شما تصحیح شود. بدون انجام این تمرینات خواندن این جلسه فایده ای ندارد:
سوال 1 :نتیجه اجرای کد زیر چه چیزی می باشد:
def f(): s = "Me too." print (s ) s = "I love python" f() print (s)
سوال 2: نتیجه اجرای کد بالا چه می باشد؟
def f(): print (s) s = "Me too." print (s) s = "I love python" f() print (s)
ارور ایجاد شده را توضیح دهید؟ آیا این خطا با خطای ایجاد شده در مرحله اول یکسان می باشد؟ تفاوت را توضیح دهید.
سوال 3 : خروجی کد زیر چه چیزی است ؟
a = 1 # Uses global because there is no local 'a' def f(): print ('Inside f() : ', a) # Variable 'a' is redefined as a local def g(): a = 2 print ('Inside g() : ',a) # Uses global keyword to modify global 'a' def h(): global a a = 3 print ('Inside h() : ',a ) # Global scope print ('global : ',a ) f() print ('global : ',a ) g() print ('global : ',a) h() print ('global : ',a )
مثل همیشه میتوانید ما را در تلگرام و یا اینستاگرام دنبال کنید :
دیدگاهتان را بنویسید