در آموزش گذشته با مفهوم کلاس در زبانهای برنامهنویسی آشنا شده و دیدیم که کلاس همچون الگویی است که میتوان از روی آن آبجکتهای مختلف را نمونهسازی کرد. حال بر اساس آنچه در آموزش گذشته آموختیم، کلاسی ساده تحت عنوان 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
میشود.