MrN3MESIS MrN3MESIS - 3 months ago 15
Python Question

python cant use a function to change the value of a variable

I'm rather new to python and was wondering why the function and therefore the if statement returns "100" instead of "83" in the code below. I'm not sure if I'm missing something obvious but it seems as if it should work.This is the code I'm refering to:

playerhp = 100
def attack1(x):
x = (x - 17)
return x

while playerhp > 0:
enemyattack = input("please type the word 'attack': ")
if enemyattack.upper() == "ATTACK":
attack1(playerhp)
print(playerhp)
else:
break

Answer

As mentioned in a comment above, this issue comes down to scoping. Try googling that for more info, but I'll try to give a beginner level explanation here.

When you declare a variable, it exists in a specific scope, and can only be accessed by variables in the same or a lower scope. For example,

var1 = 5
if var1 < 6:
   print(var1)
   var2 = 7
print(var2) #error on this line

var1 exists in the highest scope in this example, so it is accessible to lower onse, so the print(var1) line works fine. However, var2 is in a higher scope than the statement attempting to print it, and as such it cannot find the variable. Since Python forces nice formatting, you can think of scope broadly as each level of indentation. If you have to go to a section more indented, it can find it, but if you need to go through a section that is less indented to find it, then you can't.

This extends to functions. Your function attack1 exists in a different scope than what is inside your while loop, and the variable x only exists within that function. As such, when you modify x, it only modifies it in that scope, not the original. It is beyond the scope of your original question, but look up what passing by value and passing by reference mean, and how they apply to Python. As other answers point out, you can fix this by assigning the return value of x to the original number you are passing in, i.e.

playerhp = attack1(playerhp)

to take the new number, 17 less than it used to be, and reassign it to the original value, so it assumes this new value instead.

Edit with regards to what other answers suggest

Some people suggest modifying the global variable directly. (I'm assuming Python 3 here, I don't know which version you're using or if Python 2 is even different), you can do that. Python is a little funny about scoping out of functions, but it is simple to rewrite your attack function like this:

def attack1():
   global playerhp
   playerhp -= 17 #shortcut to subtract 17, same as playerhp = playerhp - 17

and you can call it simply with

attack1()

and it will work the same way. Many programmers would shy away from using global variables if you can avoid it, but that is very subjective and they'll fight all day about that until the end of time.