کار کردن با کلاسها و نمونهها
میتوانید از کلاسها برای بیان بسیاری از شرایط در دنیای واقعی استفاده کنید. پس از این که کلاس را نوشتید، وقت زیادی صرف کار کردن با نمونههایی میکنید که از آن کلاس ساختهاید. یکی از اوّلین کارهایی که میخواهید انجام دهید تغییر دادن مشخّصههای یک نمونهی خاص است. شما میتوانید مشخّصههای یک نمونه را به طور مستقیم یا از طریق نوشتن متدهای ویژهای تغییر دهید.
کلاس Car
بیایید کلاس جدیدی بنویسیم که نمایانگر یک خودرو باشد. کلاس ما اطّلاعاتی دربارهی نوع خودرویی که با آن کار میکنیم ذخیره میکند و متدی دارد که این اطّلاعات را خلاصه میکند:
|
|
متد __init__() را با پارامتر ابتدایی self تعریف میکنیم. همچنین سه پارامتر دیگر به آن میدهیم: make، model و year. متد __init__() این پارامترها را میگیرد و آنها را به مشخّصههایی که با نمونههای ساختهشده از این کلاس در ارتباطند، نسبت میدهد. زمانی که نمونهی جدیدی از کلاس Car میسازیم باید نام شرکت سازنده، مدل و سال ساخت آن را برای نمونهی خود تعیین کنیم.
متدی به نام get_descriptive_name() تعریف میکنیم که year، make و model را در یک رشته قرار میدهد که خودرو را با سادگی و آراستگی توصیف میکند. این متد ما را از چاپ کردن جداگانهی مقدار هر مشخّصه خلاص میکند. برای کار کردن با مقادیر مشخّصههای در این متد از self.make، self.model و self.year استفاده میکنیم. نمونهای از کلاس Car میسازیم و آن را به متغیّر my_new_car نسبت میدهیم. سپس get_descriptive_name() را فراخوانی میکنید تا نوع خودروی ما را مشخّص کند:
|
|
برای جالبتر کردن کلاس، مشخّصهای به آن اضافه میکنیم که با زمان تغییر کند. این مشخّصه مسافت پیموده شدهی کلّی خودرو را ذخیره میکند.
تعیین کردن مقداری پیشفرض برای یک مشخّصه
میتوان هنگامِ ساختنِ یک نمونه، مشخّصهای را بدون انتقال آن به صورت پارامتر تعریف کرد. این مشخّصهها میتوانند در متد __init__() تعریف شوند و در آنجا به آنها مقداری پیشفرض داده شود.
مشخّصهای به نام odometer_reading اضافه میکنیم که همیشه در ابتدا مقدار ۰ دارد. همچنین متدی به نام read_odometer() اضافه میکنیم که ما را در خواندن مقدار کیلومترشمار هر خودرو کمک میکند:
|
|
این بار پایتون برای ساختن نمونهی جدید متد __init__() را فرامیخواند که مقدار سازنده، مدل و سال را مانند مثال قبلی به عنوان مشخّصه ذخیره میکند. سپس پایتون مشخّصهای جدید به نام odometer_reading میسازد و به آن مقدارِ اوّلیّهی ۰ میدهد. همچنین متد جدیدی به نام read_odometer() دارید که خواندن کارکرد خودرو را ساده میکند.
کارکرد خودروی ما در ابتدا ۰ است:
تمام خودروها با کارکرد اوّلیّهی دقیقاً ۰ فروخته نمیشوند پس نیاز به روشی داریم تا مقدار این مشخّصه را تغییر دهیم.
تغییردادن مقدار مشخّصهها
مقدار یک مشخّصه را میتوانید به سه روش عوض کنید: تغییر دادن مستقیم از طریق یک نمونه، تعیین کردن مقدار از طریق یک متد یا افزایش دادن مقدار (افزودن مقداری به آن) به کمک یک متد. به هر یک از این رویکردها نگاهی میاندازیم.
تغییر دادن مستقیمِ مقدار یک مشخّصه
سادهترین راه برای تغییرِ مقدارِ یک مشخّصه این است که از طریق یک نمونه به طور مستقیم به آن دسترسی پیدا کنیم. اینجا مقدار کیلومترشمار را به طور مستقیم ۲۳ قرار میدهیم:
از نماد نقطه برای دسترسی به مشخّصهی odometer_reading خودرو استفاده کرده و مقدار آن را به طور مستقیم تعیین میکنیم. این خط به پایتون میگوید که نمونهی my_new_car را بگیر، مشخّصهی odometer_reading مربوط به آن را پیدا کن و مقدار آن را برابر با ۲۳ بگذار:
گاهی میخواهید مانندِ اینجا به مشخّصهها به طور مستقیم دسترسی پیدا کنیم امّا برخی اوقات متدی مینویسید که مقدار را برای شما بهروز کند.
تغییر دادن مقدار یک مشخّصه از طریق یک متد
داشتنِ متدهایی برای بهروزرسانی مشخّصههای خاصّی میتواند سودمند باشد. میتوانید به جای دسترسی مستقیم به مشخّصه، مقدار جدید را به متدی بدهیم که به صورت داخلی این بهروزرسانی را انجام میدهد.
مثالِ اینجا متدی به نام update_odometer() را نشان میدهد:
|
|
تنها تغییرِ ایجادشده در Car افزوده شدنِ update_odometer() است. این متد مقدار کارکرد را گرفته و به مشخّصهی self.odometer_reading نسبت میدهد. update_odometer() را فراخوانی میکنیم و مقدار ۲۳ را به عنوان نشانوند به آن میدهیم (که به پارامتر mileage در تعریفِ متد مربوط است.) این متد مقدار کیلومترشمار را ۲۳ میکند و read_odometer() این مقدار را چاپ میکند:
میتوانیم متد update_odometer() را طوری گسترش دهیم که در هر بار تغییرِ مقدارِ کیلومترشمار، کاری انجام دهد. اجازه دهید منطقی کوچکی اضافه کنیم تا مطمئن شویم هیچکس مقدار کیلومترشمار را به عقب برنمیگرداند:
|
|
اکنون update_odometer() پیش از تغییر دادنِ مشخّصه، مقدار جدید را بررسی میکند. اگر کارکرد جدید، mileage، بزرگتر یا مساوی کارکرد فعلی (self.odometer_reading) باشد، میتوانید مقدار فعلی کیلومترشمار را به مقدار جدید بهروزرسانی کنید. اگر مقدار جدید کمتر از مقدار فعلی باشد، اخطاری دریافت میکنید مبنی بر این که نمیتوانید مقدار کیلومترشمار را به عقب برگردانید.
افزایش مقدار مشخّصه از طریق یک متد
گاهی میخواهید به جای تعیین یک مقدار کاملاً جدید برای یک مشخّصه، مقدار آن را به میزان مشخّصی افزایش دهید. فرض کنید خودرویی کارکرده خریدهایم و در فاصلهی بین خریدن و سند زدن، ۱۰۰ مایل کار کرده است. متدی که اینجاست مقدار افزایشی را دریافت کرده و آن را به مقدار فعلی کیلومترشمار اضافه میکند:
|
|
متد جدید increment_odometer() تعداد مایل پیمودهشده را گرفته و آن را به self.odometer_reading اضافه میکند. یک خودروی کارکرده، my_used_car، ایجاد میکنیم. مقدار کیلومترشمار آن را با فراخوانی update_odometer() و انتقال مقدار 23_500 به آن، ۲۳،۵۰۰ میگذاریم. سپس increment_odometer() را صدا کرده و مقدار 100 را به آن میدهیم تا ۱۰۰ مایل پیمودهشده بین خریدن و ثبت خودرو را اضافه کند:
میتوانیم به سادگی این متد را تغییر دهیم تا افزودن مقدارهای منفی را نپذیرد تا هیچکس نتواند از این تابع برای کم کردن مقدار کیلومترشمار استفاده کند.
خودآزمایی
۹-۴. تعداد مشتریها: از برنامهی خود در تمرین ۹-۱ شروع کنید. مشخّصهای به نام number_served با مقدار پیشفرض ۰ اضافه کنید. نمونهای به نام restaurant از این کلاس بسازید. تعداد مشتریهایی را که رستوران پذیرای آنها بوده چاپ کنید و سپس با تغییر این مقدار آن را دوباره چاپ کنید.
متدی به نام set_number_served() اضافه کنید که امکان تعیین تعداد مشتریها را فراهم میآورد. این متد را با عدد جدیدی فراخوانی کنید و مقدار را دوباره چاپ کنید.
متدی به نام increment_number_served() اضافه کنید که به شما امکان افزایش تعداد مشتریها را میدهد. این متد را با هر عددی که دوست دارید فرابخوانید که بیانگر تعداد مهمانهای پذیرفتهشده در یک روز کاری باشد.
۹-۵. تعداد تلاشها برای ورود: مشخّصهای به نام login_attempts به کلاس User در تمرین ۹-۳ اضافه کنید. متدی به نام increment_login_attempts() بنویسید که مقدار login_attempts را یکی افزایش میدهد. متد دیگری به نام reset_login_attempts() بنویسید که مقدار login_attempts را صفر میکند.
نمونهای از کلاس User بسازید و increment_login_attempts() را چندین بار صدا کنید. مقدار login_attempts را چاپ کنید تا مطمئن شوید مقدار آن افزایش یافته است و سپس reset_login_attempts() را فراخوانی کنید. مقدار login_attempts را بار دیگر چاپ کنید تا مطمئن شوید مقدار آن صفر شده است.