Copying a dictionary into another dictionary - python

I'm working on a game and one of the commands, one to pickup items, is not working. The code pretty much checks to see if the item is in the room and if it is then to copy that to the players inventory and then delete the item from the room. However no matter what I try it either does nothing or copies the keys inside to the dictionary.
Here's the code:
def pickup(self, item):
conf = input('Do you want to pick up the ' + item.lower() + ': ')
if conf.lower() == 'y' or 'yes':
try:
self.inventory.update(room[self.room_number]['items'][item])
del room[self.room_number]['items'][item]
except KeyError:
print('You look everywhere but can\'t find a ' + item.lower())
else:
print('You consider it, but decide not to pick up the ' + item.lower())
When I print the inventory dictionary I get this
player.inventory
{
'type': 'weapon',
'equippable': True,
'value': 0,
'desc': 'a wooden stick, could be useful',
'name': 'Wooden Stick',
'perks': {
'defense': 0,
'health': 0,
'damage': 6,
'magic_damage': 0
}
}
or
{}
What I want is this:
player.inventory
{
'wooden stick':{
'type': 'weapon',
'equippable': True,
'value': 0,
'desc': 'a wooden stick, could be useful',
'name': 'Wooden Stick',
'perks': {
'defense': 0,
'health': 0,
'damage': 6,
'magic_damage': 0
}
}
Does anybody know how I can get this result. Nothing I try seems to work and I have checked to see whether anyone has answered this but can't find anything on it.
Thanks :)

You're using the wrong function. In this line:
self.inventory.update(room[self.room_number]['items'][item])
update will essentially add all the keys and values from room[self.room_number]['items'][item] to self.inventory.
Instead, you want to assign the item dictionary as a value in the inventory dictionary, with a key for that item.
So you should do this:
self.inventory[item] = room[self.room_number]['items'][item]
Or better yet, as #MKesper points out, you should pop the key so that it's removed from the room's items dictionary when you put it into the inventory:
self.inventory[item] = room[self.room_number]['items'].pop(item, None)
This will attempt to get item out of the dictionary, and if it's not found None will be returned instead. If you remove None you'll instead have a KeyError, and depending on how confident you are in item being a valid key, a KeyError might be better to catch the unusual cases when incorrect keynames have appeared.
Docs on dict.pop

You can use update method:
dict1.update(dict2)

Related

Why can't python properly define the variable

So I've been stuck wondering why I keep getting a key error, I defined the variables needed (items to store the list of key in the dictionary 'a' (Salad, soup, canapes)) and the dictionary is properly setup. I've managed to narrow it down to the fact that it defines items as the list of keys for the dictionary a, but is unable to use it outside of the .join function I used. Why am I getting a key error for items?
Any and all help is appreciated.
#Dictionaries#
a = {'SALAD': {'CAPRESE SALAD': 15, 'CEASAR SALAD BITE': 15, 'EGG SALAD': 15},
'SOUP': {'PUMPKIN COCONUT SOUP': 15, 'TOMATO SOUP': 15, 'CREAMY BROCCOLI SOUP': 15},
'CANAPES': {'BACON DEVILLED EGGS': 15, 'HALLOUMI DIPPERS': 15, 'MINI PARMA HAM VEGGIE TARTS': 15}}
#obtaining the key from the dictionary 'a'#
class keyretrieval:
def __init__(self, v, meal):
#setting up title for dialog box#
title = meal.capitalize()
items = getList(v)
inp = simpledialog.askstring(title, 'what would you like for your ' + meal + '?\nwe have ' + ', '.join(items))
#matching user casing to dictionary casing#
inp = inp.upper()
#other class used that I didn't copy onto here#
key = Menucheckkey(inp, items)
self.choice = key
#getting a key from a, appetizer is only used for the dialog box#
akey = keyretrieval(a, 'appetizer')
theres no "appetizer" key in the 'a' dictionary
If you want your code to insert a new key when an object is initialized, you can try adding the following to your init function
v.update({title : items})

TypeError -- list indices must be integers or slices, not str

I am working on automating the processes of connecting to the switch and upgrading the image. Code I have so far is:
def check_redundancy(task):
get_redundancy = task.run(task = netmiko_send_command, command_string = 'show redundancy summary', use_ttp = True, ttp_template = ' ')
task.host['redundancy'] = get_redundancy.result
results = 'SHOW REDUNDANCY INFO'
print(task.host['redundancy'])
return Result(host = task.host, result = results)
def verify_redundancy(task):
peer_state = 'ACTIVE'
for i in task.host['redundancy']:
if i['peer_state'] == peer_state:
results = str(f"Redundancy check, looking for {i['peer_state']} -- found")
check = 'Y'
task.host['check'] = 'Y'
else:
results = str(f"Redundancy check, looking for {i['peer_state']} -- did not find it")
check = 'N'
task.host['check'] = 'N'
return Result(host=task.host, result=f"{(Style.BRIGHT)} {(Fore.WHITE)}{(Back.GREEN)} {results}",check=check)
return Result(host=task.host, result=f"{(Style.BRIGHT)} {(Fore.WHITE)}{(Back.YELLOW)} {results}",check=check)
task.host['redundancy'] output looks like this:
[ [ { 'redundancy': { 'link_encryption': 'ENABLED',
'local_state': 'STANDBY HOT',
'mobility_mac': 'xxx',
'peer_state': 'ACTIVE',
'redundancy_mode': 'SSO ENABLED',
'redundancy_port': 'UP',
'redundancy_state': 'SSO',
'unit': 'Primary',
'unit_id': 'xxx',
'verage_management_gateway_reachability_latency': '933 '
'Micro '
'Seconds',
'verage_redundancy_peer_reachability_latency': '293 '
'Micro '
'Seconds'}}]]
After I run this, I get error:
if i['peer_state'] == peer_state:
TypeError: list indices must be integers or slices, not str
Any ideas how to fix this so I can look at the output and see compare the peer_state?
Thank you in advance
Your JSON object contains 2 lists within each other.
If you do:
for i in task.host['redundancy']
you only tap into the first. Depending on how your object scales you should probably add another loop or remove unnecessary lists.

Aggregation in function not working right

Hello so I have a python function that's working but not in the way I expect and I'm not sure where my code is off.
def preprocess(text):
case = truecase.get_true_case(text)
doc = nlp(case)
return doc
def summarize_texts(texts):
actions = {}
entities = {}
for item in texts:
doc = preprocess(item)
for token in doc:
if token.pos_ == "VERB":
actions[str.lower(token.text)] = actions.get(token.text, 0) +1
for token in doc.ents:
entities[token.label_] = [token.text]
if token.text not in entities[token.label_]:
entities[token.label_].append(token.text)
return {
'actions': actions,
'entities': entities
}
when I call the function for a list of sentences, this is the output I get:
docs = [
"Play something by Billie Holiday, and play again",
"Set a timer for five minutes",
"Play it again, Sam"
]
summarize_texts(docs)
output: {'actions': {'play': 1, 'set': 1},
'entities': {'PERSON': ['Sam'], 'TIME': ['five minutes']}}
It it's working in that it's finding the action keys and entities keys but I am having two issues.
it's not counting the actions right
it's only storing the last value of each entity.
output should be:
output: {'actions': {'play': 3, 'set': 1},
'entities': {'PERSON': ['Billie','Sam'], 'TIME': ['five minutes']}}
Any help would be AMAZING! I have a feeling its something easy but just too brain fried to see it.
You're replacing the data structures, not simply updating the values. You only want to create a new container if does not exist at that point.
For actions:
if token.pos_ == "VERB":
action_key = str.lower(token.text)
if action_key not in actions:
actions[action_key] = 0
actions[action_key] += 1
For entities:
for token in doc.ents:
entity_key = token.label_
entity_value = token.text
if entity_key not in entities:
entities[entity_key] = []
if entity_value not in entities[entity_key]:
entities[entity_key].append(entity_value)
As a note, you can simplify this logic by using a defaultdict. You can also use a set rather than checking the list for duplicates each time
actions = defaultdict(int)
entities = defaultdict(set)
...
if token.pos_ == "VERB":
actions[str.lower(token.text)] += 1
...
for token in doc.ents:
entities[token.label_].add(token.text)
You're not consistent in converting the token to lowercase. You use the lowercase version when assigning to the dictionary, but the original case when calling actions.get(). So if the token has mixed case, you'll keep on getting the default when you call actions.get(), and keep setting it to 1.
actions[token.text.lower()] = actions.get(token.text.lower(), 0) +1

Create batch records with Odoo create method

I am trying to create multiple invoices from an array of dictionaries with the create values in odoo13.
Creating one record at a time is okay but when I try with the batch record I get the error can't adapt to type dict
I have tried looping through the array and create a record for each item in it but this error persists.
I am currently checking on the #api.model_create_multi decorator but haven't grasped it yet fully.
What I want is that for each line in the visa_line(same as order line), to create an invoice from that. Some fields in creating an invoice are missing but that should not be the issue.
When I print the record, in the final function, it prints the duct with values correctly.
Here is my code, thank you in advance
def _prepare_invoice(self):
journal = self.env['account.move'].with_context(
default_type='out_invoice')._get_default_journal()
invoice_vals = {
'type': 'out_invoice',
'invoice_user_id': self.csa_id and self.csa_id.id,
'source_id': self.id,
'journal_id': journal.id,
'state': 'draft',
'invoice_date': self.date,
'invoice_line_ids': []
}
return invoice_vals
def prepare_create_invoice(self):
invoice_val_dicts = []
invoice_val_list = self._prepare_invoice()
for line in self.visa_line:
invoice_val_list['invoice_partner_bank_id'] = line.partner_id.bank_ids[:1].id,
invoice_val_list['invoice_line_ids'] = [0, 0, {
'name': line.code,
'account_id': 1,
'quantity': 1,
'price_unit': line.amount,
}]
invoice_val_dicts.append(invoice_val_list)
return invoice_val_dicts
#api.model_create_multi
def create_invoice(self, invoices_dict):
invoices_dict = self.prepare_create_invoice()
for record in invoices_dict:
print(record)
records = self.env['account.move'].create(record)
I fixed this issue by explicitly type fixing the record with duct. Using a normal create method without the #api.model_create_multi.
def create_invoice(self):
invoices_dict = self.prepare_create_invoice()
for record in invoices_dict:
records = self.env['account.move'].create(dict(record))

Creating dictionaries inside dictionaries based on user input

New to programming, and teaching myself by making a to-do list app that stores things to do in a dictionary called ThingsToDo, based on user input. I'm using the dict.update function, which is working, but I want to add a feature so that in the dictionary ThingsToDo, every time a user inputs a new thing to do, it stores the new item as a dictionary inside ThingsToDo, with things like Due Date, and Status inside that sub-dictionary. How can I do this?
Here is the code so far (just started):
ThingsToDo = {}
while True:
item = input("What do you need to do? ")
DueDate = input("When do you need to do it by? ")
status = "Not done."
ThingsToDo.update({
"Item": item,
"Due Date": DueDate,
"Status": status,
})
print(ThingsToDo)
First I suggest you to think about what will be the key(s) of your dictionary(ies). I can suggest you this simple solution using "what you need to do" as a key. It works well:
ThingsToDo = {}
while True:
item = input("What do you need to do? ")
DueDate = input("When do you need to do it by? ")
status = "Not done."
ThingsToDo.update({item: {"Due Date": DueDate, "Status": status}})
print(ThingsToDo)
Output example:
What do you need to do? Wash the car
When do you need to do it by? 2018/09/01
{'Wash the car': {'Due Date': '2018/09/01', 'Status': 'Not done.'}}
What do you need to do? Sort papers
When do you need to do it by? 2018/08/23
{'Wash the car': {'Due Date': '2018/09/01', 'Status': 'Not done.'},
'Sort papers': {'Due Date': '2018/08/23', 'Status': 'Not done.'}}
You have "many" things to do, so you can put that dict in a list, or a dict.
You cannot put that in a set beacuse it has to be hashable.
If you chose a dict, you have to chose a "key" for each element, right?
You can read about "data structures" here .
Let's try list :
thingsToDo = []
newThingToDo = {
'Item': 'I need a haircut',
'DueDate': 'Right now',
'Status': 'Done'
}
thingsToDo.append(newThingToDo)
Using a dict would allow you to order your tasks, but I'm not sure it is your question. Let's try ordering your tasks by adding a number.
thingsToDo = {}
newThingToDo = {
'Item': 'I need a haircut',
'DueDate': 'Right now',
'Status': 'Done'
}
thingsToDo[5] = newThingToDo
So your haircut is task number 5.
If you choose the dict way, your code could look like this :
# -*- coding: utf-8 -*-
thingsToDo = {}
while True:
n = int(input("How many tasks do you want to add?"))
for i in range(n):
item = input("What do you need to do? ")
duedate = input("When do you need to do it by? ")
status = "Not done."
newThingToDo = {
'Item': item,
'DueDate': duedate,
'Status': status
}
thingsToDo[i] = newThingToDo
print(thingsToDo)

Categories