Python - 遍历嵌套字典根据值填充列表时遇到'是'对象没有属性'items
我正在写一段代码,目的是让用户可以从一个列表中选择多个物品。每个用户都有一个固定的空间,而每个物品都有一个特定的大小。我想根据物品的稀有程度来填充这个列表,并且只显示那些大小在用户剩余空间以内的物品。
但是,一旦用户选择了一个物品,列表更新后只显示那些在他们剩余大小范围内的物品,显示列表的代码就不再工作了,并且出现了以下错误:
AttributeError: 'str' object has no attribute 'items'
user_stage1_objects = []
selected_objects_size = 0
timeframe1 = {
"Option1": {
"Common": [{"Item Name": "A1", "Size": 3}, {"Item Name": "A2", "Size": 4}],
"Uncommon": [{"Item Name": "B1", "Size": 2}, {"Item Name": "B2", "Size": 1}]
},
"Option2": {
"Common": [{"Item Name": "C1", "Size": 3}, {"Item Name": "C2", "Size": 1}],
"Uncommon": [{"Item Name": "D1", "Size": 2}, {"Item Name": "D2", "Size": 4}]
}
}
timeframe2 = {
"Option1": {
"Common": [{"Item Name": "A1", "Size": 3}, {"Item Name": "A3", "Size": 2}],
"Uncommon": [{"Item Name": "B1", "Size": 2}, {"Item Name": "B2", "Size": 1}]
},
"Option2": {
"Common": [{"Item Name": "C2", "Size": 1}, {"Item Name": "C3", "Size": 3}],
"Uncommon": [{"Item Name": "D1", "Size": 2}, {"Item Name": "D2", "Size": 4}]
}
}
def stage1_selection():
global max_amount_limit, selected_objects_size, available_objects_list, user_stage1_objects
objects_chosen = None
user_stage1_objects = []
available_objects_list = []
timeframe_choice = input("""
Select Timeframe1 or Timeframe2
1 - Timeframe1
2 - Timeframe2
> """)
if timeframe_choice == "1":
chosen_timeframe = timeframe1
elif timeframe_choice == "2":
chosen_timeframe = timeframe2
else:
print("Not a valid choice, try again")
while objects_chosen is None:
if (max_amount_limit - selected_objects_size) > 3:
if chosen_timeframe == timeframe1:
available_objects_list = timeframe1["Option1"]["Common"]
elif chosen_timeframe == timeframe2:
available_objects_list = timeframe2["Option2"]["Common"]
elif (max_amount_limit - selected_objects_size) < 4:
available_objects_list = []
if chosen_timeframe == timeframe1:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 4
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe1.items()
if option == "Option1"
}
elif chosen_timeframe == timeframe2:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 4
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe2.items()
if option == "Option1"
}
elif (max_amount_limit - selected_objects_size) < 3:
available_objects_list = []
if chosen_timeframe == timeframe1:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 3
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe1.items()
if option == "Option1"
}
elif chosen_timeframe == timeframe2:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 3
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe2.items()
if option == "Option1"
}
object_availability = available_objects_list
object_itr = 0
for i in object_availability:
print(object_itr, end=' - ')
for key, val in i.items():
print(key, ": ", val, end='\n ')
print()
object_itr = object_itr+1
chosen_object_index = input("> ")
chosen_object_index = int(chosen_object_index)
user_stage1_objects.append(object_availability[chosen_object_index]["Item Name"])
selected_objects_size = selected_objects_size + object_availability[chosen_object_index]["Size"]
if max_amount_limit == selected_objects_size:
objects_chosen = "Done"
else:
continue_object_selection = input("""
You have """+str(int(max_amount_limit - selected_objects_size))+""" amounts left.
Do you want to select more objects from Option1, or move on to Option2?
1 - Continue with Option1
2 - Move on to Option2
>""")
if continue_object_selection == "1":
objects_chosen is None
elif continue_object_selection == "2":
objects_chosen - "Done"
else:
print("Not a valid choice, try again")
def fill_chosen_objects():
global max_amount_limit, selected_objects_size, available_objects_list, user_stage1_objects
max_amount_limit = 5
selecting_objects = input("""
Would you like to see available choices from Option1?
1 - Yes
2 - No
> """)
if selecting_objects == "1":
stage1_selection()
elif selecting_objects == "2":
objects_chosen = "Done"
return user_stage1_objects
fill_chosen_objects()
抱歉这里代码有点长,但我之前尝试过发一些小段代码,结果在大代码中应用时又不行。
基本上,一旦用户考虑了最大限制(max_amount_limit)和他们已经选择的物品总大小,他们就不应该看到任何大于他们剩余空间的物品。
我第一次能看到物品列表,但当我尝试查看列表选择第二个物品时就崩溃了。
在这一行出现了AttributeError: 'str' object has no attribute 'items'的错误:
for key, val in i.items():
谢谢
2 个回答
1
你多次把你的 available_objects_list
变量赋值为一个字典里的值。
当你用 for i in object_availability:
来遍历字典时,i
会被设置为字典的键,而在你的情况中,这些键是字符串。
比如,你可以把:
available_objects_list = {
options: {
rarity: [
item for item in items
if item["Size"] < 4
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe1.items()
if option == "Option1"
}
换成
available_objects_list = [
{
options: {
rarity: [
item for item in items
if item["Size"] < 4
]
for rarity, items in options.items()
if rarity == "Common"
}
for option, options in timeframe1.items()
if option == "Option1"
}
]
1
看看这个简化的例子,它可以计算剩余的空间,并给用户提供一个可以放进去的物品列表。我觉得这可能会帮助你解决问题。
def get_timeframe():
timeframe1 = {
"Option1": {
"Common": [
{"Item Name": "A1", "Size": 3},
{"Item Name": "A2", "Size": 4}
],
"Uncommon": [
{"Item Name": "B1", "Size": 2},
{"Item Name": "B2", "Size": 1}
]
},
"Option2": {
"Common": [
{"Item Name": "C1", "Size": 3},
{"Item Name": "C2", "Size": 1}
],
"Uncommon": [
{"Item Name": "D1", "Size": 2},
{"Item Name": "D2", "Size": 4}
]
}
}
timeframe2 = {
"Option1": {
"Common": [
{"Item Name": "A1", "Size": 3},
{"Item Name": "A3", "Size": 2}
],
"Uncommon": [
{"Item Name": "B1", "Size": 2},
{"Item Name": "B2", "Size": 1}
]
},
"Option2": {
"Common": [
{"Item Name": "C2", "Size": 1},
{"Item Name": "C3", "Size": 3}
],
"Uncommon": [
{"Item Name": "D1", "Size": 2},
{"Item Name": "D2", "Size": 4}
]
}
}
while True:
timeframe_choice = input("""
Select Timeframe1 or Timeframe2
1 - Timeframe1
2 - Timeframe2
> """)
if timeframe_choice == "1":
return timeframe1
if timeframe_choice == "2":
return timeframe2
print("Not a valid choice, try again")
def select_item(available_objects_list):
while True:
for index, item in enumerate(available_objects_list):
print(index, item)
chosen_object_index = int(input("Pick One: "))
try:
return available_objects_list[chosen_object_index]
except IndexError:
pass
def stage1_selection(max_amount_limit, chosen_timeframe):
user_stage1_objects = []
available_objects_list = []
option_choice = "Option1"
while (remaining_space := max_amount_limit - sum(item["Size"] for item in user_stage1_objects)) > 0:
print(f"You have {remaining_space} space left in your pack.")
available_objects_list = [
{**item, **{"rarity": rarity}}
for rarity, items in chosen_timeframe[option_choice].items()
for item in items
if item["Size"] <= remaining_space
]
user_stage1_objects.append(select_item(available_objects_list))
return user_stage1_objects
max_amount_limit = 5
chosen_timeframe = get_timeframe()
user_stage1_objects = stage1_selection(max_amount_limit, chosen_timeframe)
print("You have selected: ")
for item in user_stage1_objects:
print(f"\t{item}")