ساخت پروژه ۱: مغز برنامه (کلاس Shop)
- کلاس
Shopرا با همهی متدها خودت بنویسی - هر قدم را با تست خودکار چک کنی
- ذخیره و بارگذاری JSON را به کلاس اضافه کنی
- در آخر کل کلاس را یکجا و بدون نگاه بنویسی
نقشهی کار
برنامه دو نیمه دارد: مغز (کلاس Shop که داده را نگه میدارد و قانونها را چک میکند) و صورت (پنجره، فرم، دکمهها و جدول). مغز به پنجره هیچ ربطی ندارد، پس میشود آن را همینجا در مرورگر ساخت و با تست خودکار چک کرد. درس بعد صورت را در VS Code میسازی.
| قدم | چه میسازی | خطهای پروژه |
|---|---|---|
| ۱ | اسکلت کلاس و سازنده | خط ۸ پروژه–خط ۱۲ پروژه |
| ۲ | add با چک ورودی | خط ۲۸ پروژه–خط ۳۴ پروژه |
| ۳ | edit و delete | خط ۳۶ پروژه–خط ۴۸ پروژه |
| ۴ | sell و report | خط ۵۰ پروژه–خط ۶۳ پروژه |
| ۵ | save و load با JSON | خط ۱۴ پروژه–خط ۲۶ پروژه |
| ۶ | همه با هم، از حفظ | — |
در هر قدم کد قدم قبل آماده گذاشته شده تا فقط روی قسمت جدید تمرکز کنی. save و load تا قدم ۵ خالی (pass) میمانند.
قدم ۱: اسکلت
قدم ۱ — سازنده
کلاس Shop بنویس که سازندهاش self.products را دیکشنری خالی و self.sales را لیست خالی بگذارد و بعد self.load() را صدا بزند. save و load فعلاً pass هستند.
دیدن راهحل (اول خودت تلاش کن)
class Shop: def __init__(self): self.products = {} self.sales = [] self.load() def save(self): pass # قدم ۵ def load(self): pass # قدم ۵
قدم ۲: افزودن کالا
قانونها: نام نباید خالی یا تکراری باشد؛ هر سه عدد باید بین صفر و بینهایت باشند (nan و inf قبول نیست). بعد از ثبت، self.save().
قدم ۲ — add
متد add(self, name, buy, sell, qty) را اضافه کن. خطاها ValueError باشند.
راهنمایی
از if not name or name in self.products: و if not all(0 <= x < float('inf') for x in (buy, sell, qty)): استفاده کن.
دیدن راهحل (اول خودت تلاش کن)
class Shop: def __init__(self): self.products = {} self.sales = [] self.load() def save(self): pass # قدم ۵ def load(self): pass # قدم ۵ def add(self, name, buy, sell, qty): if not name or name in self.products: raise ValueError('نام خالی یا کالای تکراری است') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save()
قدم ۳: ویرایش و حذف
قدم ۳ — edit و delete
edit مثل add است با این فرق که کالا باید وجود داشته باشد. delete(self, name) کالای موجود را با del حذف کند. هر دو در آخر save کنند.
دیدن راهحل (اول خودت تلاش کن)
class Shop: def __init__(self): self.products = {} self.sales = [] self.load() def save(self): pass # قدم ۵ def load(self): pass # قدم ۵ def add(self, name, buy, sell, qty): if not name or name in self.products: raise ValueError('نام خالی یا کالای تکراری است') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def edit(self, name, buy, sell, qty): if name not in self.products: raise ValueError('کالا پیدا نشد') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def delete(self, name): if name not in self.products: raise ValueError('کالا پیدا نشد') del self.products[name] self.save()
قدم ۴: فروش و گزارش
sell: کالا باید باشد، تعداد بزرگتر از صفر و حداکثر برابر موجودی. موجودی کم شود و رکورد {'name', 'qty', 'total'} به self.sales اضافه شود (total = تعداد × قیمت فروش). report: تاپل (جمع تعداد، جمع مبلغ).
قدم ۴ — sell و report
دو متد sell(self, name, qty) و report(self) را اضافه کن.
دیدن راهحل (اول خودت تلاش کن)
class Shop: def __init__(self): self.products = {} self.sales = [] self.load() def save(self): pass # قدم ۵ def load(self): pass # قدم ۵ def add(self, name, buy, sell, qty): if not name or name in self.products: raise ValueError('نام خالی یا کالای تکراری است') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def edit(self, name, buy, sell, qty): if name not in self.products: raise ValueError('کالا پیدا نشد') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def delete(self, name): if name not in self.products: raise ValueError('کالا پیدا نشد') del self.products[name] self.save() def sell(self, name, qty): if name not in self.products: raise ValueError('کالا پیدا نشد') if qty <= 0: raise ValueError('تعداد باید مثبت باشد') product = self.products[name] if qty > product['qty']: raise ValueError('موجودی کافی نیست') product['qty'] -= qty self.sales.append({'name': name, 'qty': qty, 'total': qty * product['sell']}) self.save() def report(self): return sum(s['qty'] for s in self.sales), sum(s['total'] for s in self.sales)
قدم ۵: ذخیره و بارگذاری
حالا save و load واقعی را بنویس. اینجا FILE = 'shop_data.json' است؛ در VS Code از خط __file__ (درس ۱۰) استفاده میکنی. load باید با فایل خراب (JSON نامعتبر یا غیر دیکشنری) بیصدا با دادهی خالی شروع کند.
قدم ۵ — save و load
save و load را کامل کن. تست، یک شیء دوم میسازد و چک میکند دادهها از فایل خوانده شوند.
دیدن راهحل (اول خودت تلاش کن)
import json import os FILE = 'shop_data.json' # در VS Code: مسیر کنار برنامه با __file__ class Shop: def __init__(self): self.products = {} self.sales = [] self.load() def save(self): with open(FILE, 'w', encoding='utf-8') as f: json.dump({'products': self.products, 'sales': self.sales}, f, ensure_ascii=False, indent=2) def load(self): if os.path.exists(FILE): try: with open(FILE, 'r', encoding='utf-8') as f: data = json.load(f) self.products = data.get('products', {}) self.sales = data.get('sales', []) except (OSError, json.JSONDecodeError, AttributeError): self.products, self.sales = {}, [] def add(self, name, buy, sell, qty): if not name or name in self.products: raise ValueError('نام خالی یا کالای تکراری است') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def edit(self, name, buy, sell, qty): if name not in self.products: raise ValueError('کالا پیدا نشد') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def delete(self, name): if name not in self.products: raise ValueError('کالا پیدا نشد') del self.products[name] self.save() def sell(self, name, qty): if name not in self.products: raise ValueError('کالا پیدا نشد') if qty <= 0: raise ValueError('تعداد باید مثبت باشد') product = self.products[name] if qty > product['qty']: raise ValueError('موجودی کافی نیست') product['qty'] -= qty self.sales.append({'name': name, 'qty': qty, 'total': qty * product['sell']}) self.save() def report(self): return sum(s['qty'] for s in self.sales), sum(s['total'] for s in self.sales)
قدم ۶: همه با هم، از حفظ
کادر زیر خالی است. بدون نگاه کردن به قدمهای قبل، کل کلاس را (با importها و FILE) بنویس. اگر گیر کردی، فقط همان تکه را نگاه کن و دوباره از اول بنویس. این تمرین را چند روز پشت سر هم تکرار کن تا بدون اشتباه و سریع شود.
کل کلاس Shop از حفظ
import json، import os، FILE = 'shop_data.json' و کلاس کامل Shop با ۸ متد.
دیدن راهحل (اول خودت تلاش کن)
import json import os FILE = 'shop_data.json' # در VS Code: مسیر کنار برنامه با __file__ class Shop: def __init__(self): self.products = {} self.sales = [] self.load() def save(self): with open(FILE, 'w', encoding='utf-8') as f: json.dump({'products': self.products, 'sales': self.sales}, f, ensure_ascii=False, indent=2) def load(self): if os.path.exists(FILE): try: with open(FILE, 'r', encoding='utf-8') as f: data = json.load(f) self.products = data.get('products', {}) self.sales = data.get('sales', []) except (OSError, json.JSONDecodeError, AttributeError): self.products, self.sales = {}, [] def add(self, name, buy, sell, qty): if not name or name in self.products: raise ValueError('نام خالی یا کالای تکراری است') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def edit(self, name, buy, sell, qty): if name not in self.products: raise ValueError('کالا پیدا نشد') if not all(0 <= x < float('inf') for x in (buy, sell, qty)): raise ValueError('عدد منفی یا نامعتبر مجاز نیست') self.products[name] = {'buy': buy, 'sell': sell, 'qty': qty} self.save() def delete(self, name): if name not in self.products: raise ValueError('کالا پیدا نشد') del self.products[name] self.save() def sell(self, name, qty): if name not in self.products: raise ValueError('کالا پیدا نشد') if qty <= 0: raise ValueError('تعداد باید مثبت باشد') product = self.products[name] if qty > product['qty']: raise ValueError('موجودی کافی نیست') product['qty'] -= qty self.sales.append({'name': name, 'qty': qty, 'total': qty * product['sell']}) self.save() def report(self): return sum(s['qty'] for s in self.sales), sum(s['total'] for s in self.sales)
مقایسه کن: کلاس کامل پروژه در بخش ۲ تا ۴ مستندات آمده است.
آزمون این درس
برای گذراندن این درس حداقل ۸۰٪ جواب درست لازم است. هر چند بار خواستی میتوانی دوباره امتحان بدهی.