چندریختی در پایتون «Polymorphism» یک مفهوم اساسی در برنامهنویسی «Programming» است که به موجودیتهایی مانند توابع «Functions»، روشها «Methods» یا عملگرها «Operators» امکان میدهد بسته به نوع دادهای «Data type» که پردازش میکنند، رفتارهای متفاوتی داشته باشند. این واژه از زبان یونانی آمده و به معنای «اشکال متعدد» است. تایپگذاری پویا «Dynamic typing» و Duck Typing، پایتون «Python» را به طور طبیعی چندریخت کردهاند. توابع، عملگرها و حتی اشیای داخلی مانند حلقهها رفتار چندریختی از خود نشان میدهند.
مقدمه
چندریختی در پایتون به این معناست که توابع یا متدها میتوانند با انواع مختلف دادهها بهطور انعطافپذیر عمل کنند، بدون اینکه نیاز به اعلام صریح نوع دادهها باشد. این ویژگی باعث میشود که کد نوشتهشده در پایتون بسیار منعطف و قابل گسترش باشد، زیرا میتوان کدهای جدیدی با پیادهسازیهای متفاوت اضافه کرد بدون اینکه کد موجود تغییر کند. بهطور کلی، چندریختی در پایتون از طریق ارثبری، بازنویسی متدها و Duck Typing در زمان اجرا یا کامپایل پیادهسازی میشود.
چندریختی در توابع داخلی
توابع داخلی پایتون چندریختی هستند و خود را با انواع دادههای مختلف تطبیق میدهند.
print(len("Hello")) # String length print(len([1, 2, 3])) # List length print(max(1, 3, 2)) # Maximum of integers print(max("a", "z", "m")) # Maximum in strings
پایتون رفتار را در زمان اجرا تعیین میکند و این امکان را به توابع میدهد که بدون نیاز به اعلام صریح نوع، با انواع مختلف کار کنند.
بیایید چندریختی در پایتون را با جزئیات بررسی کنیم:
چندریختی در توابع
Duck Typing به توابع اجازه میدهد با هر شیء صرفنظر از نوع آن کار کنند.
def add(a, b): return a + b print(add(3, 4)) # Integer addition print(add("Hello, ", "World!")) # String concatenation print(add([1, 2], [3, 4])) # List concatenation
چندریختی در اپراتورها
در پایتون، عملگرهایی مانند + به صورت چندریخت عمل میکنند و بسته به نوع داده، عملیات جمع، الحاق یا ادغام را انجام میدهند.
print(5 + 10) # Integer addition print("Hello " + "World!") # String concatenation print([1, 2] + [3, 4]) # List concatenation
چندریختی در برنامهنویسی شیگرا
در برنامهنویسی شیگرا، چندریختی به روشها در کلاسهای مختلف اجازه میدهد نام مشترکی داشته باشند اما وظایف متفاوتی را انجام دهند. این ویژگی از طریق ارثبری و طراحی رابط به دست میآید. چندریختی در کنار اصول دیگر برنامهنویسی شیگرا مانند ارثبری «اشتراکگذاری رفتار» و کپسولهسازی «پنهانسازی پیچیدگی» به ایجاد برنامههای مستحکم و ماژولار کمک میکند.
class Shape: def area(self): return "Undefined" class Rectangle(Shape): def __init__(self, length, width): self.length = length self.width = width def area(self): return self.length * self.width class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return 3.14 * self.radius ** 2 shapes = [Rectangle(2, 3), Circle(5)] for shape in shapes: print(f"Area: {shape.area()}")
- کد، چندریختی در پایتون را با استفاده از کلاس والد Shape و کلاسهای فرزند Rectangle و Circle نشان میدهد.
- کلاس والد Shape: یک متد عمومی به نام area دارد که مقدار «Undefined» را برمیگرداند و بهعنوان یک جایگزین برای کلاسهای مشتق شده عمل میکند تا آنها بتوانند این متد را بازنویسی کنند.
- کلاس فرزند Rectangle: طول و عرض را از طریق سازنده __init__ مقداردهی میکند. متد area را بازنویسی میکند تا مساحت مستطیل را بهعنوان طول * عرض بازگرداند.
- کلاس فرزند Circle: شعاع را از طریق سازنده __init__ مقداردهی میکند. متد area را بازنویسی میکند تا مساحت دایره را بهعنوان ۳.۱۴ * شعاع^۲ بازگرداند.
- رفتار چندریختی: یک لیست از اشیاء نوع Shape «مستطیل و دایره» ایجاد میشود. یک حلقه for از طریق این لیست عبور میکند و متد area را برای هر شیء فراخوانی میکند. متدی که اجرا میشود، بسته به نوع شیء تعیین میشود که نشاندهنده رفتار چندریختی است.
انواع چندریختی در پایتون
چندریختی در پایتون به طور کلی به دو نوع تقسیم میشود:
چندریختی زمان کامپایل
- این نوع چندریختی در زبانهای تایپ استاتیک مانند جاوا یا ++C یافت میشود، جایی که رفتار یک تابع یا عملگر در مرحله کامپایل برنامه تعیین میشود.
- مثالها شامل بارگذاری متد و بارگذاری عملگر هستند که در آنها چندین تابع یا عملگر میتوانند نام مشابهی داشته باشند اما وظایف متفاوتی را بر اساس زمینه انجام دهند.
- در پایتون، که تایپ پویا دارد، چندریختی زمان کامپایل به طور طبیعی پشتیبانی نمیشود. در عوض، پایتون از تکنیکهایی مانند تایپ پویا و Duck Typing برای دستیابی به انعطافپذیری مشابه استفاده میکند.
چندریختی زمان اجرا
- چندریختی در پایتون زمان اجرا زمانی رخ میدهد که رفتار یک متد در زمان اجرا بر اساس نوع شی تعیین میشود.
- در پایتون، این از طریق بازنویسی متد بهدست میآید: یک کلاس فرزند میتواند متدی از کلاس والد خود را بازتعریف کند تا پیادهسازی خاص خود را ارائه دهد.
- طبیعت پویا پایتون به آن اجازه میدهد که در چندریختی زمان اجرا عملکرد خوبی داشته باشد و کدی منعطف و قابل تطبیق ایجاد کند.
class Animal: def sound(self): return "Some generic sound" class Dog(Animal): def sound(self): return "Bark" class Cat(Animal): def sound(self): return "Meow" # Polymorphic behavior animals = [Dog(), Cat(), Animal()] for animal in animals: print(animal.sound()) # Calls the overridden method based on the object type
خروجی:
Bark Meow Some generic sound
در اینجا، متد sound بسته به اینکه شیء یک سگ، گربه یا حیوان باشد، بهطور متفاوتی عمل میکند و این تصمیم در زمان اجرا اتخاذ میشود. این ویژگی پویا باعث میشود پایتون برای چندریختی زمان اجرا بسیار قدرتمند باشد.
چندریختی مبتنی بر ارثبری
چندریختی در پایتون مبتنی بر ارثبری زمانی رخ میدهد که یک زیرکلاس متدی را از کلاس والد خود بازنویسی کند و پیادهسازی خاص خود را ارائه دهد. این فرآیند بازپیادهسازی متد در کلاس فرزند بهعنوان بازنویسی متد «Method Overriding» شناخته میشود.
class Animal: def sound(self): return "Some generic animal sound" class Dog(Animal): def sound(self): return "Bark" class Cat(Animal): def sound(self): return "Meow
- کلاس Animal: بهعنوان کلاس پایه «والد» عمل میکند. یک متد sound دارد که رفتار پیشفرضی ارائه میدهد و مقدار «Some generic animal sound» را بازمیگرداند. این متد نمای کلی از رفتار sound برای تمام حیوانات است.
- کلاس Dog: از کلاس Animal ارث میبرد (که با class Dog(Animal) مشخص میشود). متد sound را بازنویسی میکند تا «Woof Woof!» را بازگرداند، که رفتار خاص سگها است. این نشاندهنده بازنویسی متد است، جایی که زیرکلاس پیادهسازی متد کلاس والد را تغییر میدهد.
- کلاس Cat: از کلاس Animal ارث میبرد (که با class Cat(Animal) مشخص میشود). متد `sound` را بازنویسی میکند تا «Meow» را بازگرداند، که رفتار خاص گربهها است. مانند کلاس Dog، این نیز بازنویسی متد را نشان میدهد.
نتیجه گیری
چندریختی در پایتون از طریق ویژگیهای تایپ پویا و Duck Typing بهخوبی پشتیبانی میشود. این امکان را میدهد که توابع و متدها با انواع مختلف دادهها بهطور منعطف کار کنند بدون اینکه نیازی به اعلام صریح نوع باشد. همچنین، با استفاده از ارثبری و بازنویسی متدها، میتوان رفتارهای متفاوتی را برای کلاسهای مختلف تعریف کرد. این ویژگیها باعث میشوند که پایتون به نوشتن کدهای انعطافپذیر، قابل گسترش و نگهداری کمک کند و کدنویسی را سادهتر و موثرتر کند.