In a new function, how would I return the KEY from a passed-in dictionary in Python?

102 Views Asked by At

I've created a function that requests two parameters and the second (current_resource) is taking in a value from an out of scope dictionary and comparing the value against a user request. I am returning the values as f-strings, but instead of the value returned I want the key returned.

The function:

def check_resources(order, current_resource):
    """Checks if resources are greater than the items requirements. If so, returns order. Or Returns missing req."""
    if order > current_resource:
        return f"Sorry there is not enough {current_resource}"
    elif current_resource > order:
        return f"Okay, here is your order."

The requesting code:

print(check_resources(MENU["espresso"]["ingredients"]["water"], current_inventory["water"]))

It is checking a dictionary where I have the keys and values stored, in this case above, I am comparing it to the value of "water". And when returned, it returns an INT in the form of the value.

I am in search for way to return the Key name in the F-string.

I have tried using the .key() method such as:

current_resource.key()

but it returns the error:

AttributeError: 'int' object has no attribute 'key'.

3

There are 3 best solutions below

0
Hermann12 On

You send only the value to the function, so than you can’t get back the key:

def check_resources(order, current_resource):
    print(order, current_resource)
    """Checks if resources are greater than the items requirements. If so, returns order. Or Returns missing req."""
    if int(order) > int(current_resource):
        return f"Sorry there is not enough {current_resource} "
    elif int(current_resource) > int(order):
        return f"Okay, here is your order."

current_inventory = {"water": "120"}
MENU = {"espresso" : "2","ingredients" : "2", "water" : "100"}
print(check_resources(MENU["water"], current_inventory["water"]))

current_inventory = {"water": "120"}
MENU = {"espresso" : "2","ingredients" : "2", "water" : "200"}
print(check_resources(MENU["water"], current_inventory["water"]))

Output:

100 120
Okay, here is your order.
200 120
Sorry there is not enough 120 

How looks you dictionary input?

As one possible solution, you can send the whole dict:

import re

def check_resources(order, current_resource):
    """Checks if resources are greater than the items requirements. If so, returns order. Or Returns missing req."""
    order = [float(order["water"]) for order["water"] in re.findall(r'\d+', order["water"])]
    current_res = [float(current_resource["water"]) for current_resource["water"] in re.findall(r'\d+', current_resource["water"])]
                                                                                              
    if order > current_res:
        return f"Sorry there is not enough {list(current_resource.keys())[0]}"
    elif current_res > order:
        return f"Okay, here is your order."

current_inventory = {"water": "120 ml"}
MENU = {"espresso" : "2","ingredients" : "Arabica 10 g", "water" : "100 ml"}
print(check_resources(MENU, current_inventory))

current_inventory = {"water": "120 ml"}
MENU = {"espresso" : "2","ingredients" : "Robusta 12 g", "water" : "200 ml"}
print(check_resources(MENU, current_inventory))

Output:

Okay, here is your order.
Sorry there is not enough water 

Be aware, if resource is equal order you get None as result with your condition gt or lt, only!

0
Alkurion On

The error you're getting is because you're passing an integer and trying to use the .key() method on an integer instead of a dictionary.

If you want the name of the resource to return in the f-string. You could pass the name of the resource instead of the value and just lookup the dict value in the function.

def check_resources(order: int, resource_name: str) -> str:
"""Checks if resources are greater than the items requirements. If so, returns order. Or Returns missing req."""
if order > current_inventory[resource_name]:
    return f"Sorry there is not enough {resource_name}"
elif current_inventory[resource_name] >= order:
    return f"Okay, here is your order."

if __name__ == "__main__":
MENU = {
    "espresso": {
        "ingredients": {
            "water": 15,
        }
    }
}
current_inventory = {
    "water": 13
}

print(check_resources(MENU["espresso"]["ingredients"]["water"], "water")) # Sorry there is not enough water
2
David On

When you call the function like this you pass as parameters the value of the key, which in this case is a number, a primitive value, so you don't have a way back to the key or the object that holds the key.

  print(check_resources(MENU["espresso"]["ingredients"]["water"], current_inventory["water"]))

One solution to your problem would be to pass the keys as parameters instead of the values and access the dictionaries inside the functions, something like this

def check_resources(menuKey, inventoryKey):
    if menu[menuKey] > current_inventory[inventoryKey]:
        return f"Sorry there is not enough {inventoryKey}"
    elif current_inventory[inventoryKey] > menu[menuKey]:
        return f"Okay, here is your order."

But with this option, now you'll need to use something mentioned in this post Access nested dictionary items via a list of keys? if you want to keep calling objects like MENU["espresso"]["ingredients"]["water"]. Of course, there are multiple options to solve this issue but essentially you can't get the object key you used to pass the value.