-2

This works when I take it out of a function but it doesn't when it is a function. I keep on getting an UnboundLocalError and I'm not sure why.

import time
import random
mobhp = random.randint(10,40)
def fun1():
    print("You have chosen option number 1")
    #time.sleep(1)
    print("You attept an attack")
    #time.sleep(2)
    cointoss = 1
    if cointoss == 1:
        print("Attack successfull!")
        playerDam = random.randint(10,60)
        newmobhp = mobhp - playerDam
        print("You did",playerDam,"Damage")
        print(mobhp)
        print("^old hp^")
        print("VNew hpV")
        print(newmobhp)
        mobhp = newmobhp
        print("updated HP")
        print(mobhp)
def main():
    fun1()
main()
Roger Fan
  • 4,945
  • 31
  • 38
John Brook
  • 11
  • 2
  • 1
    You should include the error and the full stack trace in the question. – Roger Fan Sep 29 '14 at 22:03
  • 1
    initialize `mobhp` before use it – Hasan Ramezani Sep 29 '14 at 22:04
  • The full error message is rather clear: "UnboundLocalError: local variable 'mobhp' referenced before assignment" – Pascal Le Merrer Sep 29 '14 at 22:07
  • 1
    You are not passing mobhp as a parameter of your function.... def fun1(mobhp): – Daniel Sep 29 '14 at 22:07
  • This is almost certainly a dup of about 50 questions, but… the problem is that you have a global named `mobhp`, and a local with the exact same name. Because of that, you can't see the global, so `newmobhp = mobhp - playerDam` will fail, because it's looking at the local, which isn't assigned yet. If you want to use the global, you need to add `global mobhp`. If you want to pass the global in as a starting value, you have to pass it as an argument. – abarnert Sep 29 '14 at 22:07
  • There are probably many better dups than the one I found, but if you look at the Linked and Related questions from that one, recursively, you'll find dozens of them very quickly, and one of them should explain things sufficiently. If anyone finds a better dup and doesn't have the rep to reopen and reclose this, post a link here and `@` me and I'll do it. – abarnert Sep 29 '14 at 22:11
  • 1
    @abarnert I think [this answer](http://stackoverflow.com/a/8934902/2922139) is pretty good. – Roger Fan Sep 29 '14 at 22:14
  • @RogerFan: Of course that one's a dup of [this one](http://stackoverflow.com/questions/9264763/unboundlocalerror-in-python)… but yeah, I think you're right that the first one will probably make more sense for this question. Good find. – abarnert Sep 29 '14 at 22:19
  • Crap, it won't let me re-close because I'm the one who both closed and re-opened? I didn't realize that. Can someone else vote to close with the link found by @RogerFan? – abarnert Sep 29 '14 at 22:19

1 Answers1

-1

The question may have been answered many times, but it deserves to be answered again as it is a bit tricky.

It seems that you want to use the outer (as if global) variable mobhp defined before the function definition -- as others pointed out in the comments. You should follow Hasan's advice, but you may have done it if the problem were not masked by the definition outside the function. Actually, you will want probably to pass the outer value via argument as Daniel suggested. I suggest not to use global at all -- it is almost never the way to go.

What others failed to explain is that actually, the following code would work:

import time
import random
mobhp = random.randint(10,40)
def fun1():
    print("You have chosen option number 1")
    #time.sleep(1)
    print("You attept an attack")
    #time.sleep(2)
    cointoss = 1
    if cointoss == 1:
        print("Attack successfull!")
        playerDam = random.randint(10,60)
        newmobhp = mobhp - playerDam

def main():
    fun1()
main()

Here the mobhp is also used before the assignment, and all commands above the usage are the same as in the earlier case. The difference is that the lookup rules found the variable outside the function.

If the variable is not found in the local scope, the variable is searche in the outer scope. However, it is only the case when the varialble is read. Once the variable is assigned inside the function body, it is always considered local, and it is never searched in the outer scope.

The decision whether the variable is local or can be outer is done during the compilation of the function -- simply said, during loading the function body when reading the script. When the function is called, its definition was already loaded (i.e. body compiled). And because of the line mobhp = newmobhp it was decided that mobhp must be local, even though the command is found later than the newmobhp = mobhp - playerDam.

That is probably always the reason for UnboundLocalError.

pepr
  • 20,112
  • 15
  • 76
  • 139