简体   繁体   中英

Why doesn’t redefining a function inside another function work? (Python Turtle)

I'm programming a game where enemy turtles (called badturt in the program) chase the user's turtle. The user can make its turtle attack the enemy turtles by sending an attack (another turtle).

In lvl 2, there are two enemy turtles chasing the user's turtle. To make one enemy turtle stop moving (after it is attacked/hit), I tried to redefine the function that makes the enemy turtle move, which was done inside another function. (I redefined it to None)

attack = turtle.Turtle()
#...attributes

def turtleattack():
    global lvl
    global q
    global w
    global e
    #... positioning attack
    for i in range(75):
        attack.forward(10)
        if lvl == 1:
            Chase(badturt)
        if lvl == 2:
            Chase(badturt)
            Chase(badturt2)
        if lvl == 3:
            Chase(badturt)
            Chase(badturt2)
            Chase(badturt3)
        IfAttackHit()
bg.onkeypress(turtleattack, 'z')
bg.listen()


def Chase(bt): #makes bad turt (bt) chase turt
    bt.setheading(bt.towards(turt))
    bt.forward(11)

def StopChase(bt):
    global lvl
    global win
    #global Chase <---------------- program stops running if I write it in
    if lvl == 1:
        #...
    if lvl == 2:
        def Chase(bt):
            None
        if q == 2 and w == 2:
            lvl = 3
            writeinfo()
    if lvl == 3:
        def Chase(bt):
            None
        if q == 3 and w == 3 and e == 3:
            #... (winning the game)

def ChaseAgain(bt): #makes badturt chase again when it moves onto next lvl
    def Chase(bt):
        bt.setheading(badturt.towards(turt))
        bt.forward(11)
    Chase(bt)


def IfAttackHit():
    global win
    global lvl
    global q
    global w
    global e
    if lvl == 1:
        if badturt.distance(attack) < 20:
            badturt.hideturtle()
            attack.hideturtle()
            badturt.goto(300,350)
            q = 1
            StopChase(badturt) #<---- doesn't work
    if lvl == 2:
        if badturt.distance(attack) < 20:
            badturt.hideturtle()
            attack.hideturtle()
            badturt.goto(300,350)
            q = 2
            StopChase(badturt)
        if badturt2.distance(attack) < 20:
            badturt2.hideturtle()
            badturt2.goto(-300,350)
            attack.hideturtle()
            w = 2
            StopChase(badturt2)
    if lvl == 3:
        #same format as lvl 2 but with addition of badturt3


while True:
    if lvl == 1:
         while True:
            CheckDamage()
            if turthealth == 0:
                LOSE()
                break
            IfAttackHit()
            Chase(badturt)
            if q == 1:
                break
    break
    if lvl == 2:
        ChaseAgain(badturt) #make it move again
        ChaseAgain(badturt2)
        badturt.goto(300,350)
        badturt.showturtle()
        badturt2.showturtle()
        while True:
            CheckDamage()
            if turthealth == 0:
                LOSE()
                break
            IfAttackHit()
            Chase(badturt)
            Chase(badturt2)
    break
    if lvl == 3:
        #same format as lvl 2 but with addition of badturt3
        break

This didn't work. Was it because it was nested inside another function? Was StopChase() never called? Did the function get redefined again so that the enemy turtle started moving again?

Also, my teacher told me that I had to write 'global Chase' to redefine it within another function, but when I do, the program stops running at that point - when I move my cursor over the turtle screen, it just shows the loading cursor, and nothing happens on the screen/it freezes. (Was it wrong to do that, or is it an issue with the python program on my laptop?)

I also tried redefining Chase() so that badturt would only move forward 0 (essentially making it do nothing), but that didn't work either.

Please let me know what I'm doing wrong, or if there's another way to make badturt stop moving.

When you redefine a non-class method the redefinition is permanent meaning it applies to everything. You probably don't want that.

What speaks against writing a condition inside of your Chase method?


There are various bad coding practices in your code:

  • You should generally refrain from using global . You should create classes and instances of classes which have attributes and pass those instances around.
  • Methods aren't capitalized. Classes are capitalized.
  • You have some unreachable code due to break
  • Use pass instead of None when nothing is supposed to happen

Tin Nguyen is absolutely right and you should definitely follow his advices. I'd just like to elaborate on your first question. Even if it could be bad, redefining your function using global should work. Here is what I tried as a minimal example:

def f():
    print("f")

def g():
    global f
    def f():
        print("f_prime")

f()
g()
f()

When called I get:

f
f_prime

The explanation why your program stops must be elsewhere but you do not provide the error you faced, if any.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM