Why is my function not able to access my variable?

I am currently working on this exercise: https://www.codecademy.com/paths/computer-science/tracks/cspath-cs-101/modules/cspath-python-dictionaries/lessons/using-dictionaries/exercises/pop-a-key

I thought it would make this exercise simpler to just write a function for this, but the code threw an error when it tried to access the global variable health_points. Why can’t my function see health_points?

available_items = {"health potion": 10, "cake of the cure": 5, "green elixir": 20, "strength sandwich": 25, "stamina grains": 15, "power stew": 30} health_points = 20 print(health_points) def hp_up(item): health_points+= available_items.pop(item, 0) print(health_points) hp_up("stamina grains") hp_up("power stew") hp_up("mystic bread")

If you want to have the best chances of getting a useful answer quickly, make sure you follow our guidelines about how to ask a good question. That way you’ll be helping everyone – helping people to answer your question and helping others who are stuck to find the question and answer! :slight_smile:

You’ve probably come across it but functions have their own scope, they do however have access to names in outer scopes through normal LEGB rules. However, accessing names and assigning them is very different; assignment in the body of the function creates a name local to the function.

So to answer the part about why your function cannot see health_points: the issue is that the local name health_points caused by the assignment shadows the global/module name health_points. An UnboundLocalError is thrown, the function level LOCAL name health_points (not the outer scope one) has not yet been assigned/bound to a value.

Long story short you cannot both read from the global name health_points and assign to a function local name health_points like this (you’re mixing up a local name x with the global name x and Highlander rules apply). The local name is set before you ever run your function (to dig much deeper you’d need to know a little about Python’s compile steps so I’ll stop here).

For a little more info and some short examples: https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value

An ideal solution for this might be encapsulating this in a class, then you can have an instance level attribute that you pass around and update accordingly. Re-working your function and making use of return might be a tolerable solution here, technically you can also make use of the global statement but it is strongly discouraged, it is rarely the right choice.

3 Likes