خواص (Properties)
property (خصوصیت) روشی برای دسترسی به متغیرهایی با سطح دسترسی private میباشد. همانطور که در درس قبلی هم توضیح داده شد، اعضای خصوصی یک کلاس در خارج از کلاس در دسترس نیستند. حال اگر بخواهیم به اعضای خصوصی کلاس در خارج از کلاس دسترسی داشته باشیم و مقدار آنها را چاپ کنیم و یا به آنها مقداری اختصاص دهیم باید چکار کنیم. چاره کار استفاده از Property ها است.
این Decorator دارای سه بخش میباشد، یک بخش جهت مقدار دهی (بلوک setter) و یک بخش برای دسترسی به مقدار (بلوک getter) یک داده private میباشد و یک بخش جهت پاک کردن مقدار (بلوک deleter). در مثال زیر نحوه تعریف و استفاده از این Decorator آمده است :
1: class Person: 2: 3: __name = "No Name" 4: __age = 0 5: __height = 0.0 6: 7: def __init__(self): 8: self.__name 9: self.__age 10: self.__height 11: 12: @property 13: def Name(self): 14: return self.__name; 15: 16: @Name.setter 17: def Name(self, value): 18: self.__name = value; 19: 20: @Name.deleter 21: def Name(self): 22: del self.__name 23: 24: @property 25: def Age(self): 26: return self.__age 27: 28: @Age.setter 29: def Age(self, value): 30: self.__age = value; 31: 32: @Age.deleter 33: def Age(self): 34: del self.__age; 35: 36: @property 37: def Height(self): 38: return self.__height 39: 40: @Height.setter 41: def Height(self, value): 42: self.__height = value; 43: 44: @Height.deleter 45: def Height(self): 46: del self.__height; 47: 48: person1 = Person(); 49: person1.Name = "Frank"; 50: person1.Age = 19; 51: person1.Height = 162; 52: print("name: {0}".format(person1.Name)); 53: print("age: {0} years old".format(person1.Age)); 54: print("height: {0}cm".format(person1.Height)); 55: 56: print(); #Seperator 57: 58: person2 = Person(); 59: person2.Name = "Ronald"; 60: person2.Age = 25; 61: person2.Height = 174; 62: print("name: {0}".format(person2.Name)); 63: print("age: {0} years old".format(person2.Age)); 64: print("height: {0}cm".format(person2.Height));
Name: Jack Name: Frank Age: 19 years old Height: 162cm Name: Ronald Age: 25 years old Height: 174cm
در برنامه بالا نحوه استفاده از property آمده است. همانطور که مشاهده میکنید در این برنامه ما سه فیلد (خطوط 5-3) تعریف کردهایم (سه فیلد با سطح دسترسی private).
__name __age __height
دسترسی به مقادیر این فیلدها فقط از طریق property های ارائه شده (خطوط 46-12) امکان پذیر است. همانطور که احتمالا متوجه شده اید، به ازای هر فیلد یک Property تعریف شده است. هر Property از سه متد تشکیل شده است :
@property def propertyName(self): #Some Code @propertyName.setter def propertyName(self, value): #Some Code @propertyName.deleter del propertyName(self): #Some Code
همانطور که در کد بالا مشاهده می کنید، قبل از تعریف متد اول propery@، قبل از تعریف متد دوم، عبارت propertyName.setter@ و قبل از متد سوم عبارت propertyName.deleter@ نوشته می شود. propertyName همان نام متد می باشد. نام متدها طبق قرارداد باید همانند نام فیلدها است با این تفاوت که با حرف بزرگ شروع می شود. مثلا در مثال نام فیلد name و نام سه متد مربوطه Name می باشد. و اما کار این سه متد چیست؟
به کلمه کلیدی value در داخل متدهای setter، توجه کنید. Value همان مقداری است که از طریق property به فیلد اختصاص میدهیم. برای اختصاص یک مقدار به یک فیلد از طریق property کافیست که به صورت زیر عمل کنید :
Object.Property = Value;
این کار (قرار دادن یک مقدار بعد از علامت مساوی) به منزله فراخوانی متدهای setter است. و ما به برنامه میفهمانیم که میخواهیم از طریق این متدها یک فیلد را مقداردهی کنیم. Object شیء ایجاد شده از کلاس، Property نام پراپرتی و Value مقداری است که میخواهیم به فیلد اختصاص دهیم. برای دسترسی به یک خاصیت میتوانید از علامت دات (.) استفاده کنید. مثلاً برای اختصاص مقدار به سه فیلد age ،__name__ و height__ از طریق property باید به صورت زیر عمل کنید :
person1.Name = "Frank";
person1.Age = 19;
person1.Height = 162;
دستورات بالا متدهای setter مربوط به هر property را فراخوانی کرده و مقادیری به هر یک از فیلدها اختصاص میدهد. برای فراخوانی متدهای getter کافیست که نام شیء و سپس علامت نقطه و در آخر نام property را بنویسیم. با این کار به برنامه میفهمانیم که ما نیاز به مقدار فیلد داریم.
print("Name: {0}".format(person1.Name)); print("Age: {0} years old".format(person1.Age)); print("Height: {0}cm".format(person1.Height));
به این نکته توجه کنید که در متدهای getter میتوان تغییراتی بر روی فیلدها اعمال کرد. مثلاً فرض کنید که یک فیلد دارید که مقادیر پولی را در خود ذخیره میکند. شما میتوانید در متد getter نحوه نمایش مقدار موجود در این فیلد را مشخص کنید. مثلاً خروجی به صورت سه رقم سه رقم نمایش داده شود. استفاده از property ها کد نویسی را انعطاف پذیر میکند مخصوصاً اگر بخواهید یک اعتبارسنجی برای اختصاص یک مقدار به فیلدها یا استخراج یک مقدار از آنها ایجاد کنید. پس میتوان گفت که :
مثلاً شما میتوانید یک محدودیت ایجاد کنید که فقط اعداد مثبت بین 0 تا 100 به فیلد age (سن) اختصاص داده شود. همانطور که در کد ابتدای درس مشاهده میکنید ما نوع فیلد age را برای سن شخص در نظر گرفته ایم. ولی کاربر میتواند هر رقمی به این فیلد اختصاص دهد ولی چون غیر معقولانه است و سن (age) باید یک عدد مثبت و از لحاظ عقلی عددی از 1 تا 100 باشد میتوانیم کاربر را با استفاده از متد setter مربوط به این فیلد مجبور کنیم که رقمی بین این دو عدد را به age اختصاص دهد. خطوط 30-28 کد ابتدای درس را با کدهای زیر جایگزین کرده و مقادیر منفی و یا بالاتر از 100 را به فیلد age اختصاص داده و نتیجه را مشاهده کنید :
@Age.setter def Age(self, value): if(value > 0 and value <= 100): self.__age = value; else: age = 0;
مشاهده می کنید اگر کاربر بخواهد یک مقدار منفی و یا بزرگتر از صفر به فیلد age اختصاص دهد مقدار age صفر خواهد شد. اما از متد deleter اگر بخواهید که مقدار اختصاص داده شده به یک فیلد را پاک کنید استفاده می شود. بعد از خط 51 دکمه Enter را زده و کد زیر را بنویسید:
del(person1.Name)
این کد مقداری را که در خط 49 به فیلد name اختصاص داده ایم را پاک می کند و اگر برنامه را اجرا کنید مقدار پیشفرض این فیلد یعنی No Name نمایش داده می شود نه Frank.
عالیه