Programma di gestione delle attività in Python
Ho realizzato un semplice programma in Python
- memorizza le attività nel file
- consente all'utente di gestirli.
Sono interessato se la mia implementazione è efficiente e potrei fare qualcosa di meglio. Non sono sicuro se caricare tutti i dati dal file alla memoria e salvarli nuovamente nel file sia un buon modo per implementare le attività di salvataggio dell'elenco.
#!/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')
Risposte
Cominciamo dall'inizio.
CHOICE_LIST_TASKS = 1
CHOICE_ADD_TASK = 2
CHOICE_REMOVE_TASK = 3
CHOICE_QUIT = 4
È chiaro per me che vuoi creare variabili e assegnare loro determinati numeri interi in modo da non dover usare numeri magici ovunque, complimenti a te per questo. C'è un modo molto migliore per implementare questa idea in Python
Enumerazioni: Enum
Enumerazioni in Python
Un'enumerazione è un insieme di nomi simbolici
(membri) associati a valori univoci e costanti
creando un file Enum
class Choices(Enum):
list_task = 1
add_task = 2
remove_task = 3
quit = 4
Questo sembra già molto più chiaro delle variabili globali casuali. È inoltre possibile scorrere l'enumerazione e visualizzarne i valori con i nomi .
print(Choices.add_task.name)
add_task
print(Choices.add_task.value)
1
Usa più funzioni
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())
Perché non possiamo spostarlo in una funzione chiamata read_task_file()?
In questo modo è estremamente chiaro per me, tu, tu dopo un anno di lettura di vecchi progetti, e chiunque altro leggerà questo codice che quelle poche righe di codice leggeranno il file delle attività . In caso contrario, è necessario leggere completamente il codice e comprenderne lo scopo.
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
ora ottenere i compiti è
tasks = read_task_file()
Lo stesso vale per il set di codice successivo, che consentirà all'utente di inserire la propria scelta in modo da poterlo eseguire.
Assomiglierebbe a fattorizzare la parte in cui leggiamo una scelta dell'utente e la eseguiamo in una funzione
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()
Nota: Choices._value2member_map_saranno tutti i valori in un'enumerazione.
Questo sembra già molto più pulito! Eliminiamo la necessità di averlo in un ciclo dove controllerà tutti i casi, la funzione ritorna solo choicequando c'è un input valido.
Come ho detto, scomponi il lavoro in funzioni e tutte quando richiesto. Ho fatto lo stesso per i 4 lavori principali (le 4 scelte).
Elenca le attività
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]}")
Aggiungi nuova attività
def add_new_task(tasks):
return input("What task would you like to finish ?: ")
tasks.append(task)
Rimuovi attività
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)
E infine
Aggiorna file attività
def update_task_file(tasks):
file = open('tasks', 'w+')
for x in tasks:
file.write(x + '\n')
Qual è il punto di avere milioni di funzioni quando posso mettere tutto come ho già fatto? Ora quando devi giocare
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)
Questo è il vantaggio principale di avere funzioni fortemente tipizzate.
Cancellazione dello schermo e attesa di input
A causa dell'assenza di grafica, possiamo vedere che dopo alcune scelte il terminale sembra un po 'strano
Possiamo migliorare questo semplicemente cancellando lo schermo dopo ogni scelta e quindi attendere che l'utente prema un tasto
Cancellazione del terminale
Ci sono alcuni modi. Un modo popolare è quello di utilizzare os.system("cls")se sei su Windows, ma chiamarlo è piuttosto costoso e rende il tuo programma più dipendente dalla piattaforma.
Tu puoi fare
print(chr(27) + "[2J")
E anche questo funzionerà.
In attesa di input
L'aggiunta di questa riga input("Press any key to continue...")attenderà la risposta dell'utente prima di visualizzare nuovamente tutte le scelte, migliorando l'esperienza.
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()