متود، متود استاتیک و متود کلاس در پایتون

در این پست میخوام انواع متودها در پایتون رو معرفی کنم. مفهوم متوددر برنامه سازی شی گرا مفهوم متود معادل با تابعی است که به یک کلاس متصل باشه. در واقع وجود متود یکی از اصلی ترین تفاوت های برنامه نویسی شی گرا و برنامه نویسی غیر شی گراست.انواع متود در پایتوندر پایتون سه نوع متود تعریف میتونه بشه برای هر کلاس: متودهای مرتبط با هر نمونه از کلاس(Instance methods) متودهای ایستا (Static methods) و متودهای کلاس (Class methods)متودهای معمولی (Instance Methods)این رو برای این نوشتم که متودی هست که معمولا همه مون بیشتر باهاش آشنا هستیم و خیلی بیشتر ازش استفاده میکنیم. این نوع متود روی نمونه های اون کلاس قابل صدازدن هست و میتونه حالت اون نمونه رو تغییر بده. مثالی که بخوام بزنم این میشه که فرض کنید داریم یه بازی میسازیم که توش یه سری هیولا قراره داشته باشیم. هر هیولا یه تعداد چشم داره و موقع ساخته شدن تعداد چشماشو معلوم میکنیم ما. حالا هر هیولا میتونه یه سری کارا انجام بده. میتونه آدم بخوره. میتونه شیهه بکشه ( :| ) و ... هر کدوم ازین کارها یه متود معمولی هستن. کدی که براش نوشته میشه به صورت زیر هست:class Monster: def __init__(self, eyes): print('monster with {} eyes created'.format(eyes)) def doShihe(self): print('HEEEEEEEEE!') >>> m = Monster(2) # monster with 2 eyes created >>> m.doShihe() # HEEEEEEEEE!خب این مثال حس میکنم که خیلی معلومه همه چیش که چیکار میکنه. فقط همونطوری که میبینید متودهای معمولی توی پایتون یه پارامتر اجباری self رو میگیرن که در واقع همون نمونه ای هست که اون متود داره روش صدا میزنه. و از همین طریق هست که میتونن حالته های اون نمونه از کلاس رو تغییر بدن. از طریق self. نکته جالبی که میتونم اضافه کنم اینه که اسم self صرفا یه اسم هست و میتونیم اگه خواستیم با اسم دیگه ای عوضش کنیم، مثل this توی ++c و یا هر اسمی که بخوایم ولی خب میدونیم که بهتره این کارو نکنیم.متودهای ایستا (Static Methods)این نوع متود هم متود پر کاربردی هست چه توی سایر زبان ها و چه توی زبان پایتون. متودهای ایستا کاری که میکنن اینه که معمولا ما اون ها رو وابسته به خود اون کلاس در نظر میگیریم تا وابسته به نمونه های اون کلاس. مثالهایی که میتونم بزنم مثلا اینکه توی همین مثال هیولای خودمون که زدیم فرض کنید ما هیولاهایی داریم که دو چشم دارن یا بعضیاشون یه چشم دارن و ما میخوایم ببینیم که میانگین تعداد چشمای اینا چنتاس. خب این درست نیس که بریم از یه دونه ازین هیولاها بپرسیم که میانگین چشمای هیولاها چنتاس. به جاش میتونیم بریم از کلاس هیولا بپرسیم که میانگین چشمای هیولاهات چنتاس که خب اگه بخوایم واقعا اینو پیاده سازی کنیم باید از یه فیلد ایستا هم استفاده کنیم که تعداد چشم ها و تعداد هیولاهایی که تا الان ساخته شده رو نگه داره و بعد این دو تا رو تقسیم کنیم به هم ولی خب اینجا سخنو سر راست میکنم و یه مثال ساده میارم:class Monster: ... @staticmethod def getMeanEyes(): return 1.5 >>> m = Monster(1) # monster with 1 eyes created >>> m.getMeanEyes() # 1.5 >>> Monster.getMeanEyes() # 1.5همون طور که میبینید متود getMeanEyes با یک دکوراتور، تزیین شده که همون staticmethod@ رو منظورم هست. نکته دومی که لازمه بگم اینه که همونطور که میبینید متود ایستا هم روی خود اون نمونه صدا زده شده و هم روی خود کلاس و این کار در پایتون قابل انجام هست.نکته سوم اینکه متود ایستا نه میتونه حالت های کلاسو تغییر بده و نه میتونه حالت های اون نمونه ای که روش صدا زده شده رو تغییر بده. انگار صرفا مثل یه نوع تابع متصل به اون کلاس میمونه که باعث خوانا شدن بیشتر کد میتونه بشه.متود کلاس (Class Methods)متودهای کلاس در پایتون تفاوتشون با متودهای ایستا اینه که میتونن به خود کلاس دسترسی داشته باشن اما دوباره مثه متودهای ایستا اونا هم نمیتونن به نمونه های اون کلاس دسترسی داشته باشن. مثالی که میتونم اینجا بزنم فرض کنید که مثلا ما به هیولایی که تعداد چشماش یه دونه باشه میگیم هیولای تک چشم و هیولای دو چشم رو میگیم هیولای معمولی. میشه متودی ساخت که با صدا زدنش اون نوع هیولا رو برامون بسازه:class Monster: ... @classmethod def uniEyed(cls): return cls(1) @classmethod def regular(cls): return cls(2) >>> Monster.uniEyed() # monster with 1 eyes created >>> Monster.regular() # monster with 2 eyes created نکاتی که میتونید ببینید دوباره :وجود دکوراتور classmethod@ هست ورودی اجباری cls که به معنی همون کلاس هست.در تکه کد بالا همونطور که دیدید متودهای کلاس قابلیت دسترسی به خود کلاس رو دارند.به متود پیاده سازی شده در این مثال اصطلاحا متود کارخانه (Factory) گفته میشه.جمع بندیمتودهای معمولی به یک ورودی اجباری نیاز دارند که همان نمونه از آن کلاس است(پارامتر self) و میتونند از این طریق حالت اون نمونه رو تغییر بدن.متودهای کلاس نمیتونن حالت نمونه ها رو تغییر بدن ولی به خود کلاس دسترسی دارند و میتونند حالت های اون کلاسو تغییر بدن (از طریق پارامتر اجباری cls)متودهای ایستا نه به کلاس و نه به نمونه های اون کلاس دسترسی ندارند و مثه تابعای معمولی میمونند که به فضای نامی(namespace) اون کلاس تعلق دارند.برگرفته از کتاب Python Tricks - Dan Bader