首页 > 解决方案 > 食谱数据库的类不起作用?

问题描述

有 3 个文件,我将一个精简的数据库移动到其中一个文件中,以便我可以证明这个概念有效。第一个文件称为 find_a_recipe.py,它是运行的文件

[find_a_recipe.py]

from random import sample
from typing import List
from  main import *
#from cfonts import render



## main logic for type ingredient mode
def type_mode():
    print("Let's find the ingredient you are looking for...")
    keep_choosing = True
    recipes = recipe_list
    ingredient_list = get_ingredient_list(recipe_list)
    ingredients_sorted = quicksort(ingredient_list)
    while keep_choosing:
        ingredients = ingredient_filtering(ingredients_sorted)
        recipes = filter_recipes(ingredients, recipes)
        ingredient_list = get_ingredient_list(recipes)
        ingredients_sorted = quicksort(ingredient_list)
        print(f"\nWe have {len(recipes)} recipes with those ingredients.")
        keep_choosing = bolean_test("Want to choose other ingredients?")
    if len(recipes) > 5:
        recipe_choice_list = sample(recipes, 5)
    else:
        recipe_choice_list = recipes
    print("\nHere are a few suggestions! Choose one and good luck!")
    chosen_recipe = choose_recipe(recipe_choice_list, "Ok! Just choose one of those!")
    print(chosen_recipe)

## main logig for yes/no mode
def yes_no_mode():
    pass


recipe_dictionary = [
    {'id': '192281',
     'name': 'southern butter mints',
     'minutes': '15',
     'steps': 'melt cream cheese and butter in large saucepan over low heat, etc',
     'ingredients': ['cream cheese', 'butter']},
    {'id': '15017',
     'name': 'baked ricotta with parmesan and thyme',
     'minutes': '70',
     'steps': 'preheat oven to 150c, place the parmesan',
     'ingredients': ['parmesan cheese', 'thyme leaves', 'chili flakes']},
    {'id': '193618',
     'name': 'spaghetti with italian sausage  spinach  and diced tomatoes',
     'minutes': '60',
     'steps': 'boil spaghetti until al dente',
     'ingredients': ['spaghetti', 'sweet italian turkey sausage', 'diced tomatoes']}]

##Print Welcome message

title = "Find A Recipe"
title_message = """
Welcome to Find A Recipe, the Recipe suggestion app that will blow your...kitchen?!
"""
#print(render(title))
print(title_message)

##create Recipe instances from dictionary
recipe_list = []

print(recipe_dictionary)
for i in recipe_dictionary:
    id = i ["id"]
    print(id)
    #id = Recipe(i, id)
    #recipe_list.append(id)


## Get an input on suggestion mode
choose_mode = "Please, choose a suggestion mode:"
modes_list = ["Type an ingredient", "Yes or No"]
suggestion_mode = get_choice(modes_list, choose_mode)

# Based on suggestion mode, run suggestion logic
if suggestion_mode == modes_list[0]:
    type_mode()
else:
    yes_no_mode()

第二个文件包含所有逻辑 [main.py]

#import recipe_dict
from recipes import Recipe
from math import inf
from random import randrange

# ingredient list function
def get_ingredient_list(recipes):
    ingredient_list = []
    for recipe in recipes:
        for ingredient in recipe.ingredients:
            if ingredient not in ingredient_list:
                ingredient_list.append(ingredient)
    return ingredient_list


# ingredient count function
def get_ingredient_count(recipes):
    ingredient_count = {}
    for recipe in recipes:
        for ingredient in recipe.ingredients:
            if ingredient not in ingredient_count.keys():
                ingredient_count[ingredient] = 1
            else:
                ingredient_count[ingredient] += 1
    return ingredient_count


# def recipe_by_ingredient function
def get_recipes_by_ingredient(recipes, ingredient):
    recipes_by_ingredient = []
    for recipe in recipes:
        if ingredient in recipe.ingredients:
            recipes_by_ingredient.append(recipe)
    return recipes_by_ingredient


# ingredient for optimal subset function
def get_optimal_ingredient(recipes):
    best_subset_possible = len(recipes) // 2
    optimal_ing = ""
    optimal_count = inf
    ingredient_count = get_ingredient_count(recipes)
    for ingredient, count in ingredient_count.items():
        if abs(best_subset_possible - count) < abs(best_subset_possible - optimal_count):
            optimal_ing = ingredient
            optimal_count = count
    return optimal_ing


# logic for getting user recipe choice
def choose_recipe(choices, input_text):
    count = 0
    for choice in choices:
        count += 1
        print(f"{count}) {choice.name}\n")

    choice_range = [f"{num}" for num in range(1, count + 1)]
    user_choice = input(input_text)
    if user_choice not in choice_range:
        print(f"invalid input: please choose from 1 to {count}")
        choose_recipe(choices, input_text)
    else:
        return choices[int(user_choice) - 1]


# quicksort function
def quicksort(arr):
    if len(arr) <= 1: return arr
    m = arr[randrange(0, len(arr))]
    return quicksort([i for i in arr if i < m]) + \
           [i for i in arr if i == m] + \
           quicksort([i for i in arr if i > m])


# quick search in sorted list
def check_match(input, text):
    match_count = 0
    for char in range(len(input)):
        if len(input) > len(text):
            return False
        elif input[char] == text[char]:
            match_count += 1
        else:
            break
    if match_count == len(input):
        return True
    return False


def find_match(list, input):
    # base case
    if len(list) == 1:
        if check_match(input, list[0]) is True:
            return list[0]
        return "no match found..."
    # define slicers
    pivot = len(list) // 2
    start = pivot
    end = pivot
    # check for match
    if check_match(input, list[pivot]) is True:
        while start >= 0 and check_match(input, list[start]) is True:
            start -= 1
        while end <= (len(list) - 1) and check_match(input, list[end]) is True:
            end += 1
    # else call recursive steps
    else:
        if input < list[pivot]:
            return find_match(list[:pivot + 1], input)
        return find_match(list[pivot:], input)
    # return sliced list
    return list[start + 1:end]


##helper variables and functions
def bolean_test(prompt):
    user_input = input(f"{prompt} [y/n]")
    if user_input.lower() == "y":
        return True
    elif user_input.lower() == "n":
        return False
    else:
        return bolean_test(prompt)


def get_choice(choices, input_text):
    count = 0
    for choice in choices:
        count += 1
        print(f"{count}) {choice}\n")

    choice_range = [f"{num}" for num in range(1, count)]
    user_choice = input(input_text)
    if user_choice not in choice_range:
        print(f"invalid input: please choose from 1 to {count}")
        return get_choice(choices, input_text)
    else:
        return choices[int(user_choice) - 1]


# ingredient filtering logic
def ingredient_filtering(ingredient_list):
    search_ingredient_input = input("Type the first letter or first few letters of the ingredient you are looking for:")
    match = find_match(ingredient_list, search_ingredient_input)
    if type(match) is list:
        print("\nMatches found:\n")
        for i in match:
            print(i)
        test = bolean_test("Want to filter some more?")
    elif type(match) is str:
        print(match)
        test = False
    if test is True:
        return ingredient_filtering(match)
    else:
        if type(match) is list:
            return match
        return ingredient_list


# recipe filtering logic
def filter_recipes(ingredients, recipes):
    recipes_filtered = []
    for i in ingredients:
        subset = get_recipes_by_ingredient(recipes, i)
        for r in subset:
            if r not in recipes_filtered:
                recipes_filtered.append(r)
    return recipes_filtered

第三个包含我遇到问题的课程,称为 [recipes.py]

class Recipe():
    def __init__(self, dict, id):
        self.id = id
        self.name = dict["name"]
        self.minutes = dict["minutes"]
        self.steps = eval(dict["steps"])
        self.ingredients = eval(dict["ingredients"])

    def has_ingredient(self, ingredient):
        return ingredient in self.ingredients

    def __str__(self):
        print(self.name.title() + "\n")
        print(f"Preparation time: {self.minutes} minutes \n")
        print("Ingredients:")
        for i in self.ingredients:
            print(f"- {i};")
        print("\nPreparation Steps:")
        for s in self.steps:
            print(f"- {s};")
        return ""

当我将数据库移动到一个文件中时,我盯着一大堆错误

标签: python

解决方案


第三个是我遇到问题的课程

这些行中至少有一条会失败,因为您正在尝试使用eval()非 Python 代码。

self.steps = eval(dict["steps"])
self.ingredients = eval(dict["ingredients"])

参考

 'steps': 'melt cream cheese and butter in large saucepan over low heat, etc',
 'ingredients': ['cream cheese', 'butter']},

例如

>>> eval('melt cream cheese and butter in large saucepan over low heat, etc')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    melt cream cheese and butter in large saucepan over low heat, etc
         ^
SyntaxError: invalid syntax

相反,你应该让你的类像这样(或者更好,使用 dataclass

class Recipe():
    def __init__(self, id, name, minutes, steps, ingredients):
        self.id = id
        self.name = name
        self.minutes = minutes
        self.steps = steps
        self.ingredients = ingredients

然后消除对字典的需要

##create Recipe instances
recipe_list = [
    Recipe(id='192281',name='southern butter mints', minutes='15', steps='melt cream cheese and butter in large saucepan over low heat, etc', ingredients=['cream cheese', 'butter']), 
...
]

如果您希望in recipes条件工作,您需要__eq__在该类中实现功能。如果您希望能够对列表进行排序,那么__cmp__

如果您想要一个可以过滤、排序和查询的适当数据库,请从sqlite3


推荐阅读