Aufgabenverwaltungsprogramm in Python

Oct 08 2020

Ich habe ein einfaches Programm in Python erstellt

  • speichert Aufgaben in der Datei
  • ermöglicht dem Benutzer, sie zu verwalten.

Ich bin interessiert, ob meine Implementierung effizient ist und ob ich etwas besser machen könnte. Ich bin mir nicht sicher, ob das Laden aller Daten aus der Datei in den Speicher und das erneute Speichern in der Datei eine gute Möglichkeit ist, Aufgaben zum Speichern von Listen zu implementieren.

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

Antworten

3 AryanParekh Oct 08 2020 at 20:53

Beginnen wir ganz oben.

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

Mir ist klar, dass Sie Variablen erstellen und ihnen bestimmte Ganzzahlen zuweisen möchten, damit Sie nirgendwo magische Zahlen verwenden müssen. Ein großes Lob dafür. Es gibt einen viel besseren Weg, um diese Idee in Python umzusetzen

Aufzählungen: Enum

Aufzählungen in Python

Eine Aufzählung ist eine Reihe von symbolischen Namen
(Mitgliedern), die an eindeutige, konstante Werte gebunden sind

Erstellen eines Enum

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

Dies sieht bereits viel klarer aus als zufällige globale Variablen. Sie können die Aufzählung auch durchlaufen und ihre Werte mit Namen anzeigen .

print(Choices.add_task.name)

Aufgabe hinzufügen

print(Choices.add_task.value) 

1

Verwenden Sie mehr Funktionen

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

Warum können wir dies nicht in eine Funktion namens verschieben read_task_file()?
Auf diese Weise ist mir, Ihnen, Ihnen, nach einem Jahr beim Lesen alter Projekte und jedem anderen, der diesen Code jemals lesen wird, sehr klar, dass diese wenigen Codezeilen die Aufgabendatei lesen werden . Ohne das muss man den Code gründlich lesen und seinen Zweck verstehen.

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

Jetzt bekommen die Aufgaben

tasks = read_task_file()

Dies gilt auch für den nächsten Codesatz, mit dem der Benutzer seine Auswahl eingeben kann, damit wir ihn ausführen können.

Das Herausrechnen des Teils, in dem wir eine Auswahl vom Benutzer lesen und in eine Funktion ausführen, würde so aussehen

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

Hinweis: Choices._value2member_map_Alle Werte in einer Aufzählung werden angezeigt.

Das sieht schon viel sauberer aus! Wir müssen es nicht mehr in einer Schleife haben, in der alle Fälle überprüft werden. Die Funktion wird nur zurückgegeben, choicewenn eine gültige Eingabe vorliegt.

Berücksichtigen Sie, wie gesagt, die Arbeit bei Bedarf in Funktionen und alle diese. Ich habe das gleiche für die 4 Hauptjobs getan (die 4 Auswahlmöglichkeiten).


Aufgaben auflisten

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

Neue Aufgabe hinzufügen

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

Aufgabe entfernen

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)

Und schlussendlich

Aufgabendatei aktualisieren

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

Was bringt es, Millionen von Funktionen zu haben, wenn ich alles so platzieren kann, wie ich es bereits getan habe? Jetzt, wenn Sie das Spiel spielen müssen

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)

Dies ist der Hauptvorteil stark typisierter Funktionen.

Bildschirm löschen und auf Eingabe warten

Aufgrund des Fehlens von Grafiken können wir feststellen, dass das Terminal nach einigen Auswahlmöglichkeiten etwas seltsam aussieht

Wir können dies verbessern, indem wir nach jeder Auswahl einfach den Bildschirm löschen und dann warten, bis der Benutzer eine Taste drückt

Terminal löschen

Es gibt einige Möglichkeiten. Eine beliebte Methode ist die Verwendung os.system("cls")unter Windows. Dies ist jedoch recht teuer und macht Ihr Programm plattformabhängiger.

Du kannst tun

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

Und das wird auch funktionieren.

Warten auf Eingabe

Durch Hinzufügen dieser Zeile input("Press any key to continue...")wird auf die Antwort des Benutzers gewartet, bevor alle Auswahlmöglichkeiten erneut angezeigt werden, um die Benutzererfahrung zu verbessern.

Finale

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