آموزش شی گرایی در پایتون برای مبتدیان (به زبان ساده)
برنامه نویسی شی گرا معنی عبارت Object-Oriented Programming می باشد که به اختصار OOP نیز نوشته می شود. بیشتر افراد این اصطلاح را مرتبط به زبان برنامه نویسی جاوا می دانند. این درست است که جاوا به سبک شی گرایی در برنامه نویسی شهرت دارد اما آیا تنها زبانی است که از برنامه نویسی شی گرا پشتیبانی می کند؟ قطعا نه.
زبان برنامه نویسی پایتون نیز یک سبک برنامه نویسی شی گرا ارائه می دهد. در این آموزش سعی کرده ایم تا به طور کامل برنامه نویسی شی گرا در پایتون را بررسی کنیم و همچنین پیاده سازی مفاهیم شی گرایی در پایتون را توضیح دهیم.
مبانی برنامه نویسی شی گرا (OOP) در پایتون
برای یادگیری مبحث مهم برنامه نویسی شی گرا در پایتون، مفاهیم زیر را هم در قسمت تئوری و هم پیاده سازی بررسی خواهیم کر:.
1- کلاس (Class)
2- شی (Object)
3- وراثت (Inheritance)
4- صفت (Attribute)
5- متد (Method)
در ادامه آموزش برای برنامه نویسی شی گرا به اختصار از OOP استفاده می کنیم. بریم یادگیری OOP در پایتون را شروع کنیم!
نکته: در اینجا از مثال بازی یا انیمیشن Pokemon (پوکمون) در تصویر بالا استفاده می کنیم. در پوکمون شخصیت های مختلفی وجود دارد که یکی از آنها، پوکمن Pikachu (پیکاچو) است (پیکاچو همان شی موردنظر در تصویر است).
چگونه برنامه نویس شویم؟ (9 نکته برای شروع و ورود به بازار کار)
کلاس در OOP
کلاس در OOP چیست؟ این مفهوم را به کمک تصویر بالا و به سادگی معرفی خواهیم کرد.
اگر تصویر بالا را تجزیه و تحلیل کنیم، کلاس، شی، صفات، متدها و یک پیکاچو می بینیم، شاید فکر کنید که اینها چه ربطی به OOP دارند. این تصویر دقیقاً همان چیزی است که برای درک آسانتر مفاهیم OOP به آن نیاز داریم.
خب حالا منظور از کلاس در OOP چیست؟ تعریف فنی و تئوری کلاس این است که: “کلاس مجموعه شی از همان نوع است“. به عبارت ساده تر کلاس چیزی نیست جز مجموعه ای از اشیا با ویژگی های مشترک.
در اینجا برای همه شخصیت های پوکمن یک کلاس به نام “Pokemon” وجود دارد که در تصویر با مستطیل نشان داده شده است.
شی در OOP
یک شی در برنامه نویسی شی گرا در اصل جز سازنده یا یک عضو از کلاس است. در این مثال هر نوع شخصیت پوکمون یک شی از کلاس Pokemon است. به عنوان مثال. شخصیت پیکاچو یک شی از کلاس Pokemon است.
صفات در OOP
در مثال Pokemon روی پیکاچو در تصویر تمرکز کنید. چه چیزهایی می بینید؟
با نگاه به تصویر پیکاچو دو گوش، دو دست، دو پا، دو دایره کوچک قرمز روی گونه ها و یک رنگ زرد متمایز می بینید. علاوه بر آن در جدول کنار پیکاچو هم مواردی مانند Name، Type و Health (به ترتیب نام، نوع و میزان سلامتی) را مشاهده می کنیم. همه اینها به عنوان ویژگی های پیکاچو شناخته می شوند. در واقع صفات در برنامه نویسی شی گرا ویژگی هایی هستند که اطلاعاتی درباره کلاس ها یا اشیا ارائه می دهند. در این مثال این ویژگی ها اطلاعاتی درباره شی پیکاچو مانند رنگ آن، سلامتی، نام و … ارائه می دهند.
متدها در OOP
متدها اعمال مرتبط به یک شی خاص را تعیین می کنند. در این مثال هر پوکمون می تواند اعمالی مانند حمله، حرکت های مختلف و تکامل داشته باشد. در تصویر این اعمال یا اقدامات در قالب متدها در قسمت پایین جدول کلاس Pokemonآمده اند.
به طور کلی هر کلاس از اشیا را را با یک مستطیل حاوی صفات و اعمال آنها نشان می دهند.
تا به اینجا مفاهیم مختلف شی گرایی را به صورت تئوری درک کردیم حالا می خواهیم این مفاهیم را در پایتون به صورت عملی پیاده سازی کنیم.
در این آموزش برای پیاده سازی این مفاهیم از نوت بوک Jupyter در Ubuntu 20.04.2 LTS استفاده می کنیم. البته می توانید از هر سیستم عامل دیگری نیز استفاده کنید زیرا تمام مفاهیمی که اینجا بررسی خواهیم کرد به طور مشابه روی هر پلتفرمی کار می کنند.
پیاده سازی عملی OOP در پایتون
در این بخش نحوه پیاده سازی و کدنویسی مفاهیم OOP را در پایتون توضیح می دهیم.
ایجاد کلاس در پایتون
یک کلاس با نام “Pokemon” در پایتون ایجاد می کنیم.
کد:
class Pokemon():
همانطور که در کد بالا مشاهده می کنید، ساختار خاصی برای ایجاد کلاس در پایتون وجود دارد. با کلمه کلیدی “class” شروع می شود و به این ترتیب پایتون می تواند تشخیص می دهد که می خواهیم در ادامه یک کلاس بنویسیم. پس از کلمه کلیدی “class” نام کلاس نوشته می شود که در این مثال نام کلاس Pokemon است. بعد از آن () می آید و در نهایت با کاراکتر “:” خط دستور به اتمام می رسد.
آیا کلاس ایجاد شد ؟ هنوز نه. باید چند خط کد در زیر کلاس اضافه کنید تا ساخت آن کامل شود.
ایجاد متد __init__ برای کلاس
مرحله بعدی برای ایجاد کلاس، ایجاد متد خاص “__init__” است. ممکنه بپرسید “این متد __init__ چیست و چرا به این نام خوانده می شود؟”. برای درک بهتر این مفهوم، متد init را مشابه با متد main در جاوا در نظر بگیرید. (این متد ربطی به متدهای مرتبط با اعمال شی ندارد و مربوط به خود کلاس است.)
در کد جاوا می توانیم برای هر کلاس یک متد main مرتبط داشته باشیم، همین مفهوم در پایتون نیز وجود دارد. در اینجا به جای “main” به عنوان متد “__init__” شناخته می شود.
نکته: در واقع متد __init__ برای تعریف صفات شی استفاده می شود. هنگام ساخت یک شی جدید از کلاس فراخوانی می شود و تعریف و مقداردهی اولیه صفات را انجام می دهد. به آن سازنده کلاس نیز گفته می شود.
این کد را به کلاس خود اضافه می کنیم.
class Pokemon():
def __init__():
در ایجاد متد __init__ از کلمه کلیدی “def” استفاده شده است. در اصل def یک کلمه کلیدی در پایتون است که به طور خاص در تعریف متد برای یک شی نیز استفاده می شود.
در کد نوشته شده یک چیز دیگر را هم می بینیم، تورفتگی های هر خط. به طور پیشفرض هنگام نوشتن کد، پایتون در خطوط تورفتگی ایجاد می کند. چنبن ترازهای خاص در کد به عنوان “موتور نحو یا Syntax Engine ” شناخته می شود. هدف اصلی این است که کد مرتب و تمیز به نظر برسد.
هنوز تعریف متد ( )__init__ کامل نشده است و نیاز به آرگومان های خاصی (صفات) دارد. این آرگومان ها را به متد اضافه می کنیم.
کد تعریف صفات مربوط به کلاس در متد ( )__init__:
class Pokemon():
def __init__(self,name,Type,health):
self.name = name
self.health = health
متد ( )__init__ دارای 3 آرگومان است. این آرگومان ها (یا پارامترهای ارسالی) همان صفات مرتبط به شی هستند که در متد ( )__init__ هنگام ساخت شی تعریف می شوند.
در ابتدای آموزش گفتیم که پیکاچو دارای رنگ زرد، دو دایره قرمز روی گونه ها و … است. خب اینها در اصل ویژگی ها یا همان صفات شی می باشند. هنگام ساخت یک شی جدید از کلاس، متد ( )__init__ فراخوانی شده و صفات را برای آن شی تعریف کرده و مقدار انها را مشخص می کند، در نتیجه شی جدید با ویژگی های منحصر به خودش ساخته می شود.
در مثال اینجا برای هر شی از کلاس Pokemon سه صفت name، Type و health تعریف می شود، به عنوان مثال پیکاچو یک شی از کلاس Pokemon با نام پیکاچو، نوع الکتریکی و سلامت 120 می تواند می باشد.
self نیز یک کلمه کلیدی است که مسئول اتصال بین این صفات به کلاس است.
ایجاد متدهای کلاس
تا این مرحله از نوشتن کلاس، متد خاص ( )__init__ و صفات را برای کلاس تعریف کردیم. حالا با قسمت نهایی یعنی ایجاد متدها در کلاس آشنا خواهیم شد.
کد ایجاد یک متد در پایتون:
def attack(self):
print(“Electric attack!!.Zhoop!!!”)
در اینجا یک متد به نام ()attack ایجاد کردیم. اگر این قطعه کد را با دقت مشاهده کنید، می بینید که این متد یک آرگومان به نام “self” دارد. همان مهنی را دارد، با استفاده از کلمه کلیدی self متد را به کلاس متصل می شود.
همانطور که در تصویر بالا مشاهده می کنید در کلاس Pokemon سه متد مرتبط به شی وجود دارد: ()attack()، Dodge()، Evolve.
متد ()attack را ساختیم حالا دو متد باقیمانده را در کلاس خود ایجاد می کنیم. با اضافه کردن این متدها، کلاس نهایی Pokemon به شکل زیر خواهد بود:
کد کلاس Pokemon با صفات و متدهای اضافه شده:
class Pokemon():
def __init__(self,name,Type,health):
self.name = name
self.Type = Type
self.health = health
def attack(self):
print(“Electric attack!!.Zhoop!!!”)
def dodge(self):
print(“Pikachu Dodge!”)
def evolve(self):
print(“Evolving to Raichu!!!!”)
ایجاد کلاس تمام شد، مرحله آخر اجرای کد است:
ساخت شی در پایتون
در این قسمت یک نمونه از کلاس ایجاد می کنیم که همان شی است. با این کار می توانیم کد کلاس را هم تست کنیم که آیا به درستی کار می کند یا نه.
کد ساخت شی در پایتون:
pk1 = Pokemon(“Pikachu”,”Electric”,120)
یک شی با نام pk1 از کلاس Pokemon ساختیم.
دسترسی به صفات مرتبط با شی
با استفاده از عملگر نقطه (.) صفات یا ویژگی های مرتبط با شی قابل دسترس خواهد بود.
کد دسترسی به صفت name مرتبط به شی pk1:
pk1.name
خروجی
‘Pikachu’
در کد بالا به ویژگی name مرتبط با شی pk1 دسترسی پیدا کردیم و می توانیم به همین صورت با این مقدار کار کنیم. به همین ترتیب می توانیم به بقیه صفات شی نیز دسترسی پیدا کنیم.
کد دسترسی به صفت Type مرتبط به شی pk1:
pk1.Type
خروجی
‘Electric’
کد دسترسی به صفت health مرتبط به شی pk1:
pk1.health
خروجی
120
دسترسی به متدهای مرتبط با شی
با استفاده از عملگر نقطه می توانیم به متدهای مرتبط با شی نیز دسترسی پیدا کنیم.
کد دسترسی به متد ()attack مرتبط به شی pk1:
pk1.attack()
خروجی
Electric attack!!.Zhoop!!!
کد دسترسی به متد ()evolve مرتبط به شی pk1:
pk1.evolve()
خروجی
Evolving to Raichu!!!!
کد دسترسی به متد ()dodge مرتبط به شی pk1:
pk1.dodge()
خروجی
Pikachu Dodge!
نکته: در اینجا یک نکته مهم وجود دارد که هنگام دسترسی به متدهای مرتبط با شی باید بعد از نام متد() را قرار دهیم.
وراثت در OOP
وراثت یکی از مفاهیم اصلی در برنامه نویسی شی گرا است. به کمک یک مثال ساده این مفهوم را به راحتی توضیح می دهیم.
برای مثال خودرو McLaren 720S را در نظر بگیرید که در اصل یک ابرخودرو است. برای افراد علاقه مند به خودرو کاملا آشنا است.
همانطور که می بینید مثل اکثر خودروهای دیگر برخی از ویژگی های مشترک مانند درب، پنجره جلو، 4 چرخ، چراغ های جلو، چراغ های عقب و … را دارد. با این حال به عنوان یک خودرو خاص، ویژگی های سفارشی دیگری مانند موتور توربوشارژ خاص، جعبه دنده سفارشی ساخته شده توسط مک لارن و یک سیستم سفارشی AWD و .. دارد که آن را از سایر خودروها متمایز کرده است.
حالا این را به مفاهیم ارث بری در شی گرایی مرتبط می کنیم، می توان گفت این خودرو ویژگی هایی از والد خود به ارث می برد که این والد همان خودرو (کلاس خودرو) است و این همان مفهوم وراثت است. در اصل وراثت پدیده ای است که یک عنصری از کلاس والد خود ویژگی بدست می آورد. یعنی اگر یک کلاس به نام کلاس خودرو داشته باشیم، خودرو McLaren 720S علاوه بر داشتن همه ویژگی های مشترک این کلاس (که از آن به ارث می برد) ویژگی های خاصی نیز برای خود دارد. در اینجا کلاس خودرو به عنوان کلاس والد شناحته می شود.
سوپرکلاس و زیر کلاس در شی گرایی
کلاسی که عنصر از آن ارث می برد (در اینجا کلاس Car) به عنوان سوپرکلاس (Superclass) شناخته می شود و ماهیتی عمومی دارد. کلاسی که ویژگی را به ارث می برد به عنوان زیر کلاس (sub-class) شناخته می شود که ماهیت خاص دارد.
حالا این مفاهیم را در پایتون پیاده سازی می کنیم. در اینجا دو کلاس ایجاد خواهیم کرد، یک کلاس به نام “Car” به عنوان سوپرکلاس و یک کلاس به نام “McLaren” که زیر کلاس می باشد. کلاس “McLaren” همه صفات کلاس “Car” را به ارث می برد.
ساخت کلاس “Car” در پایتون:
class Car():
def __init__(self,ndoors,nwheels,tailLight,headLight):
self.nwheels = nwheels
self.tailLight = tailLight
self.headLight = headLight
در اینجا کلاس “Car” را با چهار صفت ایجاد کردیم. (صفات ndoors، ndoors، taillight و headLight به ترتیب برای ویژگی های تعداد درها، تعداد چرخ ها، چراغ عقب و چراغ جلو خودرور در نظر گرفته شده اند.)
حالا زیرکلاس “McLaren” را با همه ویژگی های به ارث برده از کلاس “Car” می سازیم.
ساخت کلاس “McLaren” در پایتون:
class McLaren(Car):
def __init__(self,ndoors,nWheels,tailLight,headLight,Engine,Wheel_Drive):
Car.__init__(self,ndoors,nWheels,tailLight,headLight)
self.Engine = Engine
self.Wheel_Drive = Wheel_Drive
def Drive(self):
print(“I am driving McLaren 720S Spyder”)
همانطور که در کد بالا مشاهده می کنید، برای نشان دادن ارث بری کلاس McLaren از کلاس Car باید هنگام ایجاد کلاس McLaren نام کلاس Car به عنوان یکی از پارامترهای ورودی آن در تعریف زیرکلاس نوشته شود و در اصل این نشان دهنده مفهوم وراثت در پایتون است.
هر شی از کلاس McLaren، چهار صفت از کلاس Car به ارث می برد و دو صفت خاص دیگر به نام های Engine و Wheel_Drive دارد که همه این صفات در تابع __init__ تعریف و مقداردهی اولیه می شوند.
حالا می خواهیم تئوری خود درباره اینکه آیا کلاس McLaren ویژگی های کلاس Car را به ارث می برد یا نه را تست کنیم.
کد ایجاد شی از کلاس McLaren:
mk1 = McLaren(“4″,”4″,”Yes”,”Yes”,”V8″,”AWD”)
سعی می کنیم به صفت خاص Engine در کلاس McLaren دسترسی پیدا کنیم.
کد دسترسی به صفت Engine از کلاس McLaren:
mk1.Engine
خروجی
‘V8’
کد دسترسی به صفت Wheel_Drive از کلاس McLaren:
mk1.Wheel_Drive
خروجی
‘AWD’
توانستیم به ویژگی هایی خاص شی کلاس McLaren دسترسی پیدا کنیم. چون این کلاس از کلاس والد خود یعنی کلاس Car ارث بری می کند، این ویژگی های وراثتی را نیز بررسی می کنیم.
کد دسترسی به صفت headLight:
mk1.headLight
خروجی
‘Yes’
کد دسترسی به صفت ndoors:
mk1.ndoors
خروجی
‘4’
کد دسترسی به صفت nwheels:
mk1.nwheels
خروجی
‘4’
کد دسترسی به صفت tailLight:
mk1.tailLight
خروجی
‘Yes’
همانطور که در اینجا دیدیم، یک شی جدید از کلاس McLaren همه ویژگی های کلاس پایه Car را به ارث می برد و در اینجا وراثت به درستی اجرا می شود.
این همه آن چیزی بود که باید درباره برنامه نویسی شی گرا در پایتون بدانید.
حتما دانلود کنید: آموزش صفر تا صد پایتون+ جزوه PDF
ویدیوی آموزش شی گرایی در پایتون
با تشکر. چقد خوب گفته بودین.
پاسخچقدر خوب و روان توضیح داده بودید ممنون
پاسخاستفاده کردیم