یکی دیگر از اصطلاحات برنامه نویسی immutability یا تغییرناپذیری است و ساده ترین مثال آن نیز رشته ها هستند. در زبان پایتون رشته ها immutable هستند که یعنی نمی توانیم آن ها را تغییر دهیم. منظور ما از تغییر، انتساب مجدد نیست چرا که انجام انتساب مجدد با رشته ها کاملا مجاز است:
my_string = "This is a great day!" my_string = "The second string" print(my_string)
کد بالا رشته The second string را چاپ می کند، بنابراین مطمئن می شویم در پایتون (فارغ از نوع داده) می توانیم انتساب مجدد داشته باشیم. مبحث immutability به تغییر همان رشته و دستکاری در آن اشاره دارد، نه جابجایی آن. به مثال زیر توجه کنید:
my_string = "This is a great day!" my_string[0] = "The" print(my_string)
همانطور که می دانید از علامت براکت برای دسترسی به ایندکس خاصی استفاده می شد بنابراین در دستور بالا گفته ایم اولین ایندکس رشته my_string (حرف T) با حروف The تعویض شود. تفاوت این عملیات با عملیات انتساب مجدد این است که در انتساب مجدد هیچ رشته ای را ویرایش نکردیم بلکه یک رشته را جایگزین رشته دیگری کردیم. این در حالی است که در عملیات بالا خود رشته را ویرایش کرده ایم. با اجرای کد بالا خطای زیر را می گیریم:
Traceback (most recent call last): File "main.py", line 3, in <module> my_string[0] = "The"TypeError: 'str' object does not support item assignment
معنای immutability یا تغییر ناپذیری همین است! با این حساب تنها حالتی که در آن می توان یک رشته را تغییر داد این است که آن را مجددا به یک مقدار ویرایش شده منتسب کنید. به طور مثال:
my_string = "This is a great day!" my_string = my_string + " second string" print(my_string)
شاید از نظر ما انسان ها کد بالا برای ویرایش رشته باشد اما از نظر کامپیوترها اینطور نیست. از نظر کامپیوترها کد بالا یک انتساب مجدد است چرا که یک فضای جدید را مموری اشغال می کند یا اینکه مقدار کاملا جدیدی را در آدرس فعلی مموری ذخیره می کند (در این مثال رشته جدیدی را در متغیر mystring ذخیره کرده ایم).
تا این قسمت از آموزش با چند تابع در زبان پایتون آشنا شده ایم. به طور مثال:
تعداد توابع پیش ساخته در زبان پایتون زیاد نیست، شما می توانید لیستی از این توابع را در این لینک مشاهده کنید. منظور ما از توابع «پیش ساخته» یا built-in توابعی هستند که به صورت پیش فرض در زبان پایتون وجود دارند و ما آن ها را اضافه نکرده ایم. پایتون برای رشته ها نیز تابع پیش ساخته ای دارد: len (مخفف length و به معنی طول) که طول یک رشته را مشخص می کند. به مثال زیر توجه کنید:
print(len('This is a random string!'))
نتیجه چاپ شده برای من عدد ۲۴ خواهد بود چرا که طول این رشته یا همان تعداد کاراکترهایش ۲۴ عدد است. نکته مهم اینجاست که تابع len شمارش را مانند انسان ها از یک شروع می کند چرا که به دنبال تعداد کاراکترهاست و مانند ایندکس ها به دنبال شماره گذاری نیست. فعلا در ابتدای این دوره هستیم و نمی توانم به صورت عملی به شما نشان بدهم که استفاده عملی از این تابع در چه محل هایی انجام می شود اما می توانم به شما نشان دهم که چطور این دستورات را با هم ترکیب کنید:
some_string = 'This is a random string!' print(some_string[0:len(some_string)])
ما در جلسه قبل در رابطه با این دستور خاص (علامت های [] در رشته ها) صحبت کرده بودیم اما حالا آن را با len ترکیب کرده ایم. این دستور می گوید از ایندکس صفر (اولین کاراکتر) تا آخرین کاراکتر رشته را چاپ کن بنابراین رشته !This is a random string برایمان چاپ خواهد شد.
زمانی که از توابع (function - تلفظ «فانکشِن) صحبت می کنیم یک کلمه را داریم که دارای پرانتز است (مثل ()print) و باید داده ورودی را درون این پرانتزها قرار بدهیم تا عملیاتی روی آن انجام شود. از طرف دیگر متد (method) ها را داریم که دقیقا مانند توابع هستند با این تفاوت که متعلق به چیز خاصی می باشند یا به زبان دیگر صاحب خاصی دارند (در مورد این موضوع در آینده صحبت خواهیم کرد). زبان پایتون متدهای متعددی را برای کار با رشته ها دارد که لیست آن را در این لینک مشاهده خواهید کرد. تفاوت دیگر متدها این است که متدها معمولا با علامت نقطه به داده اصلی متصل می شوند. بیایید چند نمونه از این متدها را با هم بررسی کنیم.
متد اول upper است که کاراکترهای یک رشته را با حروف بزرگ می نویسد:
quote = "to be or not to be" print(quote.upper())
همانطور که می بینید برای صدا زدن این متدها از علامت نقطه استفاده می کنیم تا آن ها را به داده ای خاص متصل کنیم. نتیجه اجرای کد بالا رشته TO BE OR NOT TO BE است که تماما با حروف بزرگ نوشته شده است. احتمالا می پرسید مگر نگفته بودیم که رشته ها immutable هستند؟ آیا کاری که الان انجام دادیم تغییر رشته نبود؟ خیر! بگذارید به شما ثابت کنم:
quote = "to be or not to be" print(quote.upper())print(quote)
با اجرای کد بالا نتیجه زیر را می گیریم:
TO BE OR NOT TO BE to be or not to be
در کد بالا می بینید که پس از صدا زدن متد upper باز هم رشته quote به همان شکل اصلی خود باقی مانده است. به عبارتی تمام متدهای کار با رشته ها یک رشته جدید را برمی گردانند و با رشته اصلی هیچ کاری ندارند. متد دیگر به نام capitalize نیز وجود دارد که فقط حرف اول رشته را با حروف بزرگ می نویسد و با بقیه حروف کاری ندارد:
quote = "to be or not to be" print(quote.capitalize())
نتیجه اجرای این کد رشته زیر خواهد بود:
To be or not to be
همانطور که می بینید حرف t تبدیل به T شده است. متد بعدی ما find است که یک کلمه یا چند کاراکتر را در یک رشته جست و جو می کند:
quote = "to be or not to be" print(quote.find("be"))
ما در این کد گفته ایم در رشته quote به دنبال کلمه be بگرد و با اجرای آن نیز عدد ۳ را دریافت می کنیم. عدد ۳ در واقع ایندکس کلمه پیدا شده در رشته اصلی است. در صورتی که رشته ما پیدا نشود عدد ۱- برگردانده خواهد شد. متد بعدی ما replace است که یک مقدار را در یک رشته پیدا کرده و به جای آن مقدار دیگری را در رشته اصلی قرار می دهد:
quote = "to be or not to be" print(quote.replace("be", "think"))
مقدار اولی که به replace داده ایم، مقداری است که باید تغییر کند و مقدار دوم نیز مقدار جدیدی است که باید جایگزین اولی شود. با اجرای کد بالا نتیجه زیر را می گیریم:
to think or not to think
به عبارتی be با think جایگزین شده است. همانطور که گفتم تعداد متدهای کار با رشته ها زیاد است و نباید سعی در حفظ کردن آن ها داشته باشید بلکه به مرور زمان و با کدنویسی با آن آشنا می شوید.
boolean (تلفظ: بولیِن) ها نوع دیگری از data type های ما هستند و خوشبختانه یکی از ساده ترین data type ها نیز می باشند. در زبان پایتون boolean ها به صورت bool نوشته می شوند و فقط شامل دو مقدار True (صحیح) و False (غلط) می شوند. در واقع بولین ها برای حالات دوگانه ای استفاده می شوند که فقط در آن ها یک مقدار داریم: صحیح یا غلط. مثال:
user_name = "Amir" isOld = False isYoung = True
در اینجا isOld (به معنی «آیا پیر است؟») روی False و isYoung (آیا جوان است؟) روی True تنظیم شده اند. True و False باید با حروف بزرگ شروع شوند و از واژه های پیش ساخته در زبان پایتون هستند. بولین ها به همین سادگی هستند و هیچ پیچیدگی خاصی ندارند.
مبحث بعدی رابطه بین مقادیر مختلف با بولین است. همانطور که توابعی مانند ()str یا ()int را برای تبدیل مقادیر به رشته و عدد صحیح داشتیم، تابعی به نام ()bool را نیز داریم که مقادیر را به boolean تبدیل می کند اما من توضیح دادم که بولین مقدار جدیدی نمی گیرد بلکه فقط True یا False خواهد بود. با این حساب به نظر شما نتیجه کد زیر چیست؟
print(bool(1))
من در اینجا عدد ۱ را به ()bool داده ام تا آن را به boolean تبدیل کند. به نظر شما نتیجه چاپ شده برای ما چه خواهد بود؟ پاسخ True است. اعداد ۲ و ۳ و ۴ و ۵ چطور؟ همه آن ها نیز True هستند! عدد صفر چطور؟ عدد صفر در قالب boolean غلط یا False است! احتمالا می گویید چطور باید این مسئله را یاد بگیریم؟ آیا باید حالت بولین را برای تمامی این مقادیر حفظ کنیم؟ خیر! مقادیر محدودی در پایتون و دیگر زبان های برنامه نویسی وجود دارند که از نظر بولین غلط یا False هستند اما بقیه مقادیر True می باشند بنابراین ما فقط باید مقادیر False را یاد بگیریم و در این صورت بقیه True خواهند بود. مقادیر زیر در زبان پایتون False محسوب می شوند. برخی از موارد زیر (مانند نوع داده List یا Tuple) را هنوز یاد نگرفته ایم اما مشکلی نیست، هدف ما فقط ارائه یک لیست از مقادیر False می باشد و بعدا در طول دوره با تمام آن ها آشنا می شوید:
غیر از مواردی که در لیست بالا می بینید بقیه موارد در منطق کامپیوتری برابر True یا صحیح هستند.
بر اساس مواردی که تا این قسمت یاد گرفته ایم از شما می خواهم کدی بنویسید که سال تولید کاربر را دریافت کند و سپس به او بگوید چند سالش است. اگر جلسات را به خوبی مطالعه کرده باشید می توانید بدون زحمت به این سوال پاسخ بدهید. سعی کنید خودتان این سوال را حل کرده و سپس به پاسخ من نگاه کنید.
پاسخ سوال بسیار ساده و به شکل زیر است:
birthdate = input('When were you born?') user_age = 2020 - int(birthdate) print(f"You are {user_age} years old!")
با اجرای این کد از شما پرسیده می شود when were you born (در چه سالی متولد شده اید؟) مقداری که شما به عنوان سال تولد خود وارد می کنید درون متغیری به نام birthdate ذخیره می شود. در مرحله بعدی برای به دست آوردن سن فرد ۲۰۲۰ (زمان حال) را از سال تولد کاربر کم کرده و نتیجه را درون user_age قرار می دهیم. توجه داشته باشید هر مقداری که توسط input دریافت شود، رشته خواهد بود، بنابراین سال تولد شما در برنامه ما ۱۹۹۰ نیست بلکه "۱۹۹۰" است. به همین دلیل باید ()int را صدا بزنیم تا رشته "۱۹۹۰" را به عدد ۱۹۹۰ تبدیل کنیم تا قابلیت تفریق داشته باشد. در مرحله بعدی با استفاده از formatted strings سن کاربر را نمایش داده ایم.
همانطور که در جلسات قبل توضیح دادم بخش «مهارت یادگیری» شامل نکته هایی خارج از درس یا اضافه بر درس برای افرادی است که می خواهند کدنویسی را به شکل بهتر و اصولی تر یاد بگیرند. این قسمت شامل خطاهای رایج و توصیه های کاربردی است و در قسمت های مختلف ظاهر خواهد شد. موضوع بحث این قسمت «کامنت گذاری برای کدها» است. در زبان پایتون مانند دیگر زبان های برنامه نویسی قابلیت نوشتن کامنت وجود دارد. یعنی چه؟ کامنت ها خطوطی در کدهای ما هستند که توسط مفسر یا کامپایلر نادیده گرفته می شوند و فقط برای خودمان یا دیگر اعضای تیم نوشته شده اند. در واقع کامنت ها سه کاربرد اصلی دارند:
در زبان پایتون برای اضافه کردن یک کامنت یا کامنت کردن خطی خاص از علامت # استفاده می شود. به مثال زیر توجه کنید:
# دریافت سال تولد کاربر birthdate = input('When were you born?') # محاسبه سن کاربر user_age = 2020 - int(birthdate) # نمایش سن کاربر print(f"You are {user_age} years old!")
این کد هنوز هم مثل قبل کار می کند. خطوطی که با # شروع شوند کامنت خواهند بود، بنابراین اصلا اجرا نشده و نادیده گرفته می شوند. البته شما می توانید کامنت را در کنار کد نیز بگذارید:
print(f"You are {user_age} years old!") # نمایش سن کاربر
این کد نیز به درستی اجرا می شود چرا که شروع کامنت از علامت # است، بنابراین قبل از آن همه چیز در حالت عادی اجرا می شود.
در مبحث کامنت گذاری باید سه کاربرد اصلی کامنت ها را در گوشه ذهن خود داشته باشید و بر اساس آن ها کار کنید. به طور مثال به کد زیر نگاه کنید:
# name انتساب رشته امیر به متغیرname = "Amir"
این کامنت یک کامنت بد است، آیا می دانید چرا؟ به دلیل اینکه کد شما باید تمیز و خوانا باشد و برای موارد بدیهی بدین شکل به کامنت نیازی نداشته باشد. کد بالا نیز همینطور است؛ یعنی هر کسی که به این کد نگاه کند متوجه خواهد شد که Amir را به name پاس داده ایم بنابراین اصلا نیازی به این کامنت اضافه و وقت گیر نیست. مثالی که بالاتر از نمایش سن کاربر داشتیم فقط جهت یادگیری بود و کامنت های آن اصلا خوب نبود. شما تنها زمانی به کدهایتان کامنت اضافه می کنید که آن قسمت از کدها پیچیده باشند یا اینکه نکته مهمی در آن ها وجود داشته باشد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.