Program manajemen tugas dengan Python

Oct 08 2020

Saya membuat program sederhana dengan Python

  • menyimpan tugas di file
  • memungkinkan pengguna untuk mengelolanya.

Saya tertarik jika penerapan saya efisien dan dapatkah saya melakukan sesuatu yang lebih baik. Saya tidak yakin apakah memuat semua data dari file ke memori dan sekali lagi menyimpannya dalam file adalah cara yang baik untuk mengimplementasikan tugas penyimpanan daftar.

#!/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')

Jawaban

3 AryanParekh Oct 08 2020 at 20:53

Mari kita mulai dari yang paling atas.

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

Jelas bagi saya bahwa Anda ingin membuat variabel dan menetapkannya bilangan bulat tertentu sehingga Anda tidak perlu menggunakan angka ajaib di mana pun, pujian untuk Anda untuk ini. Ada cara yang jauh lebih baik untuk mengimplementasikan ide ini dengan python

Enumeration: Enum

Pencacahan dengan Python

Enumerasi adalah sekumpulan nama simbolik
(anggota) yang terikat pada nilai konstan yang unik

membuat sebuah Enum

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

Ini sudah terlihat jauh lebih jelas daripada variabel global acak. Anda juga dapat mengulang melalui pencacahan dan menampilkan nilainya dengan nama .

print(Choices.add_task.name)

add_task

print(Choices.add_task.value) 

1

Gunakan lebih banyak fungsi

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())

Mengapa kita tidak bisa memindahkan ini menjadi fungsi yang disebut read_task_file()?
Dengan cara ini sangat jelas bagi saya, Anda, Anda setelah satu tahun membaca proyek lama, dan siapa pun yang pernah membaca kode ini bahwa beberapa baris kode itu akan membaca file tugas . Tanpa itu, seseorang harus membaca kode tersebut secara menyeluruh dan memahami tujuannya.

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

sekarang mendapatkan tugasnya

tasks = read_task_file()

Hal yang sama berlaku untuk set kode berikutnya, yang akan membiarkan pengguna memasukkan pilihan mereka sehingga kami dapat melakukannya.

Memfaktorkan bagian di mana kita membaca pilihan dari pengguna dan menjalankannya menjadi suatu fungsi akan terlihat

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()

Catatan: Choices._value2member_map_akan menjadi semua nilai dalam pencacahan.

Ini sudah terlihat jauh lebih bersih! Kami menghilangkan kebutuhan untuk memilikinya dalam loop di mana ia akan memeriksa semua kasus, fungsi tersebut hanya kembali choiceketika ada input yang valid.

Seperti yang saya katakan, faktorkan pekerjaan menjadi fungsi dan semuanya saat diperlukan. Saya telah melakukan hal yang sama untuk 4 pekerjaan utama (4 pilihan).


Buat daftar tugas

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]}")

Tambahkan tugas baru

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

Hapus tugas

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)

Dan akhirnya

Perbarui file tugas

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

Apa gunanya memiliki jutaan fungsi ketika saya bisa meletakkan segala sesuatu seperti yang sudah saya lakukan? Sekarang saat Anda harus memainkan game tersebut

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)

Ini adalah keuntungan utama memiliki fungsi yang diketik dengan kuat.

Membersihkan layar dan menunggu masukan

Karena tidak adanya Grafik, kita dapat melihat bahwa setelah beberapa pilihan terminal terlihat sedikit aneh

Kami dapat meningkatkan ini hanya dengan membersihkan layar setelah setiap pilihan, dan kemudian menunggu pengguna untuk menekan sebuah tombol

Membersihkan terminal

Ada beberapa cara. Cara yang populer adalah menggunakannya os.system("cls")jika Anda menggunakan Windows, tetapi memanggil ini cukup mahal dan juga membuat program Anda lebih bergantung pada platform.

Anda dapat melakukan

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

Dan ini juga akan berhasil.

Menunggu masukan

Menambahkan baris ini input("Press any key to continue...")akan menunggu tanggapan pengguna sebelum menampilkan semua pilihan lagi, membuat pengalaman menjadi lebih baik.

Terakhir

#!/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()