در این آموزش میخواهیم به توضیح مفهوم Variable (متغیر) بپردازیم. در توسعهٔ اکثر اپلیکیشنها ما نیاز داریم تا دادههای مختلفی را ذخیره سازیم تا بعداً بتوانیم به آنها دسترسی داشته باشیم که برای این کار مفسر پایتون از حافظهٔ کامپیوتری که برنامه روی آن اجرا میشود استفاده میکند بدین صورت که برای ذخیرهٔ هر آبجکت دلخواه مثل یک عدد صحیح یا استرینگ مکانی از حافظهٔ کامپیوتر را به آن اختصاص میدهد که این مکان آدرس منحصربهفردی همچون 0000 0111 1101 دارا است.
در واقع، اگر بخواهیم مجدداً از آن آبجکت (عدد صحیح یا استرینگ) در برنامهٔ خود استفاده کنیم، لازم است که دقیقاً آدرس جایی از حافظهٔ کامپیوتر که آن آبجکت در آنجا ذخیره شده را بدانیم و آن را در اختیار مفسر پایتون بگذاریم تا بتواند به آن مکان مراجعه کرده و اطلاعات آبجکت را به دست آورد اما در عین حال توجه داشته باشیم که به خاطر سپردن یا حتی تهیهٔ لیستی از تمام این آدرسها و استفاده از آنها کاری بسیار سخت است که فرآیند کدنویسی را به شدت کُند کرده و امکان اشتباه را به مراتب زیاد میکند!
نیاز به توضیح نیست که هدف اصلی از طراحی زبانهای برنامهنویسی سطحِ بالا ساده کردن کار برنامهنویسان برای تعامل با کامپیوترها است و به همین دلیل زبانهای برنامهنویسی با استفاده از متغیرها به کمک برنامهنویسان میآیند و کار ذخیرهٔ آبجکتها در حافظه و استفادهٔ مجدد از آنها را تا حد زیادی راحتتر میکنند که در زبان برنامهنویسی پایتون هم از مفهوم متغیر (البته با تعریفی خاص نسبت به سایر زبانهای برنامهنویسی) استفاده میشود که در ادامهٔ این آموزش بیشتر با ویژگی متغیرها در این زبان آشنا خواهیم شد.
در زبان برنامهنویسی پایتون یک متغیر را میتوان مانند یک برچسب در نظر گرفت که کافی است روی آن یک نام دلخواه بنویسیم و به نحوی آن را به هر آبجکت یا بهتر بگوییم نمونهای از یک کلاس بچسبانیم که بدین ترتیب در هر قسمت از برنامه میتوانیم نام آن آبجکت را صدا بزنیم تا مفسر پایتون در حافظهٔ کامپیوتر محل آبجکتی که برچسبی با نام مورد نظرمان به آن خورده است را پیدا کرده و محتویات آن را در اختیار ما قرار دهد.
برای درک بهتر این موضوع، در ادامه خواهیم دید که چهطور میتوانیم یک متغیر را در زبان برنامهنویسی پایتون تعریف کرد. برای این منظور، وارد پنجرهٔ شِل در نرمافزار IDLE شده و دستورهای زیر را در آن تایپ میکنیم:
>>> Name = "SokanAcademy.com"
>>> Age = 2
در حقیقت، با وارد کردن این دستورات، دو متغیر را با نامهای Name
و Age
ایجاد کردهایم به طوری که متغیر Name
به صورت برچسبی به یک آبجکت از جنس استرینگ با مقدار «SokanAcademy.com» الصاق شده و متغیر Age
به یک دادهٔ عددی با مقدار 2 منتسب شده است (البته در ادامه خواهیم دید که برای نامگذاری بهتر است از حروف کوچک استفاده کرد.) اکنون نام این متغیرها را در محیط شِل صدا میزنیم تا ببینیم مفسر چه اطلاعاتی را در اختیارمان خواهد گذاشت:
>>> Name
'SokanAcademy.com'
>>> Age
2
همانطور که میبینید، در پنجرهٔ شِل وقتی متغیر Name
را وارد کنیم، مفسر همان آبجکت استرینگی حاوی 'SokanAcademy.com'
که به آن منتسب کرده بودیم را در خروجی نمایش میدهد و با وارد کردن متغیر Age
نیز مقدار عدد اختصاصیافته را در پنجره چاپ میکند.
در دستورات بالا اولین چیزی که مشخص کردیم نام متغیر بود که این نام یک اصطلاحاً Identifier (شناسه) است. در حقیقت، شناسه نمادی است که از آن برای شناسایی متغیرها، متدها، کلاسها و سایر اجزای برنامه که نیاز به نامگذاری دارند استفاده میشود که به صورت دلخواه تعیین میشوند به طوری که شما هر نام دلخواهی را میتوانید به یک متغیر بدهید. با وجود این، در زبان برنامهنویسی پایتون قواعدی برای انتخاب شناسهها وجود دارد بدین شکل که اولین کاراکتر هر شناسه تنها یکی از حروف بزرگ یا کوچک الفبا و آندِراِسکور (_) است و اگر بخواهیم شناسهای با بیش از یک کاراکتر انتخاب کنیم، میتوانیم هر ترکیب دلخواه از حروف بزرگ و کوچک الفبا، کاراکتر _ و ارقام 0 تا 9 را در ادامه بیاوریم.
هشدار |
توجه داشته باشیم که استفاده از فاصله (اِسپیس) در انتخاب نام شناسه مجاز نیست و استفاده از کاراکترهایی مانند .، @، $، #، %، !، ? و دیگر علائمی از این دست در شناسهها مجاز نمیباشد مضاف بر اینکه شناسهها نباید از میان کیوردهای پیشفرض پایتون انتخاب شوند (کیورد یا کلمهٔ کلیدی شناسههایی هستند که طراحان زبان پایتون آنها را به صورت پیشفرض برای مفسر این زبان تعریف کردهاند و استفاده از آنها در زمان کدنویسی معنای خاصی را به مفسر میرساند و ما اجازه نداریم به جز مصارف خاصی که برای آنها در نظر گرفته شده است، برای کاربرد دیگری از آنها استفاده نماییم.). |
با استفاده از دستور ()help
به فهرستی از کلمات کلیدی در هر نسخهای از پایتون دست پیدا کنیم:
>>> help("keywords")
Here is a list of the Python keywords. Enter any keyword to get more help.
False def if raise
None del import return
True elif in try
and else is while
as except lambda with
assert finally nonlocal yield
break for not
class from or
continue global pass
برای نمونه، شناسههای زیر از جمله شناسههای معتبر در زبان پایتون هستند:
I
number2
object_name
MyVar
__var1
_n
setColor
PS2
همچنین استفاده از مثالهای زیر به عنوان شناسه در کدهای نوشتهشده به زبان پایتون مجاز نیست:
Object.color
1name
8
m@mail
True
$sign
2c#
در زبان برنامهنویسی پایتون، استانداردی برای نامگذاری متغیرها وجود دارد که بر اساس این استاندارد نام (شناسه) مناسب برای متغیرها تنها از کاراکترهایی با حروف کوچک انگلیسی تشکیل میشود که در صورت انتخاب نامی چندبخشی، کاراکترهای آن با علامت _
از هم جدا میشوند و بر اساس این استاندارد، شناسههایی مانند name
یا object_name
شناسههای قابلقبول برای نامگذاری متغیرها هستند (هیچ اجباری برای رعایت این استانداردها وجود ندارد اما لازم به یادآوری است که پیروی از این اصول باعث میشود خوانایی برنامههایی که مینویسیم بیشتر شود.)
با وجود آنکه طول یک شناسه میتواند هر مقدار دلخواهی باشد، بهتر است از شناسههایی که حاوی تعداد زیادی کاراکتر است استفاده نکنیم به علاوه اینکه سعی کنیم شناسهای انتخاب کنیم که بامعنا باشد و متناسب با مقداری باشد که آن را نشان میدهد (مثلاً اگر بخواهیم متغیری را به دادهای که رنگ یک آبجکت را نشان میدهد منتسب کنیم، بهتر است از شناسهای تحت عنوان color
استفاده کنیم به طوری که توجه به این نکات، کار بررسی و اصلاح کدها را در آینده راحتتر خواهد کرد.)
نکته |
زبان برنامهنویسی پایتون نسبت به حالت حروف حساس است و بین حروف کوچک و بزرگ تمایز قائل است. به عبارت دیگر، این زبان اصطلاحاً Case Sensitive است و از همین روی هر یک از شناسههای NUM ،num ،Num ،nUm ،nuM ،NUm ،NuM و nUM یک شناسهٔ متمایز برای مفسر این زبان هستند. |
در تعریف یک متغیر برای مفسر، پس از انتخاب نام مناسب از Operator (عملگر) انتساب استفاده میکنیم که با نماد =
مشخص میشود. عملگرها نمادهایی هستند که عمل خاصی را روی عناصر برنامه که به آنها Operand (عَملوَند) میگوییم انجام میدهند. در حالت معمول =
دو عملوند میگیرد یکی در سمت چپ خود و دیگری در سمت راست به گونهای که عملوند سمت راست را به عملوند سمت چپ منتسب میکند.
گفتیم که در یک دستور انتسابی، عملوند سمت چپ نام یک متغیر است و با توجه به مثالهای ابتدایی، عملوندی هم که در سمت راست قرار میگیرد یک آبجکت دلخواه از هر نوعی متناسب با نیاز برنامه است که وقتی به این طریق یک دستور انتسابی را مینویسیم و برنامه را اجرا میکنیم، مفسر با رسیدن به دستوری اینچنین، ابتدا آبجکتی را که در سمت راست =
قرار دارد ایجاد میکند و آن را در محلی از حافظهٔ کامپیوتر ذخیره میکند. آنگاه در صورتی که متغیری با نامی که در سمت چپ =
قرار دارد در حافظه وجود نداشته باشد، آن را در محل دیگری از حافظه ایجاد و ذخیره میکند و در مرحلهٔ آخر متغیر را به صورت برچسبی به آبجکت تعریفشده میچسباند یا اصطلاحاً به آن Reference (ارجاع) میدهد.
چند نکته در مورد متغیرها که باید مورد توجه قرار دهیم
همانطور که دیدیم، بر خلاف بسیاری از زبانهای برنامهنویسی مثل جاوا، در پایتون در زمان تعریف متغیر نیازی نیست از قبل به مفسر اعلام کنیم که میخواهیم چه نوع آبجکتی را به آن منتسب کنیم. در واقع، محتوای آبجکت منتسبشده به هر متغیر نوع آن را تعیین خواهد کرد و از همین روی باید دقت کنیم که در زمان انتساب آبجکتها به متغیرها دچار اشتباه نشویم چون مفسر در مورد اینکه شما میخواهید از چه نوع آبجکتی در برنامهٔ خود استفاده کنید اطلاعی ندارد که بخواهد درست بودن این انتساب را بررسی کرده و خطای احتمالی را گزارش دهد. همچنین پس از آنکه برای اولین بار یک متغیر را تعریف کردیم، خواهیم توانست آبجکتی که به آن اشاره میکند را تغییر دهیم:
>>> i = 10
>>> i
10
>>> i = 20
>>> i
20
>>> i = "number"
>>> i
'number'
در دستور اول متغیر i
را برای اولین بار تعریف میکنیم و عدد صحیح 10 را به آن منتسب میکنیم و همانطور که میبینید، با فراخوانی متغیر i
مقدار عددی 10 نشان داده میشود. در دستور بعد، عدد صحیح 20 را به متغیر i
منتسب کردهایم و این کار مثل آن است که برچسب قرار گرفته روی عدد صحیح 10 را بر داریم و آن را روی عدد صحیح 20 بچسبانیم که از این پس با فراخوانی متغیر i
مقدار عدد صحیح 20 نمایش داده میشود. دستور بعدی دادهای را از نوع استرینگ به متغیر i
منتسب میکند و همانطور که میبینید، متغیر i
به قدری انعطافپذیر است که نه تنها مقدار آبجکتی که میتواند به آن منتسب شود قابلتغییر است، بلکه نوع آبجکت نیز قابلتغییر میباشد.
علاوه بر مد نظر قرار دادن نکات فوق، فرض کنید بخواهیم متغیری را تعریف کنیم که فعلاً به آبجکت خاصی ارجاع نداشته باشد که در این صورت در سمت راست عملگر =
به جای تعریف یک آبجکت جدید، از کلمهٔ کلیدی None
استفاده میکنیم:
>>> i = None
>>> i
>>>
میبینیم که با فراخوانی متغیر i
مفسر هیچ مقداری را نمایش نمیدهد و تنها کاری که کرده این است که نام متغیر را در حافظهٔ کامپیوتر ذخیره میکند تا بعداً از آن برای ارجاع به یک آبجکت استفاده کنیم (توجه داشته باشید که None
یک کلیدواژهٔ پیشفرض در زبان پایتون است و هرگز نباید به جای آن از none
استفاده کنید.)
در زبان برنامهنویسی پایتون این امکان وجود دارد که در یک دستور انتسابی چند متغیر را به صورت همزمان به تعدادی آبجکت منتسب کرد که برای درک بهتر این موضوع، دستورات زیر را در نظر میگیریم:
>>> first_name, last_name, age = "Narges", "Asadi", 25
>>> first_name
'Narges'
>>> last_name
'Asadi'
>>> age
25
در دستور اول، برای انتساب آبجکتهای مختلف به متغیرها از یک عملگر =
و ,
استفاده کردهایم و سپس با فراخوانی متغیرها، ترتیب انتسابها را در خروجی میبینیم که چهطور اولین متغیر از سمت چپ تساوی یعنی first_name
به اولین آبجکت از سمت راست که استرینگی با مقدار «Narges» است ارجاع داده میشود و به همین ترتیب پیش میرود. نکتهٔ مهم اینجا است که حتماً باید تعداد متغیرهای سمت چپ با تعداد آبجکتهای سمت راست برابر باشد که در غیر این صورت با خطا مواجه خواهیم شد. برای نمونه، خروجی قطعه کدهای زیر را ببینید:
>>> first_name , last_name , age = "Narges" , "Asadi"
Traceback (most recent call last):
File "<pyshell#0>", line 1, in
first_name , last_name , age = "Narges" , "Asadi"
ValueError: not enough values to unpack (expected 3, got 2)
>>> first_name
Traceback (most recent call last):
File "<pyshell#1>", line 1, in
first_name
NameError: name 'first_name' is not defined
همانطور که مشخص است، از آنجا که متغیرها سه عدد هستند اما در سمت راست =
دو آبجکت وجود دارد، مفسر پایتون با رسیدن به این دستور انتسابی اعلام خطا میکند و هیچیک از متغیرها را به آبجکتهای سمت راست ارجاع نمیدهد به طوری که با فراخوانی متغیر اول که first_name
است، اعلام میکند که این نام تعریف نشده است.
همچنین این قابلیت در پایتون وجود دارد که در قالب یک دستور انتسابی، یک آبجکت را به چندین متغیر منتسب کنیم. برای مثال، دستورات زیر را در IDLE وارد کنید:
>>> i = j = k = 5
>>> i
5
>>> j
5
>>> k
5
همانطور که میبینید، هر سه متغیر موجود به یک آبجکت از نوع عدد صحیح با مقدار 5 ارجاع میدهند. حال ممکن است این سؤال پیش آید مبنی بر اینکه «اگر مقدار یکی از این متغیرها تغییر کند، آیا مقدار متغیرهای دیگر نیز تغییر میکند؟» که در پاسخ به این پرسش، کدهای زیر را مد نظر قرار میدهیم:
>>> i = 10
>>> i
10
>>> j
5
>>> k
5
همانطور که ملاحظه میشود، اگرچه مقدار متغیر i
تغییر کرده است، در عین حال متغیرهای j
و k
مانند قبل باقی میمانند و دلیل این موضوع به تعریف مفهوم متغیر در زبان پایتون مربوط میشود.
در واقع، در بیشتر زبانهای برنامهنویسی، متغیر مانند یک جعبه است که مقداری در آن ذخیره میشود و از همین روی اگر دو متغیر به یک آبجکت منتسب شوند، در واقع محتوای یک جعبه را نشان میدهند و بنابراین با تغییر آن آبجکت، هر دو متغیر همزمان عوض میشوند اما همانطور که گفتیم، در پایتون متغیرها مانند برچسب یا اتیکت عمل میکنند. به عبارتی، وقتی دو متغیر به طور همزمان به یک آبجکت ارجاع داده میشوند، مثل این است که هر دو را روی آن آبجکت چسباندهایم و اگر آبجکت دیگری را به یکی از متغیرها منتسب کنیم، مثل آن است که یکی از برچسبها را از آبجکت اول جدا کردهایم و به آبجکتی جدید چسباندهایم در حالی که برچسب اول در جای قبلی خود باقی مانده است!
همچنین در حین تعریف یک متغیر، عملوند سمت راست عملگر =
میتواند یک متغیر دیگر باشد که به منظور درک این نکته، دستورات زیر را در نظر میگیریم:
>>> i = 5
>>> j = i
>>> j
5
>>> i = 9
>>> j
5
همانطور که میبینید، ابتدا متغیر j
را با استفاده از متغیر i
تعریف کردیم که بر اساس توضیحات قبل، با تغییر ارجاع i
به آبجکت جدیدی با مقدار 9، متغیر j
همچنان به همان آبجکت قبلی حاوی دادهٔ عددی 5 ارجاع میدهد.