خب بخش مهمی که باید بیشتر توجه داشت همین بخش هست پس توصیه ایمنی را جدی گرفته مراقبه خودتون باشید به این بخش خوب گوش جان بسپارید
این جایی است که ما از کلاس برای تعریف برنامه استفاده میکنیم به طوری که هر شی از همان نوع کلاس دارای ویژگیهای یکسان باشد.
پایتون وظایف ویژهای را برای کلاس ها ، که به وسیله پسوند ها و پیشوند ها که با علامت "_" هستند، فراهم میکند
پایتون یک تابع مخصوص به نام __init__ را ارایه میدهد که هر زمان که ما یک نمونه از یک کلاس بسازیم و این تابع برای ایجاد طرح کلی شی استفاده میشود و ابتدای نمونه سازی از کلاس اجرا خواهد شد درست مانند تابع constructor یا construct به ترتیب در زبان های php , js
تابع __init__ هر زمان که یک شی ایجاد میشود فراخوانی میشود. تابع به یک پارامتر اجباری نیاز دارد که با کلمه "self" فراخوانی میشود. در اینجا "self" به خود شی ساخته شده از روی کلاس اشاره میکنه
مثال 1-1
class PostalAddress: def __init__(self): pass
در داخل این تابع __init__ ، ما متغیرهای نمونه محلی را ایجاد می کنیم که حالت (ویژگی های قابل شناسایی) شیء ساخته شده از این کلاس را تعریف می کنند. مانند خط 3 و 4
مثال 2-1
1 class PostalAddress: 2 def __init__(self): 3 self.name = "ABC" 4 self.street = "Central Street - 1" 5 cP1 = PostalAddress() 6 print(cP1.__dict__) # {'street': 'Central Street - 1', 'name': 'ABC'}
عبارت "self" یک کلمه کلیدی در پایتون نیست، این یک عرف در برنامه نویسی پایتون است که از واژه"self" به عنوان یک مرجع برای دسترسی به شی ساخته شده از کلاس استفاده میکنیم، با این حال، ما میتوانیم آن را هر چیزی که میخواهیم، برای مثال، نامگذاری کنیم.
مثال 3-1
class PostalAddress: def __init__(theClassInstance): theClassInstance.name = "ABC" theClassInstance.street = "Centeral Street - 1"
ولی روش بهتر برای استفاده همان عبارت "self" که دیگر برنامه نویسان منظور شما متوجه خواهند شد
توابع در کلاس، جنبه رفتاری آن شی را فراهم میکنند. اجازه دهید فقط یک تابع برای چاپ حالت فعلی شی ایجاد کنم. تابع را prnInfo مینامند
مثال 4-1
1class PostalAddress: 2 def __init__(self): 3 self.name = "ABC" 4 self.street = "Centeral Street - 1" 5 def prnInfo(self): 6 print("Name => ", self.name, " Street =>", self.street) 7 cP1 = PostalAddress() 8 cP1.prnInfo() #Name => ABC Street => Centeral Street - 1
دقیقاً مانند عملکرد __init__ ، تمام توابع خود را به عنوان یک پارامتر اجباری می گیرند. با این حال ، هنگامی که ما این تابع را فراخوانی می کنیم یعنی تابع "prnInfo" در خط 8 ، هیچ پارامتری را به آن منتقل نمی کنیم زیرا پایتون نمونه شی را به صورت خودکار می گیرد. به عبارتی به خط های 3 و 4 اشاره میکنیم
ما همچنین می توانیم به جای یک شیء ، توابع را با استفاده از کلاس فراخوانی کنیم ، اما اگر بخواهیم متد را از طریق کلاس فراخوانی کنیم با این حال، اگر میخواهیم متد را از طریق کلاس ، فراخوانی کنیم. باید شی ساخته شده از کلاس را به تابع "prnInfo" معرفی کنیم ، پایتون نمیداند که کدام یک به عنوان "self" عمل میکند.
فراخوانی با استفاده از کلاس به شکل زیر است: خط های 1 و 3
مثال 5-1
1 cP1 = PostalAddress()
# Calling the function using class, we provide the instance 2 PostalAddress.prnInfo(cP1)
# This is same as 3 cP1.prnInfo()
تا اینجای کار کلاس PostalAddress شبیه همان شی های استاتیک بود، زیرا ما نام و خیابان را در داخل تابع "__init__" مقدار دهی کردیم. با این حال، ما میخواهیم اشیا نمونه دیگری با مقادیر مختلف بسازیم.
این مقادیر را به عنوان پارامترهای ورودی در تابع init در نظر بگیرید که در کد زیر نشانداده شدهاست:
مثال 6-1
# PostalAddress taking name and street as input parameter class PostalAddress: def __init__(self, name, street): self.name = name self.street = street def prnInfo(self): print("Name => ", self.name, " Street =>", self.street) cP1 = PostalAddress("ABC", "Central Street - 1") cP1.prnInfo() cP2 = PostalAddress("DEF", "Central Street - 2") cP2.prnInfo()
خب ما میتونیم به پارامتر های تابع __init__ مقادیر پیش فرض بدهیم که بعدا در هنگام فراخوانی درصورت فراموشی مقدار دهی به شی ، ان مقدار پیش فرض جایگزین شود که از بروز خطا جلوگیری کند در خط 2
مثال 7-1
1 class PostalAddress: 2 def __init__(self, name = "Default Name", street = "Central Street - 1"): 3 self.name = name 4 self.street = street 5 cP0 = PostalAddress(); # 0 arguments 6 cP1 = PostalAddress("ABC") # 1 argument 7 cP2 = PostalAddress("DEF", "Central Street - 2") # 2 arguments
ایجاد نمونه متغیرها در توابع چندگانه
این معنی نیست که ما فقط میتوانیم متغیرهای مورد نظر را فقط درون تابع__init__ ایجاد کنیم. ما میتوانیم همین کار را در هر یک از اعضای کلاس انجام دهیم.
تنها مشکل این است که آن متغیرها تنها زمانی ایجاد خواهند شد که تابع ایجاد متغیر نمونه فراخوانی میشود. اشاره به خط 5 و 6 و فراخوانی در خط 9
مثال 8-1
1 class PostalAddress: 2 def __init__(self, name = "Default Name", street = "Central Street - 1"): 3 self.name = name 4 self.street = street 5 def createMember(self): 6 self.newMember = "Temporary Value" 7 cP0 = PostalAddress(); 8 print(cP0.__dict__); # prints {'name': 'Default Name', 'street': 'Central Street - 1'} 9 cP0.createMember(); 10 print(cP0.__dict__); # print {'name': 'Default Name', 'street': 'Central Street - 1', 'newMember': 'Temporary Value'}
متغیرهای کلاس
اغلب اوقات، آدرسهای افراد در یک جامعه کوچک، برخی از اطلاعات مشترک برای مثال کد پستی را به اشتراک میگذارند.
این به این معنی است که تمام اشیا کلاس PostalAddress باید کد پستی یکسانی داشته باشند
یك راه برای دستیابی به این هدف نوشتن كد پستی در متد __init__ به گونه ای است كه در هر شیء ایجاد شده از این کلاس در دسترس باشد.
مثال 9-1
class PostalAddress: def __init__(self, name = "Default Name", street = "Central Street - 1"): self.name = name self.street = street self.postalcode = 12345 # Hardcoding Postal Code cP0 = PostalAddress(); print(cP0.__dict__); # prints {'postalcode': 12345, 'name': 'Default Name', 'street': 'Central Street - 1'} cP1 = PostalAddress("ABC") print(cP1.__dict__); # prints {'postalcode': 12345, 'name': 'ABC', 'street': 'Central Street - 1'}
با این حال، اگر بخواهیم بعد کد پستی را تغییر دهیم، این یک مشکل است. تنها راه برای انجام این کار، تغییر دستی برای هر شی است،
مثال 10-1
cP0.postalcode = 54321 cP1.postalcode = 54321 ... ... cPn.postalcode = 54321
این کار نه تنها خسته کننده نیست بلکه راه را برای بروز اشتباهات هموار میکند پس راه کار چیست؟
خوشبختانه، ما میتوانیم متغیرهای کلاس داشته باشیم که در این موارد میتوانند به روز شوند
class variable یک متغیر است که نه در داخل متدهای موجود کلاس تعریف نمیشود بلکه در سطح بدنه کلاس تعریف می شود
این متغیر در کلیه نمونه های PostalAddress در دسترس است بیایید ببینیم چگونه می توانیم متغیرهای کلاس را تعریف کنیم
مثال 1-2
class PostalAddress: postalCode = 12345; # class Variable def __init__(self, name = "Default Name", street = "Central Street - 1"): self.name = name self.street = street cP0 = PostalAddress() print(cP0.postalCode) # print 12345
قبل از اینکه به راههایی برای تغییر متغیر کلاس نگاهی بیندازیم به گونهای که هر نمونه از کلاس با postalCode جدید به روز میشود، ما نیاز به درک یک تفاوت عمده بین متغیرهای کلاس و متغیرهای نمونه داریم. class variable به عنوان بخشی از کلاس تعریف می شوند و به عنوان نمونه نیستند
اگر ما دستور "__cP0.__dict" را اجرا کنیم "کد پستی" را در آنجا پیدا نمی کنیم.
مثال 2-2
print(cP0.__dict__) # prints {'street': 'Central Street - 1', 'name': 'Default Name'}
برای یافتن "کد پستی" ، باید از خود کلاس متغیرش را فراخوانی کنیم نه از شی ساخته شده از کلاس
مثال 3-2
print(PostalAddress.__dict__) # prints {'postalCode': 12345. .... } amongst many other things
این توالی جستجوی پایتون است که ابتدا به "نمونه" نگاه میکند، و اگر تابع / عملکرد پیدا نشود، به "کلاس" نگاه میکند. به همین دلیل است که ما میتوانیم cP۰.postalCode را با استفاده از شی نمونه چاپ کنیم.
روش کلاس
متغیرهای کلاس را می توان به دو روش یا با استفاده از خود کلاس یا با استفاده از تابع کلاس تغییر داد. برای تغییر استفاده از خود کلاس، باید کد زیر را بنویسیم
مثال 4-2
PostalAddress.postalCode = 54321
با این کار "کد پستی" نه تنها برای موارد موجود ، بلکه برای تمام مواردی که پس از اجرای این خط ایجاد می شود ، تغییر خواهد کرد.
مثال 5-2
# Instance created BeforecP0 = PostalAddress() cP1 = PostalAddress() PostalAddress.postalCode = 54321 # Instance created after changecP2 = PostalAddress() print(cP0.postalCode) # prints 54321 print(cP1.postalCode) # prints 54321 print(cP2.postalCode) # prints 54321
راه دیگر برای دستیابی به نتیجه مثال بالا class method ها در پایتون است متد ()classmethod یک روش کلاس را برای عملکرد مشخص داده است. شما میتوانید برای شی های ساخته شده از کلاس به مقدار class variable دسترسی داشته و آنرا تغییر دهید. cls در خط 7 خیلی شبیه به "self" عمل میکند. در حالی که روش کلاس تعیینکننده است، ما باید به وضوح به زبان پایتون بگوییم که این روش یک روش کلاسی است که از کلمه کلیدی استفاده میکند.classmethod@ یعنی در خط 6
مثال 6-2
1 class PostalAddress: 2 postalCode = 12345; # class Variable 3 def __init__(self, name = "Default Name", street = "Central Street - 1"): 4 self.name = name 5 self.street = street 6 @classmethod 7 def newPostalCode(cls, newcode): 8 cls.postalCode = newcode
خب در" Instance methods" کلمه ,"self" را به عنوان پارامتر اجباری می گیرند ، در حالی کهClass methods کلمه "class" را به عنوان پارامتر اجباری می گیرند.
در هر دو مورد ، لازم نیست که ما صراحتا از Instance or Class عبور کنیم ، پایتون به طور خودکار از آن مراقبت می کند.
اکنون می توانیم این روش جدید newPostalCode را از طریق Instance یا از طریق Class فراخوانی کنیم. در هر دو مورد ، نتیجه نهایی یکسان خواهد بود. در اینجا نحوه استفاده ما از روش Instance استفاده میکنیم
مثال 7-2
cP0 = PostalAddress() cP1 = PostalAddress()# Call using Instance PostalAddress.newPostalCode(9999) cP2 = PostalAddress() print(cP0.postalCode) # prints 9999 print(cP1.postalCode) # prints 9999 print(cP2.postalCode) # prints 9999
به پایان آمد این دفتر حکایت همچنان باقی است :)