Список покупок с использованием Python 3

В этой программе на Python я использовал списки и поток управления, чтобы пользователи могли добавлять элементы в список покупок и отображать этот список.

Мне нужен совет относительно моего кода с точки зрения (архитектуры, рисков, возможностей, дизайна), чтобы я мог узнать, как я могу лучше кодировать и развивать свои навыки.

shopping_list = []

# Add a function to allow users to ask for help when they need to
def show_help():
    print('What should we pick up at the store?')
    print("""
  Enter 'DONE' to stop adding items.
  Enter 'HELP' for additional info.
  Enter 'SHOW' to see your shopping list
  """)

# Create a function that adds an item to the list
def add_to_list(item):
    shopping_list.append(item)
    print('{} was added to your shopping list!'.format(item))
    print('You have {} items on your list.'.format(len(shopping_list)))


# Create a function to print all the items in the shopping list
def show_list():
    print('My Shopping List:')
    for item in shopping_list:
        print(item)


show_help()

while True:
    new_item = input('> ')

    # If the user inputs 'DONE' exit the loop
    if new_item == 'DONE':
        break
    # If the user inputs 'HELP' show the help documentation
    elif new_item == 'HELP':
        show_help()
        continue
    # if the user inputs 'SHOW' show the list
    elif new_item == 'SHOW':
        show_list()
        continue

    # Call add_to_list with new item as an argument
    add_to_list(new_item)

show_list()

1 ответ
1


Code Tells You How, Comments Tell You Why?

Вы пытались задокументировать свой код с помощью комментариев, и это здорово! Однако комментарии, использующие # в основном предназначены для других программистов и обычно зарезервированы для объяснения кратких частей кода. Обычный способ документ ваш код, предназначенный для пользователя, с PEP 257 — Соглашения о строках документации.

Как указано в заголовке комментариев (#) следует использовать редко. Во-первых, вы должны сначала постараться сделать свой код как можно более простым для понимания, не полагаясь на комментарии как на костыль. Только в том месте, где невозможно сделать код более понятным, можно начинать добавлять комментарии. Я бы далее разбил его на три

  1. Уточните цель вашего кода с помощью функций, следующих за принцип единой ответственности
  2. Уточните, что делает каждая переменная, с помощью четких имен переменных, которые соответствуют стандартным соглашениям о форматировании Python.
  3. Если «почему» неясно в первых двух пунктах, тогда и только после этого мы добавляем комментарии.

PEP8 - Style Guide for Python Code

Как выбрать самые низкие плоды. Согласованность — ключевая часть программирования, так как она значительно повышает удобочитаемость. Это также немного говорит о внимании кодеров к деталям. Давайте посмотрим, как вы назвали свои глобальные константы:

shopping_list = []

Pep8 рекомендует следующее соглашения об именах:

  • CAPITALIZED_WITH_UNDERSCORES для констант
  • UpperCamelCase для имен классов
  • lowercase_separated_by_underscores для других имен

Честно говоря, вы в основном следуете этому стандарту, и это отлично! Я просто указываю на то, что следовать этим стандартам — это разумно.


Handling user input

Помимо шуток, как правило, следует никогда за исключением того, что пользователь использует правильный синтаксис ввода. Вместо этого вы должны встроить проверки, исключения для обработки этих ошибок.

Что будет, если я напишу help? Лучше всего позволить функции обрабатывать вводимые пользователем данные.

def get_valid_user_input():

    options = ["add", "done", "show"]
    print(MENU)
    while True: 
        choice = input("> ").lower()
        if choice not in options:
           print(f"Ooops, you need to enter one of the valid options {options}")
        else:
           return choice

Use of functions

Часть, которая мне запомнилась, была

def show_help():
    print('What should we pick up at the store?')
    print("""
  Enter 'DONE' to stop adding items.
  Enter 'HELP' for additional info.
  Enter 'SHOW' to see your shopping list
  """)

Функция должна быть блоком организованного, многократно используемого кода, который используется для выполнения одного связанного действие. Теперь давайте пройдемся по этому контрольному списку, чтобы увидеть, должна ли это быть функция.

  • Функция вызывается более чем дважды? ✔️

  • Служит ли функция единственная цель? ✔️

  • Выполняет ли функция действие? ❌

    MENU = "What should we pick up at the store?nn
    Enter 'DONE' to stop adding items.n
    Enter 'HELP' for additional info.n
    Enter 'SHOW' to see your shopping list"
    

Поскольку ответ на последний вопрос был отрицательным, ваша функция не принимает никаких данных, поэтому это может быть постоянный.

Примечание: Как правило, тройные кавычки следует использовать для
строки документации и не использоваться для печати.


f-strings

f-строки — это новый способ формирования строк в Python, и вы обычно должны их использовать. Например

 print('{} was added to your shopping list!'.format(item))
 print('You have {} items on your list.'.format(len(shopping_list)))

становится

 print(f"{item} was added to your shopping list!")
 print(f"You have {len(shopping_list)} items on your list.")

Nitpicking

  • Поместите те части вашего кода, которые требуют выполнения, за if __name__ == "__main__": сторожить. Таким образом, вы можете импортировать этот модуль python из других мест, если хотите, а защита предотвращает случайный запуск основного кода при каждом импорте.

A deeper look

 What should we pick up at the store?

 Enter 'DONE' to stop adding items.
 Enter 'HELP' for additional info.
 Enter 'SHOW' to see your shopping list

 >

Было бы лучше, если бы он читал

 Enter 'DONE' to stop adding items.
 Enter 'HELP' for additional info.
 Enter 'SHOW' to see your shopping list

 What should we pick up at the store?
 >

Во-вторых, что произойдет, если я неуверен и наберу справку? Затем мне будет предложено то же самое меню.

 What should we pick up at the store?

 Enter 'DONE' to stop adding items.
 Enter 'HELP' for additional info.
 Enter 'SHOW' to see your shopping list

 > HELP
 What should we pick up at the store?

 Enter 'DONE' to stop adding items.
 Enter 'HELP' for additional info.
 Enter 'SHOW' to see your shopping list

 >

Полагаю, это не очень поможет. Хотя это семантика, вы обрабатываете ввод пользователя как item, что сбивает с толку. Например

# If the user inputs 'DONE' exit the loop
if new_item == "DONE":
    break

Лучшим решением было бы использовать другое имя, например user_input а позже измените его на item, когда его нужно добавить в корзину. Ниже я представляю несколько иной способ решения этой проблемы.


My own attempt

  • Я перевел ваши комментарии на строки документации. Они были хорошо написаны и содержательны!
  • Я включил if __name__ == "__main__": сторожить.
  • Колокольчики и свистки Я добавил подсказки по набору текста, см. PEP484.
  • Ваш список покупок лучше структурирован как простой класс. Это упрощает обслуживание и добавление функциональности. (Что делать, если вы хотите удалить товар из своего списка покупок?)
  • Более надежная обработка пользовательского ввода. Попробуйте написать что-нибудь глупое в качестве ввода, что произойдет?
  • Я отделил бизнес-логику от пользовательского интерфейса, выполнив печать в main и сохраняя ShoppingCart чистый.
  • HELP был удален и вместо screen_clear() был добавлен в дополнение к отображению меню каждый раз.
  • Цифровое меню было добавлено как очарование пользователя. Считаете ли вы, что этот стиль меню является улучшением, зависит от вас. Если вы решили сохранить свой стиль, по крайней мере, input("> ").upper() чтобы позволить пользователям делать add. Числовые данные вводятся быстрее, могут быть более четкими и их легче расширить до большего количества вариантов.
  • Меню и добавление элементов были разделены на две функции (помните, вы использовали item для обоих).

code

import platform  # For getting the operating system name
import subprocess  # For executing a shell command


def clear_screen():
    """Clears the terminal screen."""

    # Clear command as function of OS
    command = "cls" if platform.system().lower() == "windows" else "clear"

    # Action
    return subprocess.call(command) == 0


MENU_OPTIONS = ["add item", "see your shopping list", "exit"]


def get_user_menu_choice() -> int:
    """Gives the user a menu to choose from"""
    low, high = 1, len(MENU_OPTIONS)
    error_msg = f"Woops, your input must be an integer in {low}...{high}n"
    while True:
        print("Input a number from the list below:")
        for index, option in enumerate(MENU_OPTIONS):
            print(f" {1+index:>3d}: {option}")
        try:
            choice = int(input("nPlease enter a number: "))
            if low <= choice <= high:
                return choice
        except ValueError:
            pass
        print(error_msg)


class ShoppingCart:
    def __init__(self):
        self.items = []

    def add(self, item: str):
        """Create a function that adds an item to the list"""
        if item != "":
            self.items.append(item)
        return item

    def get_items_from_user(self) -> None:
        clear_screen()
        print("nnnWrite in the item you want to add to your shopping list!")
        print("[leave blank to return to menu]n")

        item = self.add(input("> "))
        while item:

            clear_screen()
            print(f"{item} was added to your shopping list!")
            item_str = "items" if len(self.items) > 1 else "item"
            print(f"You have {len(self.items)} {item_str} in your list.")

            print("nWrite in the item you want to add to your shopping list!")
            print("[leave blank to return to menu]n")

            item = self.add(input("> "))

    def __str__(self) -> str:
        """Create a function to show all the items in the shopping list"""
        string = "My Shopping List:n"
        for index, item in enumerate(self.items):
            string += f"n{1+index:>3d}. {item}"
        return string + "n"


def main() -> None:

    choice, add_item, display_items, exit_program = 0, 1, 2, 3

    cart = ShoppingCart()

    clear_screen()
    while choice != exit_program:
        choice = get_user_menu_choice()
        if choice == add_item:
            cart.get_items_from_user()
            clear_screen()
        elif choice == display_items:
            clear_screen()
            print(cart)


if __name__ == "__main__":
    main()

  • Я не понимаю, насколько ваше цифровое меню является улучшением по сравнению со строками OP.

    — Райндериен

  • 1

    Как правило, тройные кавычки следует зарезервировать для строк документации и не использовать для печати. просто неправда. Heredocs в тройных кавычках полезны всякий раз, когда есть многострочный строковый литерал.

    — Райндериен

  • @Reinderien Ì возникли проблемы с тройными кавычками при использовании Sphinx, doctest и другие программы, которые читают и обрабатывают строки документации. Вот почему я избегаю их использования. Для вашего второго пункта написать 1, 2 или 3 намного быстрее, чем вводить точно DONE. Улучшение состоит в том, чтобы разрешить и то, и другое, но это выходит за рамки этого ответа.

    — N3buchadnezzar

  • Справедливо сказать, что числовой подход — это улучшение юзабилити, но если это так, вы должны указать это в своем ответе и объяснить свою теорию относительно того, почему

    — Райндериен

  • Также, SCREEN_CLEAR не является переносимым, и даже для операционных систем, которые его поддерживают, они могут быть в режиме конвейера, для которого эта escape-последовательность будет взорвана.

    — Райндериен

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *