Chương trình quản lý tác vụ bằng Python

Oct 08 2020

Tôi đã tạo một chương trình đơn giản bằng Python

  • lưu trữ các tác vụ trong tệp
  • cho phép người dùng quản lý chúng.

Tôi quan tâm đến việc triển khai của tôi có hiệu quả không và tôi có thể làm điều gì đó tốt hơn. Tôi không chắc liệu việc tải tất cả dữ liệu từ tệp vào bộ nhớ và lưu lại vào tệp có phải là cách tốt để triển khai các tác vụ lưu danh sách hay không.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os


CHOICE_LIST_TASKS = 1
CHOICE_ADD_TASK = 2
CHOICE_REMOVE_TASK = 3
CHOICE_QUIT = 4


def read_int(prompt='> ', errmsg='Invalid number!'):
    num = None
    while num is None:
        try:
            num = int(input(prompt))
        except ValueError:
            print(errmsg)
    return num


def display_menu():
    print('What do you want to do?')
    print('[1] List all tasks')
    print('[2] Add a new task')
    print('[3] Delete task')
    print('[4] Quit')


choice = None
file = None
if not os.path.exists('tasks'):
    file = open('tasks', 'w+')
else:
    file = open('tasks', 'r+')
tasks = []

for line in file.readlines():
    tasks.append(line.strip())

while choice != CHOICE_QUIT:
    display_menu()
    choice = read_int()
    if choice == CHOICE_LIST_TASKS:
        if len(tasks) == 0:
            print('Task list is empty!')
        else:
            print('Tasks:')
            for x in tasks:
                print(x)
    elif choice == CHOICE_ADD_TASK:
        desc = input('Which task do you want to do? ')
        index = tasks.append(desc)
        print('Successfully added a new task!')
    elif choice == CHOICE_REMOVE_TASK:
        if len(tasks) == 0:
            print('Task list is empty!')
        else:
            for x in tasks:
                print(tasks.index(x), x)
            index = read_int('Which task do you want to delete? ')
            try:
                tasks.pop(index)
                print('Successfully deleted task!')
            except IndexError:
                print('Please enter proper task number')
    elif choice == CHOICE_QUIT:
        print('Good bye!')
    else:
        print('Invalid choice!')

file = open('tasks', 'w+')
for x in tasks:
    file.write(x + '\n')

Trả lời

3 AryanParekh Oct 08 2020 at 20:53

Hãy bắt đầu từ đầu.

CHOICE_LIST_TASKS = 1
CHOICE_ADD_TASK = 2
CHOICE_REMOVE_TASK = 3
CHOICE_QUIT = 4

Tôi thấy rõ rằng bạn muốn tạo các biến và gán cho chúng một số nguyên nhất định để bạn không cần phải sử dụng các số ma thuật ở bất cứ đâu, rất tuyệt vời cho bạn. Có một cách tốt hơn nhiều để thực hiện ý tưởng này trong python

Các bảng kê: Enum

Các phép liệt kê trong Python

Một bảng liệt kê là một tập hợp các tên tượng trưng
(thành viên) liên kết với các giá trị duy nhất, không đổi

tạo ra một Enum

class Choices(Enum):
    list_task = 1
    add_task = 2 
    remove_task = 3
    quit = 4

Điều này đã có vẻ rõ ràng hơn nhiều so với các biến toàn cục ngẫu nhiên. Bạn cũng có thể lặp lại bảng liệt kê và hiển thị các giá trị của nó bằng tên .

print(Choices.add_task.name)

thêm nhiệm vụ

print(Choices.add_task.value) 

1

Sử dụng nhiều chức năng hơn

file = None
if not os.path.exists('tasks'):
    file = open('tasks', 'w+')
else:
    file = open('tasks', 'r+')
tasks = []

for line in file.readlines():
    tasks.append(line.strip())

Tại sao chúng ta không thể chuyển nó thành một hàm được gọi read_task_file()?
Bằng cách này, tôi, bạn, bạn sau một năm đọc các dự án cũ, và bất kỳ ai khác sẽ đọc mã này rằng vài dòng mã đó sẽ đọc tệp nhiệm vụ . Không có điều đó, người ta phải đọc mã kỹ lưỡng và hiểu mục đích của nó.

def read_task_file():
    file = None
    if not os.path.exists('tasks'):
        file = open('tasks', 'w+')
    else:
        file = open('tasks', 'r+')
    tasks = []
    for line in file.readlines():
        tasks.append(line.strip())
    return tasks

bây giờ nhận được nhiệm vụ là

tasks = read_task_file()

Điều này cũng chính xác áp dụng cho bộ mã tiếp theo, cho phép người dùng nhập lựa chọn của họ để chúng tôi có thể thực hiện nó.

Tính toán phần mà chúng tôi đọc lựa chọn từ người dùng và thực hiện thành một chức năng sẽ trông như thế nào

def read_task_choice():
    display_menu()
    choice = read_int()
    if choice not in Choices._value2member_map_:
        print("Invalid input! Please enter a correct choice\n")
        read_task_choice()

Lưu ý: Choices._value2member_map_sẽ là tất cả các giá trị trong một kiểu liệt kê.

Điều này đã trông sạch hơn nhiều! Chúng tôi loại bỏ sự cần thiết của nó trong một vòng lặp nơi nó sẽ kiểm tra tất cả các trường hợp, hàm chỉ trả về choicekhi có đầu vào hợp lệ.

Như tôi đã nói, hãy phân chia công việc thành các chức năng và tất cả chúng khi được yêu cầu. Tôi đã làm tương tự cho 4 công việc chính (4 lựa chọn).


Liệt kê các nhiệm vụ

def list_tasks(tasks):
    if len(tasks) == 0:
        print("Task list is empty!")
        return None


    for i in range(len(tasks)):
        print(f"{i} {tasks[i]}")

Thêm nhiệm vụ mới

def add_new_task(tasks):
    return input("What task would you like to finish ?: ")
    tasks.append(task)

Loại bỏ nhiệm vụ

def remove_task(tasks):
    if len(tasks) == 0:
        print("Task list is already empty!")
        return None

    list_tasks(tasks)
    task = int(input(("Which task would you like to remove: ?")))

    if task < 0 or task >= len(tasks):
        print("Invalid input! Please select an appropriate task")
        remove_task(tasks)
    tasks.pop(task)

Và cuối cùng

Cập nhật tệp nhiệm vụ

def update_task_file(tasks):
    file = open('tasks', 'w+')
    for x in tasks:
        file.write(x + '\n')

Có ích gì khi có hàng triệu chức năng khi tôi có thể đặt mọi thứ như tôi đã làm? Bây giờ khi bạn phải chơi trò chơi

tasks = read_task_file()

while True:
    choice = read_task_choice()
    if choice == Choices.list_task.value:
        list_tasks(tasks)

    elif choice == Choices.add_task.value:
        add_new_task(tasks)
        

    elif choice == Choices.remove_task.value:
        remove_task(tasks)

    else:
        break

    update_task_file(tasks)

Đây là lợi thế chính của việc có các chức năng được gõ mạnh.

Xóa màn hình và chờ nhập liệu

Do không có Đồ họa, chúng ta có thể thấy rằng sau một vài lựa chọn, thiết bị đầu cuối trông hơi lạ

Chúng tôi có thể cải thiện điều này bằng cách chỉ cần xóa màn hình sau mỗi lựa chọn, sau đó đợi người dùng nhấn một phím

Xóa thiết bị đầu cuối

Có một số cách. Một cách phổ biến là sử dụng os.system("cls")nếu bạn đang sử dụng windows, nhưng cách gọi này khá tốn kém và cũng khiến chương trình của bạn phụ thuộc vào nền tảng nhiều hơn.

Bạn có thể làm

print(chr(27) + "[2J")

Và điều này cũng sẽ hoạt động.

Đang đợi đầu vào

Thêm dòng input("Press any key to continue...")này sẽ đợi phản hồi của người dùng trước khi hiển thị lại tất cả các lựa chọn, giúp trải nghiệm tốt hơn.

Sau cùng

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
from enum import Enum

class Choices(Enum):
    list_task = 1
    add_task = 2
    remove_task = 3
    quit = 4

def read_int(prompt='> ', errmsg='Invalid number!'):
    num = None
    while num is None:
        try:
            num = int(input(prompt))
        except ValueError:
            print(errmsg)
    return num

def display_menu():
    print('What do you want to do?')
    print('[1] List all tasks')
    print('[2] Add a new task')
    print('[3] Delete task')
    print('[4] Quit')

def read_task_file():
    file = None
    if not os.path.exists('tasks'):
        file = open('tasks', 'w+')
    else:
        file = open('tasks', 'r+')
    tasks = []
    for line in file.readlines():
        tasks.append(line.strip())
    return tasks

def update_task_file(tasks):
    file = open('tasks', 'w+')
    for x in tasks:
        file.write(x + '\n')

def read_task_choice():
    display_menu()
    choice = read_int()
    if choice not in Choices._value2member_map_:
        print("Invalid input! Please enter a correct choice\n")
        read_task_choice()
    return choice

def add_new_task(tasks):
    task = input("What task would you like to do: ")
    tasks.append(task)

def list_tasks(tasks):
    if len(tasks) == 0:
        print("Task list is empty!")
        return None


    for i in range(len(tasks)):
        print(f"{i} {tasks[i]}")

def remove_task(tasks):
    if len(tasks) == 0:
        print("Task list is already empty!")
        return None

    list_tasks(tasks)
    task = int(input(("Which task would you like to remove: ?")))

    if task < 0 or task >= len(tasks):
        print("Invalid input! Please select an appropriate task")
        remove_task(tasks)
    tasks.pop(task)

def clear_screen():
    print(chr(27) + "[2J")

def pause():
    input("Press any key to continue...")

tasks = read_task_file()

while True:
    clear_screen()
    choice = read_task_choice()
    if choice == Choices.list_task.value:
        list_tasks(tasks)

    elif choice == Choices.add_task.value:
        add_new_task(tasks)


    elif choice == Choices.remove_task.value:
        remove_task(tasks)

    else:
        break

    update_task_file(tasks)
    pause()