Table of Contents
طراحی پروژهٔ «فهرست کارها»
در این پروژه یک برنامهٔ خط فرمان (Command Line) میسازیم که به ما کمک کند کارهای روزانهمان را مدیریت کنیم. ایده این است:
- کار جدید اضافه کنیم
- فهرست کارها را ببینیم
- کار انجامشده را علامت بزنیم
- کار را حذف کنیم
- فهرست کارها در یک فایل ذخیره شود تا بعداً هم در دسترس باشد
در این پروژه از مهارتهایی استفاده میکنیم که در فصلهای قبلی یاد گرفتهاید:
- متغیرها و انواع داده
- شرطها و حلقهها
- لیست و دیکشنری
- تابعها
- کار با فایلها
در این فصل خودِ پروژه را گام به گام میسازیم.
طرح کلی برنامه
قبل از کدنویسی، رفتار کلی برنامه را مشخص میکنیم.
کاربر وقتی برنامه را اجرا میکند، یک منوی ساده میبیند:
- نمایش فهرست کارها
- افزودن کار جدید
- علامتزدن کار به عنوان انجامشده
- حذف یک کار
- خروج از برنامه
هر کار میتواند این اطلاعات را داشته باشد:
- توضیح کار (مثلاً: «مطالعهٔ ۳۰ دقیقه پایتون»)
- وضعیت انجامشدن (انجامشده / انجامنشده)
برای نگهداشتن کارها از یک لیست استفاده میکنیم که هر عضو آن یک دیکشنری است؛ مثلاً:
{"title": "مطالعهٔ ۳۰ دقیقه پایتون", "done": False}پس ساختار کلی دادهها چیزی شبیه این است:
tasks = [
{"title": "مطالعهٔ ۳۰ دقیقه پایتون", "done": False},
{"title": "پیادهروی", "done": True},
]پیادهسازی نسخهٔ ساده (بدون فایل)
اول یک نسخهٔ درونحافظهای میسازیم که فقط تا وقتی برنامه باز است کار میکند. بعد آن را با فایل ترکیب میکنیم.
۱. ساخت منوی اصلی
def show_menu():
print("========== فهرست کارها ==========")
print("1. نمایش فهرست کارها")
print("2. افزودن کار جدید")
print("3. علامتزدن کار به عنوان انجامشده")
print("4. حذف یک کار")
print("5. خروج")
print("================================")و حلقهٔ اصلی برنامه:
def main():
tasks = [] # فهرست کارها در حافظه
while True:
show_menu()
choice = input("یک گزینه را انتخاب کنید: ")
if choice == "1":
show_tasks(tasks)
elif choice == "2":
add_task(tasks)
elif choice == "3":
mark_task_done(tasks)
elif choice == "4":
delete_task(tasks)
elif choice == "5":
print("خداحافظ!")
break
else:
print("گزینه نامعتبر است. دوباره تلاش کنید.")
if __name__ == "__main__":
main()در این مرحله فقط منو و اسکلت برنامه را داریم. حالا توابع مربوط به مدیریت کارها را مینویسیم.
۲. نمایش فهرست کارها
میخواهیم فهرست را با شماره و وضعیت نمایش دهیم، مثلاً:
[ ] 1. مطالعهٔ پایتون[x] 2. پیادهروی
def show_tasks(tasks):
if not tasks:
print("هیچ کاری در فهرست نیست.")
return
print("\nفهرست کارها:")
for index, task in enumerate(tasks, start=1):
status = "[x]" if task["done"] else "[ ]"
print(f"{status} {index}. {task['title']}")
print()نکتهها:
- از
enumerateبرای گرفتن شمارهٔ آیتمها استفاده شده است. - از یک علامت
[x]برای کارهای انجامشده و[ ]برای کارهای انجامنشده استفاده میکنیم.
۳. افزودن کار جدید
کاربر متن کار را وارد میکند و ما آن را به لیست اضافه میکنیم:
def add_task(tasks):
title = input("عنوان کار جدید را وارد کنید: ").strip()
if not title:
print("عنوان کار نمیتواند خالی باشد.")
return
task = {"title": title, "done": False}
tasks.append(task)
print("کار جدید اضافه شد.")چند نکته:
- با
strip()فاصلههای اضافی ابتدای و انتهای متن حذف میشود. - اگر کاربر فقط Enter بزند، کار ثبت نمیشود.
۴. علامتزدن کار به عنوان انجامشده
ابتدا فهرست را نشان میدهیم، سپس از کاربر میخواهیم شمارهٔ کار را وارد کند:
def mark_task_done(tasks):
if not tasks:
print("هیچ کاری برای انجامدادن وجود ندارد.")
return
show_tasks(tasks)
choice = input("شمارهٔ کاری که انجام شده را وارد کنید: ")
if not choice.isdigit():
print("باید یک عدد وارد کنید.")
return
index = int(choice) - 1 # چون شمارش ما از 1 است ولی اندیس لیست از 0
if 0 <= index < len(tasks):
tasks[index]["done"] = True
print("کار به عنوان انجامشده علامت خورد.")
else:
print("شمارهٔ وارد شده معتبر نیست.")اینجا:
- با
isdigit()بررسی میکنیم که ورودی عدد است. - مطمئن میشویم که عدد در بازهٔ درست لیست است.
۵. حذف یک کار از فهرست
مشابه علامتزدن، اما این بار کار را حذف میکنیم:
def delete_task(tasks):
if not tasks:
print("هیچ کاری برای حذف وجود ندارد.")
return
show_tasks(tasks)
choice = input("شمارهٔ کاری که میخواهید حذف کنید را وارد کنید: ")
if not choice.isdigit():
print("باید یک عدد وارد کنید.")
return
index = int(choice) - 1
if 0 <= index < len(tasks):
removed = tasks.pop(index)
print(f"کار «{removed['title']}» حذف شد.")
else:
print("شمارهٔ وارد شده معتبر نیست.")
تابع pop عنصر را از لیست برمیدارد و خودش را برمیگرداند تا بتوانیم عنوان آن را چاپ کنیم.
افزودن ذخیرهسازی در فایل
نسخهای که تا الان ساختیم، بعد از بستن برنامه همهٔ کارها را از دست میدهد. میخواهیم کارها در فایلی مثل tasks.txt ذخیره شوند تا دفعهٔ بعد هم در دسترس باشند.
اینجا یک روش ساده را استفاده میکنیم:
- هر خط فایل یک کار است.
- ساختار هر خط:
$وضعیت$;$عنوان$ - وضعیت میتواند
"0"برای انجامنشده و"1"برای انجامشده باشد.
مثال محتویات فایل:
0;مطالعهٔ ۳۰ دقیقه پایتون
1;پیادهروی۱. بارگذاری کارها از فایل
وقتی برنامه شروع میشود، تلاش میکنیم فایل را بخوانیم. اگر موجود نبود، از یک لیست خالی شروع میکنیم.
FILENAME = "tasks.txt"
def load_tasks():
tasks = []
try:
with open(FILENAME, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue # خط خالی را رد کن
status_str, title = line.split(";", 1)
done = True if status_str == "1" else False
tasks.append({"title": title, "done": done})
except FileNotFoundError:
# اگر فایل وجود نداشت، فهرست خالی برمیگردانیم
pass
return tasksنکتهها:
- از
split(";", 1)استفاده میکنیم تا اگر عنوان کار خودش;داشت، فقط اولین مورد جدا شود. - اگر فایل نبود، خطا را میگیریم و کاری نمیکنیم.
۲. ذخیرهکردن کارها در فایل
هر بار که تغییری در فهرست میدهیم (افزودن، حذف، تغییر وضعیت)، میتوانیم کل فهرست را دوباره در فایل بنویسیم.
def save_tasks(tasks):
with open(FILENAME, "w", encoding="utf-8") as f:
for task in tasks:
status_str = "1" if task["done"] else "0"
line = f"{status_str};{task['title']}\n"
f.write(line)اینجا:
- حالت
"w"کل فایل را از نو مینویسد. - هر کار را در یک خط ذخیره میکنیم.
۳. اتصال بارگذاری و ذخیره به برنامهٔ اصلی
حالا باید:
- در شروع
main، به جایtasks = []ازload_tasks()استفاده کنیم. - بعد از هر تغییری،
save_tasks(tasks)را صدا بزنیم.
def main():
tasks = load_tasks() # بارگذاری از فایل
while True:
show_menu()
choice = input("یک گزینه را انتخاب کنید: ")
if choice == "1":
show_tasks(tasks)
elif choice == "2":
add_task(tasks)
save_tasks(tasks)
elif choice == "3":
mark_task_done(tasks)
save_tasks(tasks)
elif choice == "4":
delete_task(tasks)
save_tasks(tasks)
elif choice == "5":
print("خداحافظ!")
break
else:
print("گزینه نامعتبر است. دوباره تلاش کنید.")به این شکل، هر تغییری بلافاصله در فایل ذخیره میشود و اگر برنامه قطع شود، اطلاعات از بین نمیرود.
بهبودهای اختیاری
اگر دوست دارید برنامه را کمی حرفهایتر کنید، میتوانید چند ویژگی اضافه کنید.
۱. فیلتر کردن کارها (فقط انجامنشدهها یا فقط انجامشدهها)
مثلاً زیرمنو برای نمایش:
- همهٔ کارها
- فقط کارهای انجامنشده
- فقط کارهای انجامشده
ایدهٔ ساده:
def show_tasks_filtered(tasks, only_done=None):
filtered = []
for task in tasks:
if only_done is None:
filtered.append(task)
elif only_done and task["done"]:
filtered.append(task)
elif (only_done is False) and (not task["done"]):
filtered.append(task)
if not filtered:
print("کاری برای نمایش وجود ندارد.")
return
for index, task in enumerate(filtered, start=1):
status = "[x]" if task["done"] else "[ ]"
print(f"{status} {index}. {task['title']}")و در منو گزینههای جدید برای این نمایشها قرار دهید.
۲. ویرایش عنوان یک کار
امکانی برای تغییر متن یک کار:
def edit_task(tasks):
if not tasks:
print("هیچ کاری برای ویرایش وجود ندارد.")
return
show_tasks(tasks)
choice = input("شمارهٔ کار برای ویرایش را وارد کنید: ")
if not choice.isdigit():
print("باید یک عدد وارد کنید.")
return
index = int(choice) - 1
if 0 <= index < len(tasks):
new_title = input("عنوان جدید را وارد کنید: ").strip()
if not new_title:
print("عنوان نمیتواند خالی باشد.")
return
tasks[index]["title"] = new_title
print("کار ویرایش شد.")
else:
print("شمارهٔ وارد شده معتبر نیست.")
بعد از ویرایش، فراموش نکنید save_tasks(tasks) را صدا بزنید.
جمعبندی پروژهٔ فهرست کارها
در این پروژه:
- یک برنامهٔ تعاملی خط فرمان ساختید.
- دادهها را با ساختار «لیست از دیکشنریها» مدیریت کردید.
- از حلقهٔ بینهایت و منو برای تعامل با کاربر استفاده کردید.
- ورودی کاربر را بررسی و خطاهای سادهٔ ورودی را کنترل کردید.
- اطلاعات را در یک فایل متنی ذخیره و از آن بارگذاری کردید.
این پروژه، نمونهای کوچک اما واقعی از یک برنامهٔ کاربردی است. میتوانید این برنامه را مطابق نیاز خود گسترش دهید؛ برای مثال:
- اولویت (مثلاً مهم / معمولی) به کارها اضافه کنید.
- مهلت انجام (تاریخ) برای هر کار بگذارید.
- با مرتبسازی، کارهای مهمتر را بالاتر نشان دهید.
ایدهٔ اصلی این فصل این است که ببینید با مفاهیم سادهای که تا اینجا یاد گرفتهاید، میتوانید یک ابزار مفید واقعی برای خودتان بسازید.