در آموزش گذشته با نحوۀ تعریف کلاس و همچنین چگونگی نمونهسازی از روی آن آشنا شدیم اما در این آموزش قصد داریم ببینیم پس از تعریف یک کلاس در پایتون چه اتفاقاتی در پشت پرده میافتند.
در واقع، پس از تعریف هر کلاس دلخواهی در زبان برنامهنویسی پایتون، یکسری اتریبیوت پیشفرض به آن کلاس افزوده میشوند به طوری که هر یک کارکرد مختص به خود را دارا است که در این آموزش برخی از پرکاربردترین این دست اتریبیوتها را معرفی خواهیم کرد. برای شروع این مبحث، کدی مانند زیر را مد نظر قرار میدهیم:
class Student:
'Common base class for all students'
count = 0
def __init__(self, name, family):
self.name = name
self.family = family
Student.count += 1
def displayCount(self):
print("Total Student:", Student.count)
def displayStudent(self):
print("Name:", self.name, ", family:", self.family)
اسکریپت این برنامه را در فایلی به نام StudentClass.py
ذخیره کرده و آن را اجرا میکنیم. در کد فوق ابتدا با بهکارگیری کیورد class
کلاسی به نام Student
تعریف کرده و در ادامه علامت :
را قرار داده سپس با رعایت تورفتگی وارد بدنۀ داخلی کلاس شده و استرینگی در قالب یک کامنت مابین علائم تککوتیشن به صورت ' '
قرار دادهایم (در آموزش آشنایی با مستندسازی در پایتون به تفصیل بدین موضوع پرداختهایم.)
حال در ادامه متغیری به نام count
تعریف کرده و مقدار اولیۀ ۰ را به آن دادهایم که به عنوان یکی از اتربیوتهای کلاس Student
به شمار میرود و قرار است تا تعداد آبجکتهای ساختهشده از روی آن را نگهداری کند. سپس متد از پیش تعریفشدۀ ()__init__
را نوشتهایم که نقش کانستراکتور را بازی میکند و دارای سه پارامتر ورودی است. پارامتر اول تحت عنوان self
به منظور ارجاع دادن به آبجکتهای ساختهشده از روی کلاس جاری مورد استفاده قرار میگیرد و پارامتر دوم تحت عنوان name
برای نگهداری اتریبیوت مرتبط با نام و در نهایت پارامتر family
را داریم که به منظور نگهداری اتریبیوت نام خانوادگی آبجکت مد نظر تعریف شدهاند.
داخل کانستراکتور کلاس نیز گفتهایم در صورت ساخت آبجکتی از روی کلاس Student
مقدار معادل آرگومان ورودیِ name
و family
به ترتیب به اتریبیوتهای name
و family
منتسب گردد و در ادامه دستور Student.count += 1
را داریم که بدین ترتیب گفتهایم در صورت ساخت آبجکتی از روی کلاس، مقدار اتریبیوت count
یک واحد افزایش یابد (همانطور که در آموزش آشنایی با کیورد گلوبال گفتیم، متغیر count
در داخل متد ()__init__
و در یک دستور انتسابی به کار رفته است و از همین روی یک متغیر لوکال ارزیابی میشود.)
در واقع، به منظور دسترسی به اتریبیوت count
هم در داخل کلاس و هم خارج از آن به صورت گلوبال ابتدا نام کلاس را ذکر کرده سپس علامت .
را قرار دادهایم چرا که بدون ذکر نام کلاس نمیتوانیم خارج از کلاس Student
به آن دسترسی داشته باشیم. در چنین شرایطی، با ساخت آبجکت از روی کلاس Student
متد ()__init__
فراخوانی شده و مقادیر معادل هر یک از آرگومانهای ورودی را به ترتیب به متغیرهای name
و color
منتسب میکند و در نهایت دستور count += 1
اجرا میشود که معادل count = count + 1
است.
همانطور که پیشتر گفتیم، count
یک متغیر لوکال ارزیابی میشود و از همین روی مفسر پایتون در داخل متد ()__init__
به دنبال آن میگردد اما با این حال متغیری با شناسۀ count
در داخل این متد تعریف و مقداردهی اولیه نشده است که بدین ترتیب با ذکر نام کلاس در ابتدای آن میتوانیم به صورت گلوبال به آن دسترسی داشته و از همین روی در هر بار ساخت آبجکت از روی کلاس Student
مقدار اتربیوت count
یک واحد افزایش پیدا میکند.
در ادامه، متدی تحت عنوان ()displayCount
با پارامتر ورودی self
تعریف کردهایم که به منظور اشاره به آبجکت ساختهشده از روی کلاس جاری مورد استفاده قرار میگیرد. فانکشن مذکور را برای نمایش تعداد آبجکتهای ساختهشده از روی کلاس Student
تعریف کردهایم که در آن گفتهایم در صورت فراخوانی، مقدار منتسب به اتریبیوت count
را به همراه استرینگ «:Total Student» در خروجی چاپ کند.
به همین ترتیب فانکشن دیگری به نام ()displayStudent
تعریف کردهایم که در صورت فراخوانی روی آبجکت ساختهشده از روی این کلاس، نام و نام خانوادگی دانشآموز را در قالب استرینگی متشکل از مقادیر منتسب به هر یک از اتریبیوتهای name
و family
از آبجکت مربوطه در خروجی چاپ میکند.
حال پس از تعریف کلاس Student
قصد داریم با بهکارگیری فانکشن ()print
ببینیم هر یک اتریبیوتهای از پیش تعریفشده در این کلاس چه مقادیری را نگهداری میکنند. اولین اتریبیوت تحت عنوان __doc__
شناخته میشود و نشاندهندۀ داکیومنت مربوط به کلاس مد نظر میباشد که در مورد کلاس Student
استرینگ مربوط به کامنت درجشده در سطر دوم از بدنۀ کلاس را در خروجی ریترن میکند. برای این منظور کد زیر را در نظر میگیریم:
>>> print(Student.__doc__)
Common base class for all students
در کد فوق به منظور دسترسی به اتریبیوت مد نظر از کلاس Student
ابتدا نام کلاس را آورده و در ادامه یک علامت .
قرار دادهایم سپس نام اتریبیوت از پیش تعریفشدۀ __doc__
را ذکر کردهایم و آن را به عنوان پارامتر ورودی به فانکشن ()print
دادهایم که از همین روی استرینگ «Common base class for all students» در خروجی چاپ میشود.
اتریبوت از پیش تعریفشدۀ دیگری به نام __name__
داریم که دربرگیرندۀ نام کلاس مربوطه است و به منظور تست آن روی کلاس Student
ساختاری مانند بلوک زیر را مد نظر میدهیم:
>>> print(Student.__name__)
Student
در کد فوق اتربیوت __name__
از کلاس Student
را به عنوان آرگومان ورودی به فانکشن ()print
دادهایم که با اجرای آن نام کلاس مربوطه در خروجی چاپ میشود.
در حین اجرای کلاس فوق، اتریبیوت از پیش تعریفشدۀ دیگری تحت عنوان __module__
به این کلاس افزوده میشود که نشاندهندۀ نام ماژولی است که کلاس مد نظر در آن تعریف شده است به طوری که سازوکار این اتریبیوت برای کلاس Student
به صورت زیر خواهد بود:
>>> print(Student.__module__)
__main__
خروجی حاصل از اجرای کد فوق بیانگر این موضوع است که کد مد نظر در ماژول خاصی تعریف نشده و از طریق محیط اسکریپتی یا تعاملی پایتون و در یک حالت استاندارد اجرا شده است.
تعریف کلاس در نسخۀ سوم زبان برنامه نویسی پایتون به دو روش انجام میشود که در ادامه فرم کلی هر یک را تشریح میکنیم. روش اول که در آموزش آشنایی با مفهوم Class با آن آشنا شدیم، یک حالت مرسوم به منظور تعریف کلاس بوده و فرم کلی آن بدین صورت میباشد:
class Sample:
#blocks of code
اما روش دوم بدین ترتیب است که در جلوی نام کلاس علائم ()
قرار داده و داخل آن آرگومانی تحت عنوان object
داریم که فرم کلی آن بدین صورت میباشد:
class Sample(object):
#blocks of code
به طور کلی، هر دو روش فوقالذکر به منزلۀ تعریف کلاسی دلخواه تحت عنوان Sample
بوده و بدین صورت تفسیر میشوند كه هنگام تعریف کلاس در زبان برنامهنویسی پایتون، تمامی کلاسها به صورت پیشفرض از یک کلاس به اصطلاح Base یا والد تحت عنوان object
ارثبری میکنند (در آموزشهای آتی با مفهوم Inheritance و چگونگی ارثبری کلاسها از یکدیگر بیشتر آشنا خواهیم شد.)
اتریبیوت __bases__
نیز آبجکتی از جنس تاپل است و کلاسهای والدی را نشان میدهد که کلاس مد نظر از آنها ارثبری کرده است و هر یک از آنها را با علامت ,
از یکدیگر جدا میکند. در مورد کلاس Student
نیز با اجرای کد زیر خواهیم داشت:
>>> print(Student.__bases__)
(<class 'object'>,)
بنابراین خروجی حاصل از اجرای کد فوق بیانگر این موضوع است که کلاس Student
صرفاً از کلاس object
ارثبری کرده است و چنانچه کلاس مد نظر از کلاسی دیگر ارثبری کند، به جای استرینگ «object» استرینگ مربوط به نام کلاس والد در خروجی ریترن میشود.
در نهایت، اتریبیوت از پیش تعریفشدۀ __dict__
را داریم که یک آبجکت از نوع دیکشنری بوده و تمامی اتریبیوتهای تعریفشده در کلاس مربوطه را نگهداری میکند. برای مثال در رابطه با کلاس Student
داریم:
>>> print(Student.__dict__)
{'__module__': '__main__', '__doc__': 'Common base class for all students', 'count': 1, '__init__': <function Student.__init__ at 0x0000000F65F908C8>, 'displayCount': <function Student.displayCount at 0x0000000F65F90400>, 'displayStudent': <function Student.displayStudent at 0x0000000F65F902F0>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>}
همانطور که میبینید، خروجی حاصل از اجرای کد فوق اتریبیوتهایی با مقادیر متناظرشان را نشان میدهد که به ترتیب شامل ماژول مرتبط با کلاس Student
و استرینگ مربوط به کامنت درجشده، اتریبیوت count
با تعداد آبجکتهای ساختهشده از روی این کلاس و همچنین سایر اتریبیوتهای آن است.