سازنده (Constructor)

سازنده‌، متد خاصی است که وجود آن برای ساخت اشیا لازم است. سازنده‌ به شما اجازه می‌دهند که مقادیری را به هر یک از فیلدها اختصاص دهید و کدهایی که را که می‌خواهید هنگام ایجاد یک شیء اجرا شوند را به برنامه اضافه کنید. فیلد در اصل متغیری است که در داخل کلاس تعریف می شود. اگر از هیچ سازنده‌ای در کلاستان استفاده نکنید، مفسر از سازنده پیشفرض که یک سازنده بدون پارامتر است استفاده می‌کند. برای تعریف سازنده از متد جادویی __init__ به صورت زیر استفاده می شود :

def __init__(self):
    code to execute

در مثال زیر یک کلاس که شامل سازنده است را مشاهده می‌کنید:

  1: class Person: 
  2: 
  3:     #Constructor that has 3 parameters                
  4:     def __init__(self, n = "", a = 0, h = 0): 
  5:         self.name   = n;                     
  6:         self.age    = a;                     
  7:         self.height = h;                     
  8: 
  9:     def ShowInformation(self):
 10:         print("Name: {0}".format(self.name));         
 11:         print("Age: {0} years old".format(self.age)); 
 12:         print("Height: {0}cm".format(self.height));   
 13:            
 14: firstPerson  = Person();                              
 15: firstPerson.name   = "Jack";    
 16: firstPerson.age    = 21;        
 17: firstPerson.height = 160;       
 18: firstPerson.ShowInformation();  
 19:                                 
 20: print(); #Seperator             
 21: 
 22: secondPerson = Person("Mike", 23, 158);               
 23: secondPerson.ShowInformation(); 
Name: Jack
Age: 21 years old
Height: 160cm

Name: Mike
Age: 23 years old
Height: 158cm

در خطوط 12-1 کد بالا یک کلاس ایجاد شده است. در خطوط 7-4 یک سازنده را با استفاده از متد جادویی __init__ ایجاد کرده ایم. همانطور که قبلا اشاره شد، یکی از راه هایی که ما مجبور نباشیم، به متدی که دارای پارامتر است آرگومانی ارسال کنیم، استفاده از پارامترهای پیشفرض است. ما در خط 4، سه آرگومان به نام های n ،a و h ایجاد و سه مقدار ثابت به آنها داده ایم. این سه مقدار، به سه فیلد age ،name و height اختصاص داده می شوند. اگر نمونه‌ای ایجاد کنیم، نمونه ایجاد شده مقادیر پیشفرض را نشان می‌دهد. برای درک بهتر موقتا خطوط 23-14 کد بالا را حذف کرده و کدهای زیر را نوشته و برنامه را اجرا کنید:

firstPerson  = Person();                                  
firstPerson.ShowInformation();

برای اختصاص مقدار به فیلدهای کلاس دو راه وجود دارد. اولین روش این است که یک شیء از کلاس ایجاد کرده و بعد علامت نقطه می گذاریم و در نهایت نام فیلد را نوشته و به وسیله علامت مساوی یک مقدار به آن اختصاص می دهیم. کاری که در خطوط 18-4 انجام داده ایم.
به این نکته توجه کنید که هر تعداد پارامتر که در متد سازنده ایجاد کنید باید هنگام ایجاد شیء از کلاس و در داخل پرانتزهای جلوی نام کلاس، آرگومانهایی برای این پارامترها در نظر بگیرید. یعنی ما می بایست در خط 14 و در داخل پرانتزها 3 آرگومان برای سه پارامتر a، n و h در نظر می گرفتیم. ولی چون در خط 4، ما از پارامترهای پیشفرض استفاده کرده ایم، لازم نیست در خط 14 آرگومانی ارسال کنیم. در عوض این کار را در خطوط 17-15 انجام داده ایم. یعنی صراحتا در این خطوط اعلام کرده ایم که سه متغیر age ،name و height شیء firstPerson دارای چه مقادیری باشند. همانطور که مشاهده می‌کنید لازم است که به فیلدهای شی، مقادیری اختصاص داده شود تا این شی نیز با فراخوانی متد ShowInformation() آن‌ها را نمایش دهد.

روش دوم هم این است که در داخل پرانتزهای نام کلاس، سه آرگومان برای پارامترهای a، n و h ارسال کرده تا به سه متغیر age ،name و height اختصاص داده شوند. این کار را در خط 22 انجام داده ایم. مشاهده می‌کنید که با فراخوانی متد ShowInformation() همه چیز همانطور که انتظار می‌رود اجرا می‌شود. این بدین دلیل است که شما هنگام تعریف نمونه و از قبل مقادیری به هر یک از فیلدها اختصاص داده‌اید بنابراین آنها نیاز به مقدار دهی مجدد ندارند مگر اینکه شما بخواهید این مقادیر را اصلاح کنید.

در کد بالا و در خط 4، همانطور که مشاهده می کنید، ما از پارامترهای پیشفرض استفاده کردیم. این کار باعث می شود که ما بتوانیم هم اشیایی از کلاس ایجاد کنیم که آرگومانهای متفاوتی به سازنده ارسال کنند. به کد زیر توجه کنید:

  1: class Person: 
  2: 
  3:     #Constructor that has 3 parameters                  
  4:     def __init__(self, n = "No Name", a = 0, h = 0): 
  5:         self.name   = n;   
  6:         self.age    = a;    
  7:         self.height = h; 
  8: 
  9:     def ShowInformation(self):
 10:         print("Name: {0}".format(self.name));           
 11:         print("Age: {0} years old".format(self.age));   
 12:         print("Height: {0}cm\n".format(self.height));     
 13:            
 14: firstPerson  = Person();
 15: secondPerson = Person("Jack");          
 16: thirdPerson  = Person("Mike", 23);       
 17: fourthPerson = Person("Chris", 18, 152);
 18:                                        
 19: firstPerson.ShowInformation();
 20: secondPerson.ShowInformation();                    
 21: thirdPerson.ShowInformation();                     
 22: fourthPerson.ShowInformation();
Name: No Name
Age: 0 years old
Height: 0cm

Name: Jack
Age: 0 years old
Height: 0cm

Name: Mike
Age: 23 years old
Height: 0cm

Name: Chris
Age: 18 years old
Height: 152cm

ما چهار شیء کلاسمان تعریف کرده‌ایم (خطوط 17-14). به اولین شیء (خط 14) هیچ آرگومانی اختصاص داده نشده است در نتیجه مقادیر پیشفرض به فیلدها از طریق سازنده اختصاص می یابد. دومین شیء یک آرگومان که رشته Jack است به سازنده ارسال می کند. این آرگومان به فیلد name اختصاص می یابد. و بقیه فیلدها با مقادیر پیشفرض پر می شوند. بقیه اشیاء هم به ترتیب 2 و 3 آرگومان قبول می کنند و جایگزین فیلدهای مربوطه می شوند. یکی از موراد استفاده از کلمه کلیدی self به صورت زیر است. فرض کنید نام پارامترهای متد کلاس شما یا سازنده، شبیه نام یکی از فیلدها باشد.

def __init__(name, age, height):
   name   = name;
   age    = age;
   height = height;

این نوع کدنویسی ابهام بر انگیز است و مفسر نمی‌تواند متغیر را تشخیص داده و مقداری به آن اختصاص دهد. اینجاست که از کلمه کلیدی self استفاده می‌کنیم.

def __init__(name, age, height):
   self.name   = name;
   self.age    = age;
   self.height = height;

قبل از هر فیلدی کلمه کلیدی self را می‌نویسیم و نشان می‌دهیم که این همان چیزی است که می‌خواهیم به آن مقداری اختصاص دهیم. کلمه کلیدی self نشان دهنده شیء جاریست.