Descriptor
استفاده از descriptor ها هم یک روش قوی برای اضافه کردن رفتار متد مانند به یک اتریبیوت بدون تغییر دادن اینترفیس یک کلاس است. فرض کنید یک برنامه طراحی نوشتید و دو تا کلاس به نام های دایره و مربع دارید. میخواهیم عددی را به عنوان شعاع/ طول بگیریم و قبل ان چک کنیم که عدد حتما مثبت باشد. خب طبق چیزی که تا الان یاد گرفتیم میدانیم که با property میشود همین کار را انجام داد اما این کار باعث کد تکراری زدن میشود و خوب نیست پس از descriptor استفاده میکنیم.
با استفاده از descriptor کدی مانند زیر خواهیم داشت.
در قطعه کد بالا میبینیم که یک کلاس به نام PositiveNumber داریم.
این همان descriptor ما هست. سه داندر متد داره که به ترتیب به توضیح انها میپردازم.
متد اولی توسط پایتون به صورت اتومات هنگامی که از ان یک اینستنس بسازید صدا زده میشود و نام ان اینستنس هرچه که باشد به عنوان ارگومان name به متد پاس داده میشود. ارگومان owner هم نام کلاسی است که descriptor در ان استفاده شده است. ( در مثال ما Circle یا Square)
متد دوم همان متد getter و متد سوم هم همان متد setter همانند کاری که در پراپرتی انجام دادیم.
ارگومان instance که در دو متد getter,setter وجود داره درواقع همون اینستنسی هست که از کلاس Circle یا Square ما ساخته شده.
توجه داشته باشید که برای ذخیره یا مشاهده از اتریبیوت
این متد ها، اتومات توسط خود پایتون صدا زده میشوند.
حال در کلاس دایره خود، یک اتریبیوت کلاس به نام radius داریم که مقدارش، یک اینستنس از کلاس descriptor ما هست.
حال از این بعد هروقت بخواهیم مقداری در اتریبیوت radius ذخیره کنیم یا مقدار ان را مشاهده کنیم، بجای انکه پایتون از اتریبیوت
منبع
#Descriptor #Python
@Code_Crafters
استفاده از descriptor ها هم یک روش قوی برای اضافه کردن رفتار متد مانند به یک اتریبیوت بدون تغییر دادن اینترفیس یک کلاس است. فرض کنید یک برنامه طراحی نوشتید و دو تا کلاس به نام های دایره و مربع دارید. میخواهیم عددی را به عنوان شعاع/ طول بگیریم و قبل ان چک کنیم که عدد حتما مثبت باشد. خب طبق چیزی که تا الان یاد گرفتیم میدانیم که با property میشود همین کار را انجام داد اما این کار باعث کد تکراری زدن میشود و خوب نیست پس از descriptor استفاده میکنیم.
با استفاده از descriptor کدی مانند زیر خواهیم داشت.
import math
class PositiveNumber:
def __set_name__(self, owner, name):
self._name = name
def __get__(self, instance, owner):
return instance.__dict__[self._name]
def __set__(self, instance, value):
if not isinstance(value, int | float) or value <= 0:
raise ValueError("positive number expected")
instance.__dict__[self._name] = value
class Circle:
radius = PositiveNumber()
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
return round(math.pi * self.radius**2, 2)
class Square:
side = PositiveNumber()
def __init__(self, side):
self.side = side
def calculate_area(self):
return round(self.side**2, 2)
در قطعه کد بالا میبینیم که یک کلاس به نام PositiveNumber داریم.
این همان descriptor ما هست. سه داندر متد داره که به ترتیب به توضیح انها میپردازم.
متد اولی توسط پایتون به صورت اتومات هنگامی که از ان یک اینستنس بسازید صدا زده میشود و نام ان اینستنس هرچه که باشد به عنوان ارگومان name به متد پاس داده میشود. ارگومان owner هم نام کلاسی است که descriptor در ان استفاده شده است. ( در مثال ما Circle یا Square)
متد دوم همان متد getter و متد سوم هم همان متد setter همانند کاری که در پراپرتی انجام دادیم.
ارگومان instance که در دو متد getter,setter وجود داره درواقع همون اینستنسی هست که از کلاس Circle یا Square ما ساخته شده.
توجه داشته باشید که برای ذخیره یا مشاهده از اتریبیوت
__dict__استفاده میکنیم که جلوتر متوجه علت ان خواهید شد.
این متد ها، اتومات توسط خود پایتون صدا زده میشوند.
حال در کلاس دایره خود، یک اتریبیوت کلاس به نام radius داریم که مقدارش، یک اینستنس از کلاس descriptor ما هست.
حال از این بعد هروقت بخواهیم مقداری در اتریبیوت radius ذخیره کنیم یا مقدار ان را مشاهده کنیم، بجای انکه پایتون از اتریبیوت
__dict__ان را بخواند یا ذخیره کند، متد های getter, setter از کلاس PositiveNumber با توجه به عملیات مورد نیاز صدا زده میشود و ارگومان های مورد نیاز پاس داده خواهد شد.
منبع
#Descriptor #Python
@Code_Crafters
👍4❤2👏1