【问题标题】:Why doesn’t redefining a function inside another function work? (Python Turtle)为什么在另一个函数中重新定义一个函数不起作用? (蟒蛇龟)
【发布时间】:2020-03-17 07:22:31
【问题描述】:

我正在编写一个游戏,其中敌方海龟(在程序中称为 badturt)追逐用户的海龟。用户可以通过发送攻击(另一只乌龟)使其乌龟攻击敌方乌龟。

在 lvl 2 中,有两只敌方海龟在追逐用户的海龟。为了让一只敌方海龟停止移动(在它被攻击/击中后),我尝试重新定义使敌方海龟移动的函数,这是在另一个函数中完成的。 (我将其重新定义为无)

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

这不起作用。是因为它嵌套在另一个函数中吗?从未调用过 StopChase() 吗?函数是否再次被重新定义,以便敌方海龟再次开始移动?

另外,我的老师告诉我,我必须编写 'global Chase' 来在另一个函数中重新定义它,但是当我这样做时,程序会停止运行 - 当我将光标移到海龟屏幕上时,它只是显示加载光标,屏幕上没有任何反应/它冻结。 (这样做是错的,还是我笔记本电脑上的 python 程序有问题?)

我还尝试重新定义 Chase() 以便 badturt 只会向前移动 0(基本上让它什么都不做),但这也不起作用。

请让我知道我做错了什么,或者是否有其他方法可以让 badturt 停止移动。

【问题讨论】:

    标签: python turtle-graphics


    【解决方案1】:

    当您重新定义非类方法时,重新定义是永久的,这意味着它适用于所有内容。你可能不想要那个。

    在你的 Chase 方法中写一个条件的理由是什么?


    您的代码中有各种不良的编码习惯:

    • 您通常应避免使用global。您应该创建具有属性的类和类的实例并传递这些实例。
    • 方法不大写。类是大写的。
    • 由于break,您有一些无法访问的代码
    • 在不应该发生任何事情时使用 pass 而不是 None

    【讨论】:

    • 感谢您的建议。只是想知道,为什么使用全局是不好的做法?我是一个初学者(如果你还没有从我糟糕的编码中知道的话),所以我不太了解如何格式化我的代码。
    • 它会导致一些非常hacky和混乱的代码。您的代码中需要更多的结构,这可以通过类来实现。一个类应该具有的所有相关属性都在实例内部。它还可以更好地扩展,因为一旦您定义了一个全局变量,该变量名就消失了。例如,您有一个名为level 的全局变量。稍后您想要跟踪其他对象的级别。使用类你可以做turtle1.levelturtle2.level。您可以将turtle1turtle2 放入turtles 等列表中。
    • @whattheheck——有很多讨论,例如Global Variables are Evil,解释了为什么应该避免它们。它们确实有作用,但在代码中看到时通常是一种设计气味。
    【解决方案2】:

    Tin Nguyen 是绝对正确的,你绝对应该听从他的建议。我想详细说明你的第一个问题。即使它可能很糟糕,使用 global 重新定义你的函数也应该有效。这是我尝试的一个最小示例:

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

    当被调用时,我得到:

    f
    f_prime
    

    您的程序停止的原因必须在其他地方说明,但您没有提供您遇到的错误(如果有)。

    【讨论】:

      猜你喜欢
      • 2014-01-08
      • 2015-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-24
      • 2021-08-10
      相关资源
      最近更新 更多