Позвольте мне ответить на ваш вопрос другим вопросом:
Действительно ли необходимо смешивать буквы и цифры?
Разве они не могут быть просто строками?
Ну, давайте пройдем долгий путь и посмотрим, что делает программа:
- Отображение главного меню
- Запрос / получение ввода пользователя
- Если действительно: хорошо
- Если нет: напечатайте сообщение об ошибке и повторите
- Теперь у нас есть правильный ввод
- Если это буква:выполнить специальное задание
- Если это число: вызвать правильную функцию рисования
Точка 1. Давайте сделаем функцию дляэто:
def display_menu():
menu_text = """\
Draw a Shape
============
1 - Draw a triangle
2 - Draw a square
D - Display what was drawn
X - Exit"""
print menu_text
display_menu
очень просто, поэтому нет необходимости объяснять, что он делает, но позже мы увидим преимущество помещения этого кода в отдельную функцию.
Точка 2. Это будет сделано с помощью цикла:
options = ['1', '2', 'D', 'X']
while 1:
choice = raw_input(' Enter your choice: ')
if choice in options:
break
else:
print 'Try Again!'
Точка 3. Ну, после второй мысли, может быть, специальные задачи не такие уж особенные,поэтому давайте поместим их тоже в функцию:
def exit():
"""Exit""" # this is a docstring we'll use it later
return 0
def display_drawn():
"""Display what was drawn"""
print 'display what was drawn'
def draw_triangle():
"""Draw a triangle"""
print 'triangle'
def draw_square():
"""Draw a square"""
print 'square'
Теперь давайте соберем все вместе:
def main():
options = {'1': draw_triangle,
'2': draw_square,
'D': display_drawn,
'X': exit}
display_menu()
while 1:
choice = raw_input(' Enter your choice: ').upper()
if choice in options:
break
else:
print 'Try Again!'
action = options[choice] # here we get the right function
action() # here we call that function
Ключ к вашему переключателю лежит в options
, который больше не являетсяlist
но dict
, поэтому, если вы просто итерируете его, как if choice in options
, ваша итерация выполняется на клавишах : ['1', '2', 'D', 'X']
, но если вы сделаете options['X']
, вы получите функцию выхода (разве это не замечательно!).
Теперь давайте снова улучшимся, потому что поддержание сообщения главного меню и словаря options
это не слишком хорошо, через год я могу забыть изменить одно или другое,Я не получу то, что хочу, и мне лень, и я не хочу делать дважды одно и то же и т. Д.
Так почему бы не передать словарь options
в display_manu
и не позволить display_menu
делать всю работу, используя строки документации в __doc__
для генерации меню:
def display_menu(opt):
header = """\
Draw a Shape
============
"""
menu = '\n'.join('{} - {}'.format(k,func.__doc__) for k,func in opt.items())
print header + menu
Нам понадобится OrderedDict
вместо dict
для options
, потому что OrderedDict
как следует из названия, сохраняйте порядок своих предметов (посмотрите официальный документ ).Итак, у нас есть:
def main():
options = OrderedDict((('1', draw_triangle),
('2', draw_square),
('D', display_drawn),
('X', exit)))
display_menu(options)
while 1:
choice = raw_input(' Enter your choice: ').upper()
if choice in options:
break
else:
print 'Try Again!'
action = options[choice]
action()
Остерегайтесь того, что вы должны разработать свои действия так, чтобы они все имели одинаковую подпись (в любом случае они должны быть такими, они все действия!).Возможно, вы захотите использовать вызываемые элементы в качестве действий: экземпляры класса с __call__
реализованы.Создание базового Action
класса и наследование от него будет идеальным здесь.