每次调用函数时命令都会改变吗?

时间:2014-11-18 02:37:30

标签: python arrays turtle-graphics

def drawPoint(direction, x):
    turtle.(direction[x])(1)
    turtle.forward(1)
    x = x + 1
    drawPoint(direction, x%2)       

def main():
     x = 0
     myTurtle = turtle.Turtle()
     myWindow = turtle.Screen()
     direction = ['right', 'left', 'up', 'down']
     drawPoint(direction, x)

例如我试图写龟。(方向[x])。 direction是一个字符串数组,字符串是turtle命令。因此,如果我遍历方向数组,每次调用drawPoint时都会更改turtle命令。

1 个答案:

答案 0 :(得分:0)

我可以看到你在这里要做的事情:

turtle.(direction[x])(1)

您希望使用direction[x]中的字符串作为方法的名称。您可能不应想要这样做,但可以。只是不直接;你必须使用getattr函数:

getattr(turtle, direction[x])(1)

无论如何,使用getattr通常不是一个好主意。更好的想法是将方法存储在列表中,而不是它们的名称中。像其中一个:*

direction = [myTurtle.right, myTurtle.left, myTurtle.up, myTurtle.down]
direction = [turtle.Turtle.right, turtle.Turtle.left, turtle.Turtle.up, turtle.Turtle.down]

第一个版本创建一个绑定方法列表,它知道它们附加到哪个对象(myTurtle),因此您只需调用direction[0](1)即可。第二个创建未绑定方法的列表,它们不知道它们附加到哪个对象;你必须像参数direction[0](myTurtle, 1)一样明确地传递它。我认为后者在这种情况下更有意义,因为下一点,但两者都是完全有效的。


你在这里也遇到了另一个问题:turtle不是你的龟对象,它是一个模块。您需要一些对象才能使用,但drawPoint中没有。幸运的是,您在myTurtle中创建了一个名为main的名称,因此您只需将其传递给drawPoint


最后,如果你想迭代,请使用循环,而不是递归调用自己。否则,在第1000个循环中,你将得到一个异常,你的程序将以一个丑陋的堆栈跟踪退出。**


所以:

def drawPoint(myTurtle, direction, x):
    while True:
        direction[x](myTurtle)(1)
        myTurtle.forward(1)
        x = x + 1
        x %= 2

def main():
     x = 0
     myTurtle = turtle.Turtle()
     myWindow = turtle.Screen()
     direction = ['right', 'left', 'up', 'down']
     drawPoint(myTurtle, direction, x)

另一个漂亮的技巧。如果要永久循环遍历列表,而不是跟踪索引并使用%重置为0,则可以使用cycle函数。在这种情况下,我们只想绕过direction的前两个元素,因此我们将使用切片:

import itertools

def drawPoint(myTurtle, direction, x):
    for dir in itertools.cycle(direction[:2]):
        dir(myTurtle)(1)
        myTurtle.forward(1)

*在Python中,所有是一流的值 - 模块,类,对象,函数,绑定和非绑定方法等。这意味着您可以将其粘贴在列表中,将它传递给函数,无论你想要什么。

**每次调用另一个函数时,它都会在堆栈上推送另一个帧。当你返回时,它会从堆栈中弹出一个框架。但是如果你的函数在返回之前调用另一个函数,并且在返回之前调用另一个函数,依此类推,你最终会溢出堆栈。为了避免较低级语言的恶意崩溃(和安全漏洞),Python不会让你走得那么远,并且当你获得1000深度时会引发异常。 (如果你已经习惯了另一种语言,例如,Scheme,这让你感到惊讶,那是因为Scheme会进行尾调用消除,而Python则不然;更常见的是,Scheme旨在鼓励尽可能多的递归,而Python旨在劝阻它。)