python turtle输出坐标_Python Turtle在计时器上移动坐标列表

本文探讨了如何使用Python Turtle库在计时器上按指定坐标列表移动图形。作者展示了不同尝试,包括直接递归调用和使用全局变量,最后提供了一个避免无限循环问题的解决方案。通过示例代码,解释了列表切片和调用堆栈的工作原理,澄清了对递归和Turtle库理解的常见误解。
摘要由CSDN通过智能技术生成

我正在尝试让Python Turtle使用计时器在坐标列表中移动,可能有很多方法可以实现,但是以我目前的尝试,该程序只是挂起了。有人可以解释为什么吗?

import turtle

path = [(0, 0), (10, 10), (10, 20), (30, 40)]

bob = turtle.Turtle("square")

def do_path(a_list):

x, y = a_list[0]

bob.goto(x, y)

while len(a_list) > 0:

turtle.ontimer(lambda: do_path(a_list[1:]), 500)

do_path(path)

turtle.done()

使用全局变量似乎也无济于事:

import turtle

path = [(0, 0), (10, 10), (10, 20), (30, 40)]

bob = turtle.Turtle("square")

def do_path():

global path

x, y = path.pop(0)

bob.goto(x, y)

while len(path) > 0:

turtle.ontimer(lambda: do_path(path), 500)

do_path()

turtle.done()

解决方案

在while循环中进行递归调用对我来说似乎很可怕-while循环永远不会在where的所有深度处结束len(a_list) != 0。更像这样吗?

import turtle

coordinates = [

(0, 0),

(10, 10),

(10, 20),

(30, 40)

]

coordinates_iter = iter(coordinates)

t = turtle.Turtle("square")

def go_to_next_coord():

try:

next_coord = next(coordinates_iter)

except StopIteration:

return

t.goto(next_coord)

turtle.ontimer(go_to_next_coord, 500)

go_to_next_coord()

turtle.done()

所以lambda:do_path(a_list [1:])不会修改a_list吗?在递归函数调用中会不会?

当然不!您只需要切片a_list(完全独立)并将其传递do_path为参数。a_list从第一次递归开始就不会改变大小,因此,当您do_path等待完成时,while循环会挂起。

编辑-关于它是否真的是“递归”的主题:

import turtle

def foo(depth):

print(f"Starting depth {depth}")

if depth != 5:

turtle.ontimer(lambda: foo(depth+1), 1000)

print(f"Ending depth {depth}")

foo(0)

输出:

Starting depth 0

Ending depth 0

Starting depth 1

Ending depth 1

Starting depth 2

Ending depth 2

Starting depth 3

Ending depth 3

Starting depth 4

Ending depth 4

Starting depth 5

Ending depth 5

看起来从技术上讲它根本不是严格的递归!乌龟似乎可以安排这些回调。您可以期望在递归设置中看到的输出看起来像这样:

Starting depth 0

Starting depth 1

Starting depth 2

Starting depth 3

Starting depth 4

Starting depth 5

Ending depth 5

Ending depth 4

Ending depth 3

Ending depth 2

Ending depth 1

Ending depth 0

但是,您遇到的问题通常与递归或乌龟无关。确切地说,这与对调用堆栈和/或可能的列表切片的误解有关。看一下下面的示例代码:

def do_it(depth, items):

length = len(items)

print(f"I'm recursion depth {depth}, I see {length} item(s).")

if depth != 5: #arbitrary base case:

new_items = items[1:]

print(f"Depth {depth} - items: {items}")

print(f"Depth {depth} - new_items: {new_items}")

do_it(depth+1, new_items)

print(f"Depth {depth} is ending now, length is {length} and items is {items}")

do_it(0, [1, 2, 3, 4, 5])

输出:

I'm recursion depth 0, I see 5 item(s).

Depth 0 - items: [1, 2, 3, 4, 5]

Depth 0 - new_items: [2, 3, 4, 5]

I'm recursion depth 1, I see 4 item(s).

Depth 1 - items: [2, 3, 4, 5]

Depth 1 - new_items: [3, 4, 5]

I'm recursion depth 2, I see 3 item(s).

Depth 2 - items: [3, 4, 5]

Depth 2 - new_items: [4, 5]

I'm recursion depth 3, I see 2 item(s).

Depth 3 - items: [4, 5]

Depth 3 - new_items: [5]

I'm recursion depth 4, I see 1 item(s).

Depth 4 - items: [5]

Depth 4 - new_items: []

I'm recursion depth 5, I see 0 item(s).

Depth 5 is ending now, length is 0 and items is []

Depth 4 is ending now, length is 1 and items is [5]

Depth 3 is ending now, length is 2 and items is [4, 5]

Depth 2 is ending now, length is 3 and items is [3, 4, 5]

Depth 1 is ending now, length is 4 and items is [2, 3, 4, 5]

Depth 0 is ending now, length is 5 and items is [1, 2, 3, 4, 5]

>>>

I know the output is a bit dense to follow, but hopefully it should demonstrate a misconception you seem to be having. Just because you call a new function (or the same function in the case of recursion) within a function, doesn't mean that the function you're "leaving" ends or terminates. The function you left is waiting on the call-stack until the function you went to terminates, and then execution comes back to the calling-function. All I'm really trying to highlight here is that the different "depths" (functions sitting on the call-stack) see different things. The example I used here is recursive, but the same thing applies in your non-recursive case. Just because you called do_path inside of do_path doesn't mean that the old do_path just suddenly goes away. It's waiting for the inner, most recent invokation of do_path to finish until it can finish.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值