کلاس در پایتون
شی گرایی یا Object Oriented Programming (OOP) به وسیله کلاس ها در پایتون میسر میشود. آنها ما را از شرِّ نوشتن کدهای تکراری راحت میکنند و باعث میشوند که کدهای تمیزتری داشته باشیم. علاوه بر این، درک این مبحث میتواند به درک بیشتر توابع و دیتاتایپهای built-in در پایتون و … کمک قابل توجهی کند. در این پست مفهوم کلاس و نحوه تعریف کلاس در پایتون را آموزش خواهم داد. با من همراه باشید…
مقدمهای بر کلاس در پایتون
بارها شنیدهایم که پایتون یک زبان برنامهنویسی شیءگرا است. زبان برنامهنویسی شیءگرا یا Object Oriented Programming language یک پارادایم یا استایل برنامهنویسی مبتنی بر object است. در پایتون همه چیز یک آبجکت است. اعداد، رشتهها، لیست و حتی توابع، یک آبجکت هستند. حالا شما میتوانید با استفاده از کلاس، یک آبجکت جدید، همانند این آبجکتهای پیشفرض بسازید!
کلاسها در پایتون بسیار شبیه BluePrint هستند. این جمله را در بسیاری از مراجع و وبلاگها میتوان دید. اما شاید برای شما سوال باشد که BluePrint چه هست؟
کلاس در پایتون مثل BluePrint
در گذشتههای دور که دستگاه فتوکپی وجود نداشت، از BluePrint برای تکثیر استفاده میشد. این روش در سال 1842 توسط John Herschel ابداع شد و بیشتر برای تکثیر نقشههای ساختمانی استفاده میشد. روش کار هم بسیار ساده بود.
ابتدا یک فرد متخصص، نقشه را روی کاغذ پوستی میکشید. سپس یک کاغذ را به یک ماده شیمیایی آغشته میکردند و میگذاشتند خشک شود. سپس کاغذ پوستی را روی کاغذ آغشته به مواد شیمیایی فیکس کرده و در معرض نور خورشید میگذاشتند. مواد شیمیایی در معرض مجاورت با اشعه UV رنگ آبی به خود میگرفتند. طبیعتا چون نور خورشید از خطوط کشیده شده روی کاغذ پوستی عبور نمیکند، رد خطها روی کاغذ میماند و به این صورت کپی انجام میشد! با استفاده از BluePrint امکان این وجود داشت که تعداد نامحدودی کپی از یک نقشه ایجاد شود.
وجه شباهت BluePrint و کلاس زیاد است. متخصصی که شما باشید، باید یک کلاس بنویسید که در واقع همان نقشهای است که روی کاغذ پوستی کشیده میشود. سپس از روی این کلاس میتوانید آبجکتهای مختلف بسازید. اما دیگر نمیخواهد که کامپیوترتان را به ماده شیمیایی خاصی آغشته کنید 🤪 و فقط کافی است که آن کلاس را فراخوانی یا Call کنید!
تعریف کلاس در پایتون
تعریف کلاس در نگاه اول ممکن است کمی برای مخاطب غریبه و سخت به نظر بیاید. به همین دلیل بهتر است قدم به قدم جلو برویم و کمکم با بخشهای مختلف آن آشنا شویم.
در اولین قدم میخواهم سینتکس کلاس را معرفی کنم. برای تعریف کلاس باید از کلیدواژه class در پایتون استفاده کنیم. سپس نام کلاس را مینویسیم و بعد از آن هم علامت کولن یا دونقطه (:) میگذاریم. به این شکل:
کدهایی که در بخش statements نوشته میشوند، خودشان داستان دارند که در بخشهای بعدی آنها را معرفی خواهم کرد. بیایید ابتدا کمی در مورد اسم کلاس (class_name) صحبت کنیم.
اسم کلاس در پایتون
اولین نکته در نامگذاری کلاسها این است که از اسم یا عباراتی بهتر است استفاده کنیم که توصیف کننده عملکرد آن کلاس باشد. نام کلاسها در پایتون محدودیت خاصی ندارند اما یک قرارداد برای نامگذاری کلاسها وجود دارد. بسیاری از برنامهنویسان پایتون، نام کلاسها را به صورت snake_case انتخاب میکنند. در snake_case کلمات با آندرلاین از هم جدا میشوند، مثل age_estimation یا area_circle.
این روش هم درست است اما توصیه میشود نام کلاسها را به صورت PascalCase بنویسیم، مثل AgeEstimation یا AreaCircle. در PascalCase حرف اول همه کلمات باید بزرگ باشند. دقت کنید شما اگر به هر شکل دیگری کلاس را نامگذاری کنید، به خطا نمیخورید. اما رعایت این قراردادها باعث میشود کدهای شما یکدست، تمیز و حرفهای به نظر برسد.
نحوه تعریف کلاس در پایتون
سناریوی من برای معرفی کلاس به شما این است: میخواهم یک کلاس بسازم که یک اسم را دریافت کرده و به او سلام کند! کمکم در بخشهای آینده این کلاس را با هم میسازیم و همزمان با بخشهای مختلف کلاس در پایتون هم آشنا میشویم.
در این بخش میخواهیم با استفاده از ساختار کلاس در پایتون که در بخش قبل معرفی کردیم، کلاسی که در موردش صحبت کردم را بسازیم. اول از همه باید یک اسم برای کلاس انتخاب کنیم و ترجیحا به شکل PascalCase بنویسیم درست است؟ من اسم SayHello را انتخاب کردم. بنابراین کلاس من به شکل زیر خواهد شد:
class SayHello: pass
Attribute و Method در کلاس
یکی از ویژگیهایی که برای کلاسها مطرح میکنند توانایی encapsulate کردن data و behavior است! اما این جمله یعنی چه؟ encapsulate یعنی کپسوله کردن، تجمیع کردن. منظور این جمله این است که یک کلاس در پایتون، متغیرها (data) و توابع (behavior) را میتواند در کنار هم داشته باشد. چیجورییی؟ خیلی ساده. در دو بخش بعدی توضیح خواهم داد.
Attribute در کلاس
Attribute-ها در کلاس در واقع همان متغیرها هستند که در خود یکسری داده ذخیره میکنند. این متغیرها بلافاصله بعد از تعریف کلاس تعریف میشوند. مثلا در کلاس SayHello که قبلا با هم صحبت کردیم، نام، یک داده است که به شکل زیر تعریف میشود:
class SayHello: name = 'name'
در مراجع مختلف ممکن است Attribute-ها را با عنوان property یا characteristic هم معرفی کنند. در این بخش ما توانستیم یک کلاس بسازیم و یک اتریبیوت با نام name به آن اضافه کنیم. در بخش بعدی میخواهیم چند آبجکت از روی این کلاس بسازیم! مگر نگفتیم که کلاس یک BluePrint است؟ برویم ببینیم چند مرده حلاج است!
ساختن آبجکت از روی کلاس
در این بخش میخواهیم چند آبجکت از روی کلاس بسازیم. به این کار instantiation هم گفته میشود. برای این کار کافی است کلاس را فراخوانی کرده و در یک متغیر ذخیره کنیم. مثلا آبجکت اول را در person1 میخواهیم ذخیره کنیم:
person1 = SayHello()
برای دسترسی به اتریبیوتها (و متدها که در بخش بعدی با آنها آشنا خواهیم شد)، کافی است جلوی آبجکتی که ساختیم (اینجا person1) یک دات یا نقطه بگذاریم و عنوان آن اتریبیوت را بنویسیم. مثلا برای دسترسی به name کافی است بنویسیم:
person1.name
'name'
مشاهده میکنید که عبارت ‘name’ را نشان میدهد. دقیقا همان چیزی که در هنگام تعریف کلاس در اتریبیوت name ریخته بودیم. خب این که نشد. هدف ما این بود که بتوانیم نامهای مختلفی تعریف کنیم. راه حل چیست؟
این امکان وجود دارد که از بیرون کلاس، اتریبیوتها را مقداردهی کنیم. مثلا فرض کنید بخواهیم name را howsam بگذاریم. برای این کار باید بنویسیم:
person1.name = 'howsam'
مجدد اتریبیوت name را پرینت میکنیم:
person1.name
'howsam'
مشاهده میکنید که مقدار آن تغییر کرده. حالا میخواهیم یک آبجکت دیگر برای یک فرد جدید بسازیم که اسمش Flower است. برای این کار بنویسید:
person2 = SayHello() person2.name = 'Flower'
یک بار دیگر کلاس SayHello را فراخوانی کردیم و در متغیر person2 ذخیره کردیم. در واقع ما دو instance از کلاس SayHello ساختیم که در یکی، اتریبیوت name برابر با ‘howsam’ و در دیگری برابر با ‘Flower’ است:
person1.name
'howsam'
person2.name
'Flower'
به همین ترتیب شما میتوانید هر تعداد آبجکت که دلتان بخواهد بسازید.
متد (method) در کلاس
گفتیم که کلاسها در پایتون میتوانند data و behavior را تجمیع کنند. دیدیم که data در اتریبیوتها ذخیره میشوند. حالا نوبت behavior است. منظور از behavior کارهایی است که کلاس میتواند انجام دهد. شما با تعریف تابع در بدنه کلاس، میتوانید یکسری عملکرد یا behavior به کلاس اضافه کنید. به توابعی که در بدنه کلاس تعریف میشوند، متد گفته میشود.
بیایید کلاس SayHello را تکمیل کنیم. هدف این است که یک متد برای سلام گفتن بنویسیم! یعنی تابعی که یک پرینت معمولی انجام بدهد. خب بسمالله:
class SayHello: name = 'name' def greet(self): print('hello ' + self.name + '!')
احتمالا الان این شکلی شدید 🤔. کلیدواژه self جدید است. self در واقع نمایندهای از آبجکت است. شما با self به آبجکت متصل میشوید تا بتوانید به دادههای مرتبط با همان آبجکت دسترسی داشته باشید. در دنیای بیرون کلاس، شما اسم آبجکت را مینویسید و با دات به اتریبیوتها و متدهای آن دسترسی دارید. در داخل کلاس اما اسم آبجکت self است!
در متد greet برای دسترسی به name نوشتیم self.name چرا؟ چون در داخل تابع greet، ما name را نداریم. name یک اتریبیوت است. به همین دلیل است که نوشتیم self.name چون self نماینده آبجکت است و آبجکت یک اتریبیوت به نام name دارد.
حالا بیایید همان آبجکتهای person1 و person2 را مجدد تعریف کنیم:
person1 = SayHello() person1.name = 'howsam' person1.greet()
hello howsam!
و برای person2:
person2 = SayHello() person2.name = 'Flower' person2.greet()
hello Flower!
class SayHello: name = 'name' def greet(self): print('hello ' + self.name + '!') def bye(self): print('Goodbye ' + self.name + '!')
متد init در کلاس
در کلاسها یکسری متدهای خاص وجود دارند که به آنها magic methods گفته میشود. این متدهای جادویی بسیار جالب هستند و نام همه آنها با داندرلاین (__) شروع و به آن ختم میشود. تعداد این متدهای جادویی زیاد است و معرفی همه آنها در این پست نمیگنجد. در این بخش میخواهیم یکی از پرکاربردترین magic method-ها را معرفی کنیم، متد جادویی __init__.
متد init مخفف initialization است. این متد همزمان با فراخوانی کلاس اجرا میشود. چه فایدهای دارد؟ کلاس SayHello را در ذهن خود مرور کنید. شما از کلاس آبجکت ساختید و سپس اتریبیوت name را مقداردهی کردید. این پروسه کمی اذیتکننده نبود؟ راه حل این مشکل همین init است. کلاس SayHello با استفاده از init به شکل زیر در میآید:
class SayHello: def __init__(self, name): self.name = name def greet(self): print('hello ' + self.name + '!')
در کد بالا متد جادویی __init__ را اضافه کردیم. طبق قراردادی که با هم داشتیم ورودی اول متد را self و ورودی دوم را name گذاشتیم. سپس در تابع init، مقدار name را (که به عنوان ورودی دریافت میشود) به اتریبیوت name اختصاص دادیم.
گفتیم متد init همزمان با فراخوانی کلاس اجرا میشود. پس ورودی init را چطور باید وارد کنیم؟ ورودی init را باید به عنوان ورودی به کلاس بدهیم. به این شکل:
person1 = SayHello('howsam')
تمام؟! بله دیگر نیازی نیست بنویسید person1.name=’howsam’ بلکه همین خط کد کافی است. حالا متد greet را فراخوانی میکنیم:
person1.greet()
hello howsam!
خب این هم نتیجهاش. متدهای جادویی واقعا جادویی هستن نه؟ شاید بتوان گفت در کد همه کلاسها متد init وجود دارد و اتریبیوتها به شکلی که ابتدا توضیح دادیم به ندرت استفاده میشوند.
تعریف کلاسی برای کتاب!
فرض کنید که (به هر دلیلی) به یک کلاسی نیاز داریم که نام کتاب، نام نویسنده کتاب و تعداد صفحات را میگیرد. این کلاس دو کار باید بتواند انجام دهد. یک اینکه برای هر کلمه، یک جمله به شکل زیر بسازد. مثلا برای کتاب Harry Potter، نوشته JK Rowling و با تعداد صفحات 500، بنویسد:
Book Title: Harry Potter
Writer: JK Rowling
Number Of Pages: 500
همچنین یک لیست سیاه به ما داده شده است! در این لیست نام کتابهای ممنوعه قرار داده شده است. اگر کتاب موردنظر در لیست ممنوعه باشد، باید عبارت ‘Warning!, This book is not for your age’ برگردانده شود. پس ما نیاز به متغیرهایی داریم که نام کتاب، نویسنده و تعداد صفحات را در آنها ذخیره کنیم. دو متد هم باید بنویسیم که دو کار خواسته شده را انجام دهند.
متغیرها را در متد __init__ مینویسیم تا زمانی که کلاس را فراخوانی میکنیم initialize شوند. نام دو متد دیگر را sent و blacklist انتخاب میکنیم:
class book: def __init__(self, book_title, writer_name, num_pages): self.title = book_title self.writer = writer_name self.pages = num_pages def sent(self): print('Book Title: ', self.title) print('Writer: ', self.writer) print('Number Of Pages: ', self.pages) def black_list(self): b_list = ['Harry Potter', 'Desiree'] if self.title in b_list: print('Warning!, This book is not for your age')
ابتدا یک متغیر تعریف میکنیم:
my_book = book('Harry Potter', 'JK Rowling', 500)
سپس برای نوشتن جملات موردنظرمان مینویسیم:
my_book.sent()
با اجرای کد بالا خواهیم داشت:
Book Title: Harry Potter Writer: JK Rowling Number Of Pages: 500
برای بررسی این که کتاب در لیست سیاه هست یا خیر، مینویسیم:
my_book.black_list()
Warning!, This book is not for your age
جمعبندی
در این پست نحوه نوشتن کلاس در پایتون را آموزش دادیم. اگرچه کلاسهایی که بررسی شدند، بسیار ساده بودند. اما برای ورود به دنیای پایتون همین قدر دانستن از کلاسها کفایت میکند! بعدها که دستتان راه افتاد میتوانید کلاسهای پیچیدهتری را بنویسید. امیدوارم این آموزش مورد توجه شما قرار گرفته باشد. سوالات و نظرهایتان را برایمان کامنت کنید. به کامنتها در اسرع وقت پاسخ داده خواهد شد.
مطالب زیر را حتما مطالعه کنید
دستورهای پراستفاده pip
علامت تقسیم ، باقیمانده و خارج قسمت در پایتون
نصب کتابخانه matplotlib در پایتون
کوندا چیست
آموزش matplotlib در پایتون
آموزش کتابخانه numpy در پایتون
3 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
واقعا عالی بود. بخش class رو در سایت شما کامل متوجه شدم.
سلام. با تشکر از شما، object در این مثال ها چیست؟
با سلام
من آموزش های زبان پایتون در سایت شما را تمام کردم و تشکر میکنم.
چه منبعی برای آموزش های تکمیلی و پیشرفته زبان پایتون معرفی میکنین؟