Witam, piszę sobie klasę do obsługi menu w konsoli:
from collections import OrderedDict
def read_int(prompt='> ', errmsg='invalid integer'):
while True:
try:
return int(input(prompt))
except ValueError:
print(f'Error: {errmsg}')
class Menu:
def __init__(self, title, description='', fancy_banner=True, fill_char='#', prompt='Your choice: '):
self.title = title
self.description = description
self.items = OrderedDict()
self.fancy_banner = fancy_banner
self.fill_char = fill_char
self.active = True
self.prompt = prompt
def quit(self):
self.active = False
def add_item(self, title, action):
if title in self.items:
raise ValueError(f"cannot add item, duplicate item '{self.title}'")
self.items[title] = action
def remove_item(self, title):
if title not in self.items:
raise ValueError(f"cannot remove item, item '{self.title}' not found in menu '{self.title}'")
self.items.pop(title)
def invoke(self, title, *args, **kwargs):
if title not in self.items:
raise ValueError(f"cannot invoke function, item '{self.title}' not found in menu '{self.title}'")
self.items[title](*args, **kwargs)
def print_banner(self):
if self.fancy_banner:
banner = self.fill_char * (len(self.title) + 4) + '\n'
banner += f'# {self.title:^{len(self.title)}s} #\n'
banner += self.fill_char * (len(self.title) + 4) + '\n'
else:
banner = self.title + '\n'
return banner
def loop(self):
while self.active:
for offset, item in enumerate(self.items):
print(f'{offset}) {item}\n')
try:
choice = int(input(self.prompt))
if choice not in enumerate(self.items):
raise ValueError()
except ValueError:
print('Error: invalid choice!')
self.invoke(item)
def __str__(self):
return self.title
def __repr__(self):
return f"Menu(title='{self.title}')"
def __contains__(self, item):
return item in self.items
def main():
main_menu = Menu(title='Main menu')
main_menu.loop()
if __name__ == '__main__':
main()
Czy dobrze robię używając OrderedDict do przechowywania itemów czy lepiej stworzyć osobną klasę MenuItem i przechowywać w liście instancje tej klasy? Chcę mieć dostęp do elementów menu zarówno po wartościach przesunięcia jak w normalnej liscie, jak i po tytułach opcji menu.