در آموزش گذشته با مفهوم کلاس در زبانهای برنامهنویسی آشنا شده و دیدیم که کلاس همچون الگویی است که میتوان از روی آن آبجکتهای مختلف را نمونهسازی کرد. حال بر اساس آنچه در آموزش گذشته آموختیم، کلاسی ساده تحت عنوان Shape را به صورت زیر در فایلی به نام ShapeClass.py پیادهسازی میکنیم:
class Shape:
size
همانطور که در کد فوق ملاحظه میشود، ابتدا کلیدواژۀ class را نوشته و نامی دلخواه برای کلاس خود در نظر گرفته سپس علامت : را قرار دادهایم. در ادامه یک متغیر تحت عنوان size با در نظر گرفتن تورفتگی نسبت به سطر اول ایجاد کردهایم که دارای هیچ مقدار اولیهای نیست. حال میتوانیم از روی کلاس Shape بدین ترتیب نمونهسازی کنیم:
myRect = Shape()
myCircle = Shape()
در حقیقت، زمانی که دستور ()Shape اجرا میشود، متد از پیش تعریفشدۀ ()__new__ برای ساخت آبجکت جدید و متدی دیگر تحت عنوان ()__init__ به منظور مقداردهی اولیه به آن فراخوانی میشوند که تحت عنوان Constructor شناخته شده و از همین روی اگر بخواهیم در زمان تعریف یک آبجکت مقادیر اولیهای را به اتریبیوتهای آن منتسب کنیم، باید متد از پیش تعریفشدۀ ()__init__ را مورد استفاده قرار دهیم. برای مثال، کلاس Shape را بدین صورت بازنویسی میکنیم:
class Shape:
size = 2
def __init__(self, name, color):
self.name = name
self.color = color
اولین پارامتری که به متد ()__init__ و همچنین دیگر متدهای کلاس مد نظر داده میشود self نام دارد که نمایندۀ نمونۀ ایجادشده از روی کلاس مذکور است و به منظور دسترسی به اتریبیوتهای کانستراکتور مورد استفاده قرار میگیرد سپس در ادامه پارامترهایی به عنوان ورودی به متد ()__init__ داده میشوند که قصد داریم تا در زمان ایجاد هر آبجکت جدید از روی کلاس مد نظر آنها را مقداردهی کنیم. در واقع، هنگام ساخت آبجکت جدید از روی کلاس کنونی، پارامتر self به آبجکت مذکور ارجاع میدهد و بدین ترتیب میتوان به اتریبیوتهای مد نظر از متد ()__init__ دسترسی داشته و آنها را مقداردهی کرد به علاوه اینکه با بهکارگیری کیورد self به عنوان اولین پارامتر ورودیِ سایر متدهای کلاس میتوان به متد مد نظر از کلاس مربوطه دسترسی داشته و آن را روی آبجکت ساختهشده از روی کلاس فراخوانی کرد.
برای مثال، در کد فوق پارامترهایی تحت عناوین name و color به کانستراکتور داده شدهاند و در بدنۀ آن نیز دستور self.name = name را نوشتهایم و بدین ترتیب گفتهایم که در هنگام ساخت هر گونه آبجکتی از روی کلاس Shape اتریبیوت name باید به مقدار معادل پارامتر ورودیِ name منتسب شود. همچنین دستور self.color = color نیز اتریبیوت color را برای هر گونه آبجکت ساختهشده از روی این کلاس به مقدار پارامتر ورودیِ color منتسب میکند. اکنون چنانچه بخواهیم آبجکتهای جدیدی از روی این کلاس ایجاد کنیم، به صورت زیر عمل میکنیم:
shape1 = Shape('Circle', 'Yellow')
shape2 = Shape('Square', 'Green')
در کد فوق دو آبجکت جدید تحت عناوین shape1 و shape2 ایجاد کرده و اتریبیوتهای name و color را برای آنها مقداردهی کردهایم. همانطور که در آموزش گذشته اشاره کردیم، با استفاده از عملگر . میتوانیم به مقدار اتریبیوتهای این دو شیئ دسترسی پیدا کنیم که برای این منظور کدی مانند زیر خواهیم داشت:
>>> print(shape1.name)
Circle
>>> print(shape2.color)
Green
همانطور که میبینید، مقادیر منتسب به هر یک از اتریبیوتهای name و color به ترتیب برابر با مقادیر مد نظر برای آرگومانهای ورودی در هنگام ساخت آبجکتهای جدید متناظر میباشند. همچنین در صوت نیاز میتوان اتریبیوت جدیدی به آبجکت مد نظر اضافه کرد، اتریبیوتهای قبلی را تغییر داد و برخی اتریبیوتهای مد نظر را حذف کرد (به عبارتی، صفت منتسب به یک آبجکت را از آن گرفت.) که به عنوان یک مثال در این مورد، کدهای زیر را مد نظر قرار میدهیم:
shape1.color = 'blue'
shape1.radius = 20
del shape1.name
در دستور اول یک مقدار جدید معادل استرینگ «blue» به اتریبیوت color از آبجکت shape1 منتسب کردهایم و در دستور دوم نیز اتریبیوت جدیدی با شناسۀ radius و مقداری معادل با 20 به آبجکت shape1 منتسب میکنیم و در نهایت در دستور سوم با استفاده از کیورد del و سپس دسترسی به اتریبیوت name از آبجکت shape1 آن را از آبجکت مد نظر حذف میکنیم. حال جهت تست، قصد داریم ببینیم که اجرای کدهای فوق چه تغییراتی روی اتریبیوتهای مربوط به هر یک از آبجکتهای shape1 و shape2 اِعمال کردهاند که برای این منظور داریم:
>>> print(shape1.color)
blue
>>> print(shape1.radius)
20
>>> print(shape1.name)
Traceback (most recent call last):
File "C:/SokanAcademy/ShapeClass.py", line 19, in
print(shape1.name)
AttributeError: 'Shape' object has no attribute 'name'
همانطور که میبینید، آخرین مقادیر منتسب به هر یک از اتریبیوتهای color و radius از آبجکت shape1 به ترتیب برابر با استرینگ «blue» و عدد 20 میباشند که در خروجی چاپ شدهاند. اجرای دستور سوم نیز منجر به بروز خطا شده است چرا که آبجکت shape1 اتریبیوتی با شناسۀ name ندارد (در واقع، پیش از این با دستور del این اتریبیوت را از آبجکت مد نظر حذف کردهایم.)
علاوه بر روشهای فوقالذکر، از فانکشنهای دیگری نیز میتوان به منظور مدیریت اتریبیوتهای یک آبجکت استفاده کرد که در ادامه خلاصهای از نحوۀ کارشان را آوردهایم:
کاربرد فانکشن به منظور دسترسی به اتریبیوتهای یک آبجکت getattr(obj, name[default]) برای بررسی اینکه یک آبجکت اتریبیوت خاصی را دارا است یا خیر hasattr(obj, name) مقداردهی به اتریبیوتی از یک آبجکت (چنانچه اتریبیوت مد نظر موجود باشد، مقدار جدید میگیرد و در غیر این صورت اتریبیوت جدیدی با مقدار مربوطه به آبجکت منتسب میشود.) setattr(obj, name, value) برای حذف یک اتریبیوت از آبجکت delattr(obj, name)به عنوان مثالی عملی در رابطه با هر یک از فانکشنهای فوق، کدی مانند زیر را مد نظر قرار میدهیم:
>>> print(hasattr(shape2, 'radius')) # Returns true if 'radius' attribute exists
False
>>> print(getattr(shape1, 'radius')) # Returns value of 'radius' attribute
20
>>> setattr(shape2, 'radius', 8) # Set attribute 'radius' at 8
>>> delattr(shape1, 'color') # Delete attribute 'color'
خروجی دستور اول برابر با مقدار بولین False است چرا که هرگز اتریبیوتی تحت عنوان radius به آبجکت shape2 منتسب نکردهایم و دستور دوم نیز مقدار منتسب به اتریبیوت radius از آبجکت shape1 را در خروجی چاپ میکند و در ادامه دستور سوم اتریبیوتی به نام radius با مقداری معادل با عدد 8 را به آبجکت shape2 منتسب میکند و در نهایت دستور چهارم نیز منجر به حذف اتریبیوت color از آبجکت shape1 میشود.
