Значение словаря не изменяется внутри назначения цикла for

#python #dictionary

#python #словарь

Вопрос:

Итак, я изучаю python, используя Learn python the hard way. Я пытаюсь разработать систему инвентаризации. Цель состоит в том, чтобы встроить это в класс, который будет извлекаться классом room . Я собираюсь использовать словарь для инвентаря, чтобы при создании инвентаря для каждой комнаты я мог сказать, где они находятся в комнате.

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

Прямо сейчас я работаю над тем, чтобы забрать элемент, когда кто-то говорит «возьми нож». Я могу выполнить странный поиск и установить для этого значения значение None, чтобы, когда кто-то заглядывает в комнату, оно не отображалось, но, похоже, я столкнулся с проблемой области видимости. Я прочитал несколько других вопросов на этом сайте, в которых говорилось, что, поскольку это изменяемый объект, мне не нужно выполнять глобальный dict, и когда я попытался это сделать, он получил ошибку. Я могу редактировать объект, но когда я возвращаюсь к своему оператору if и циклу for, он не будет перенесен.

Пожалуйста, помогите мне 🙂

 #This is the inventory in this room
inventory = {'desk': 'Miniature Fusion Warhead',  
         'bed':'knife', 'sink':None}        
def take(item):
    if item in inventory.itervalues():
        #add_item_to_inventory(item)

        for key, value in inventory.iteritems():

            if value == item:
                print ("Wow.n"
                    "Look at you.n"
                    "Picking shit up and everything.")
                value = None


    else:
        print ("What do you think this is?"
            "  The dollar store?  We don't "
            "got that shit here!")


# Prints out what items are in the room.  
# I am hoping to later come up with an idea for how
# To make different variations of this, and have it randomly
# pick between the different ways it says what it sees.
for key, value in inventory.iteritems():
    if value != None:
        print "You see a %s on the %s." % (value, key)
print "What do you want to pick up?"
ui = raw_input(">")
split_ui = ui.split()
print split_ui

if len(split_ui) > 1:
    if split_ui[0] == "take":
        print ("You reach over to grab the %s."
            "n...") % split_ui[1]
    take(split_ui[1])

    else:
        print ("What you talking bout Willis?  "
            "Don't you know this is just about "
            "takin shit.")
else:
    print ("Who taught you how to talk?"
        "n...nLet me show you how its done.n"
        "Use a verb, like take, then throw in an "
        "object like knife.")

print inventory
  

Это результат, который мне дают.

 You see a knife on the bed.
You see a Miniature Fusion Warhead on the desk.
What do you want to pick up?
>take knife
['take', 'knife']
You reach over to grab the knife.
...
Wow.
Look at you.
Picking shit up and everything.
{'sink': None, 'bed': 'knife', 'desk': 'Miniature Fusion Warhead'}
  

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

Спасибо!

Комментарии:

1. не могли бы вы очистить синтаксис вашего примера кода?

Ответ №1:

value Внутри вашего цикла отличается от реального значения словаря. Это просто ссылка на это значение, поэтому, когда вы это делаете value = None , вы фактически изменяете значение ссылки, чтобы сохранить новое значение None , а не значение словаря.

Чтобы лучше продемонстрировать это, это перед назначением внутри for key, value in inventory.iteritems():

 -------            -------------------------
|value|   -------> |value of the dictionary|
-------            -------------------------
  

это после value = None

                    -------------------------
                   |value of the dictionary|
                   -------------------------
-------            ------
|value|   -------> |None|
-------            ------
  

Как вы можете видеть, значение словаря не меняется. Изменяется только переменная value for цикла
. Эта переменная принадлежит области действия for цикла, и после этого она отбрасывается.

Альтернативой было бы вместо value = None делать:

 inventory[key] = None
  

Комментарии:

1. Или del inventory[key] , и при получении из словаря, используйте inventory.get(key, None) . Это был бы более надежный способ сделать это.

2. Большое вам спасибо за помощь! Это решило мою проблему. Я изо всех сил пытался придумать способ поиска ключа на основе значения, и я как бы объединил некоторые другие решения, и это сработало, поэтому я побежал с ним. Я никогда не думал о том факте, что на самом деле я менял не словарь, а переменную, которую я установил на значение словаря. Ваш пример действительно помог мне понять, спасибо, что научили меня, а не просто дали мне ответ!

Ответ №2:

zbs верен, вы только меняете значение указателя на значение dict . Однако вы делаете это слишком сложно:

 #This is the inventory in this room
inventory = {'Miniature Fusion Warhead': 'desk',
             'knife':'bed'}
player_inventory = set()

def take(item):
  if item in inventory:
    print("You picked up the {}".format(item))
    player_inventory.add(item)
    del inventory[item]

  else:
    print("That item doesn't exist")

while True:
  print('')
  print("Inventory: "   ', '.join(player_inventory))
  for k,v in inventory.items():
    print("You see a {} on the {}".format(k, v))

  print("What do you want to pick up?")
  ui = raw_input("> ").split()
  verb = ui[0]
  item = ' '.join(ui[1:])
  if verb == 'take':
    if item:
      print("You take the {}".format(item))
      take(item)
    else:
      print("That item doesn't exist")
  else:
    print("That's not an action")