در پایتون، کلاسها وسیلهای تمیز برای بستهبندی دادهها و عملکرد با هم در عناصر قابل استفاده مجدد ارائه میکنند. ایجاد کلاس های سفارشی به شما امکان می دهد تا موجودیت های دنیای واقعی مانند کاربران، محصولات و کارمندان را مدل کنید.
در پایتون، کلاسها وسیلهای تمیز برای بستهبندی دادهها و عملکرد با هم در عناصر قابل استفاده مجدد ارائه میکنند. ایجاد کلاس های سفارشی به شما امکان می دهد تا موجودیت های دنیای واقعی مانند کاربران، محصولات و کارمندان را مدل کنید.
کلاسهای پایتون روشهای جادویی را تعریف میکنند که میتوانید آنها را سفارشی کنید تا به شما اجازه دهند رفتار کلاسهای خود را برای موقعیتهای منحصربهفرد شکل دهید.
آشنایی با روش های جادویی
متدهای جادویی را که به آن متدهای dunder نیز میگویند، بهعنوان طلسمهای مخفی یا آوازهای مخفی تصور کنید که پایتون بهطور خودکار وقتی اعمال خاصی را روی یک شی انجام میدهید، فراخوانی میکند.
پایتون رفتارهای داخلی زیادی را برای کلاس ها از طریق متدهای نمونه، استاتیک و کلاس ارائه می کند. میتوانید کلاسهای پایتون ایجاد کنید و با استفاده از روشهای جادویی، آنها را حتی بیشتر سفارشی کنید.
متدهای جادویی متدهای نمونه ای در پایتون هستند که قبل و بعد از نام متد دو خط زیر (__method__) دارند.
این متدهای ویژه دستورالعمل هایی را در مورد نحوه مدیریت اشیاء یک کلاس به پایتون می دهند. در اینجا چند روش جادویی رایج در کلاس های پایتون آورده شده است:
- __gt__: این روش بررسی میکند که آیا یک شی از دیگری بزرگتر است یا خیر.
- __init__: این متد زمانی اجرا می شود که شما نمونه ای از یک کلاس را ایجاد می کنید و عمدتاً برای مقداردهی اولیه مشخصه است.
- __str__: این نمایش رشته ای از کلاس توصیف کننده شی را برمی گرداند.
- __repr__: این متد یک خروجی می دهد که به شما امکان می دهد با استفاده از eval() شی را دوباره بسازید.
- __len__: وقتی از تابع len() روی یک شی استفاده می کنید، این متد طول شی را برمی گرداند.
- __eq__: این روش مقایسه بین اشیاء را با استفاده از عملگر دو برابر (==) امکان پذیر می کند.
- __lt__: این مقایسه کمتر از (<) را برای اشیا پیاده سازی می کند.
- __add__: وقتی از عملگر جمع (+) روی اشیاء استفاده می کنید، این متد اجرا می شود و عملیات جمع را انجام می دهد.
- __getitem__: به شما امکان می دهد موارد را از یک شی با استفاده از نحو فهرست، مانند obj[key] بازیابی کنید.
پیاده سازی روش های جادویی
بهترین راه برای درک روش های جادویی استفاده از آنهاست.
نمایش رشته ای از یک شی
شما می توانید نمایش رشته یک شی را برای خوانایی یا پردازش بیشتر سفارشی کنید.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person('John', 25)
print(p1)
در اینجا شما یک کلاس Person ساده با متد جادویی __init__ برای مقداردهی اولیه آن دارید. هنگامی که شی p1 را چاپ می کنید، از نمایش رشته پیش فرض ارائه شده توسط پایتون استفاده می کند.
برای سفارشی کردن نمایش رشته، متدهای جادویی __str__ و __repr__ را تعریف کنید:
class Person:
def __init__(self, name, age, height):
self.name = name
self.age = age
self.height = height
def __str__(self):
return f'{self.name} is {self.age} years old'
def __repr__(self):
return f'{self.name} is {self.age} years old'
p1 = Person('John', 25, 78)
print(p1)
اکنون شما یک نمایش رشته ای خوانا و جامع تر از شی p1 دارید:
ویژگی طول یک شی
تصور کنید که وقتی متد len() یک شی Person را فراخوانی می کنید، ارتفاع آن را می خواهید. متد جادویی __len__ را برای کلاس Person پیاده سازی کنید:
class Person:
def __init__(self, name, age, height):
self.name = name
self.age = age
self.height = height
def __str__(self):
return f'{self.name} is {self.age} years old'
def __repr__(self):
return f'{self.name} is {self.age} years old'
def __len__(self):
return self.height
p2 = Person('Issac', 25, 89)
print(len(p2))
متد جادویی __len__ ویژگی ارتفاع یک نمونه Person را برمی گرداند. وقتی len(p2) را فراخوانی می کنید، متد جادویی __len__ را به طور خودکار فراخوانی می کند که ارتفاع شی p2 را برمی گرداند.
مدیریت مقایسه بین اشیاء
اگر نیاز دارید که اشیاء یک کلاس را بر اساس ویژگی های خاص کلاس مقایسه کنید. می توانید روش جادویی __eq__ را تعریف کنید و منطق مقایسه خود را پیاده سازی کنید.
class Person:
def __init__(self, name, age, height):
self.name = name
self.age = age
self.height = height
def __str__(self):
return f'{self.name} is {self.age} years old'
def __repr__(self):
return f'{self.name} is {self.age} years old'
def __len__(self):
return self.height
def __eq__(self, other):
return self.name == other.name and self.age == other.age
p1 = Person('John', 25, 56)
p2 = Person('John', 25, 61)
print(p1 == p2)
روش __eq__ ویژگی های نام و سن دو شیء Person را برای تعیین برابری مقایسه می کند.
عملگر دو برابر (==) از این روش برای بررسی برابری به جای مقایسه هویت ها استفاده می کند. بنابراین دو نمونه Person اگر ویژگیهای نام و سن مطابقت داشته باشند با هم برابر هستند. این به شما امکان می دهد تا رفتار پیش فرض بررسی برابری را برای کلاس سفارشی خود لغو کنید.
با پیاده سازی این روش های جادویی، می توانید رفتار سفارشی را تعریف کنید که با توکارهای پایتون سازگار باشد.
روش های جادویی پیشرفته
در اینجا چند نمونه پیشرفته از استفاده از متدهای جادویی برای سفارشی کردن کلاس ها آورده شده است.
کلاسها مانند کانتینر عمل میکنند
با استفاده از متدهای جادویی میتوانید کلاسهایی را تعریف کنید که مانند کانتینرها عمل میکنند. شما می توانید از کانتینرها مانند تاپل ها برای ذخیره مجموعه ای از عناصر داده استفاده کنید. آنها روش های مختلفی را برای دستکاری، دسترسی و تکرار از طریق عناصر موجود ارائه می کنند.
class Person:
def __init__(self):
self.data = []
def __len__(self):
return len(self.data)
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value
def __delitem__(self, index):
del self.data[index]
p1 = Person()
p1.data = [10, 2, 7]
print(len(p1)) # 3
p1[0] = 5
print(p1[0]) # 5
حالا یک شی Person می تواند مانند یک ظرف رفتار کند:
سفارشی کردن دسترسی به ویژگی
با استفاده از متد جادویی __getattr__ می توانید نحوه دسترسی به ویژگی های کلاس Person را بر اساس شرایط خاص سفارشی کنید.
class Person:
def __getattr__(self, name):
if name == 'age':
return 40
else:
raise AttributeError(f'No attribute {name}')
p1 = Person()
print(p1.age) # 40
متد __getattr__ زمانی اجرا میشود که بخواهید به یک ویژگی دسترسی پیدا کنید که مستقیماً در شی وجود ندارد. در این حالت، بررسی میکند که نام ویژگی age است یا خیر و 40 را برمیگرداند.
برای هر نام مشخصه دیگری، یک AttributeError با یک پیام مربوطه ایجاد می کند.
رفتار کلاسها مانند فراخوانی
متد __call__ به شما امکان می دهد نمونه ای از کلاس را به عنوان یک شیء فراخوانی (به عنوان مثال، یک تابع) در نظر بگیرید.
class Adder:
def __call__(self, x, y):
return x + y
adder = Adder()
print(adder(2, 3)) # 5
هنگامی که یک نمونه از Adder ایجاد می کنید و سپس آن را با آرگومان فراخوانی می کنید، متد __call__ اجرا می شود و قبل از برگرداندن نتیجه، جمع را انجام می دهد.
بارگذاری بیش از حد اپراتور
با استفاده از روش های جادویی می توانید بارگذاری بیش از حد اپراتور را انجام دهید. بارگذاری بیش از حد اپراتور به شما امکان می دهد تا رفتارهای سفارشی را برای اپراتورهای داخلی تعریف کنید، زمانی که با نمونه هایی از کلاس های خود استفاده می کنید. در اینجا یک مثال رایج است که بارگذاری بیش از حد اپراتور را توضیح می دهد.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
if isinstance(other, Vector):
new_x = self.x + other.x
new_y = self.y + other.y
return Vector(new_x, new_y)
else:
raise TypeError("Unsupported operand type for +")
def __str__(self):
return f"({self.x}, {self.y})"
# Creating two Vector instances
v1 = Vector(2, 3)
v2 = Vector(1, 4)
# Adding two Vector instances using the + operator
v3 = v1 + v2
# Printing the result
print(v3) # Output: (3, 7)
نتیجه یک بردار جدید است:
کلاس Vector متد __add__ را تعریف می کند، که زمانی اجرا می شود که از عملگر + بین دو نمونه از کلاس استفاده می کنید. این روش مولفه های مربوط به دو بردار را اضافه می کند و یک نمونه Vector جدید را با نتیجه برمی گرداند.
در اینجا روش های جادویی اساسی را مشاهده کرده اید که می توانید برای سفارشی کردن رفتار کلاس خود پیاده سازی کنید. پایتون روشهای جادویی بسیار بیشتری دارد که در هنگام ایجاد کلاسها انعطافپذیری بیشتری را ارائه میدهند. برای فهرست کامل به اسناد رسمی مراجعه کنید.
برنامه نویسی شی گرا در پایتون
متدهای جادویی در پایتون راههای قدرتمندی را برای سفارشیسازی و بهبود رفتار کلاسها ارائه میکنند. متدهای جادویی همراه با مفهوم برنامه نویسی شی گرا (OOP) در پایتون هستند. بنابراین درک مفهوم OOP هنگام تلاش برای استفاده از روش های جادویی مهم است.