理解Think Python的示例代码如何像计算机科学家一样思考4.3 ex 5

理解Think Python的示例代码如何像计算机科学家一样思考4.3 ex 5,python,Python,我很难理解这本书的作者为什么使用了几行代码: import math import turtle bob = turtle.Turtle() def polyline(t, n, length, angle): """Draws n line segments. t: Turtle object n: number of line segments length: length of each segment angle: degrees betwe

我很难理解这本书的作者为什么使用了几行代码:

import math
import turtle

bob = turtle.Turtle()

def polyline(t, n, length, angle):
    """Draws n line segments.

    t: Turtle object
    n: number of line segments
    length: length of each segment
    angle: degrees between segments
    """
    for i in range(n):
        t.fd(length)
        t.lt(angle)


def polygon(t, n, length):
    """Draws a polygon with n sides.

    t: Turtle
    n: number of sides
    length: length of each side.
    """
    angle = 360.0/n
    polyline(t, n, length, angle)


def arc(t, r, angle):
    """Draws an arc with the given radius and angle.

    t: Turtle
    r: radius
    angle: angle subtended by the arc, in degrees
    """
    arc_length = 2 * math.pi * r * abs(angle) / 360
    n = int(arc_length / 4) + 3
    step_length = arc_length / n
    step_angle = float(angle) / n

    # making a slight left turn before starting reduces
    # the error caused by the linear approximation of the arc
    t.lt(step_angle/2)
    polyline(t, n, step_length, step_angle)
    t.rt(step_angle/2)


def circle(t, r):
    """Draws a circle with the given radius.

    t: Turtle
    r: radius
    """
    arc(t, r, 90)

circle(bob, 100)

我在评论中强调了我的困惑。说明是使用Python中的turtle创建一个通用函数来绘制一个圆。我正在使用Python3.7,但我并不认为这有什么区别。为什么作者在我第一条评论的地方使用了n?他从哪里得到这个公式的?另外,其余注释代码背后的逻辑是什么?我理解其余的练习,如果我知道他是如何得到这个方程的,我也会理解这个。

让我们逐行取弧函数:

arc_length = 2 * math.pi * r * abs(angle) / 360
2*math.pi*r
是圆周长的公式
abs(angle)/360
告诉您路径的圆周比例。将它们相乘,就得到了乌龟描述这条弧线所需的距离(假设它可以沿着弯曲的路径移动,我们只是近似)

这是我们希望乌龟在接近这个圆的周长所描述的路径时要走的步数。它不必是这个特定的值;其他实现使用
int(弧长/3)+1
和其他值<代码>步长和
步长角度
都是通过它来缩放的,因此增加它将使每个步长变小,并使单个步长的旋转变小。忽略浮点数学问题和累积的舍入误差,总行驶距离和总旋转将保持不变

step_length = arc_length / n
step_angle = float(angle) / n
我们的多段线将为我们制作
n
步骤。在每一步中,我们要移动
1/n
th的
arc_长度
,并旋转
1/n
th的圆弧所描述的总角度。如果我们将
n
在这两个值之前的行中设置一个较大的值,
步长
步长角度
将相应地缩小

至于其他方面:

t.lt(step_angle/2)
polyline(t, n, step_length, step_angle)  # take a lot of little steps
t.rt(step_angle/2)
这里的半圈是我们对圆弧近似的一个小改进。考虑一下我们在这里描述的路径,例如,沿单位圆的90度圆弧,从(1,0)开始,到(0,1)结束,共3步。下面是单位圆本身(理想x、理想y和理想航向,其中理想航向是圆在该点的切线)、原始x、原始y和原始航向以及x、y、,在开始这条路之前,先左转
步进角/2
,然后再右转
步进角/2
以取消它,从而产生航向:

     |ideal x|ideal y|ideal heading|raw x|raw y|raw heading|adj x|adj y|adj heading|
------------------------------------------------------------------------------------
Start|1      |0      |90           |1    |0    |90         |1    |0    |105        |
Step1|0.86   |0.5    |120          |1    |0.52 |120        |0.86 |0.51 |135        |
Step2|0.5    |0.86   |150          |0.74 |0.98 |150        |0.49 |0.88 |165        |
Step3|0      |1      |180          |0.28 |1.24 |180        |-0.01|1.01 |195        |
End  |0      |1      |180          |0.28 |1.24 |180        |-0.01|1.01 |180        |
请注意,调整后的值比原始值更接近理想值。当你思考折线如何工作时,这是一个直观的感觉:它沿着它所面对的任何方向向前移动,然后向左转弯。当您从未调整的航向开始时,在您尝试转弯之前将
步长
移动到弧上方。您将始终位于弧的上方和右侧。先向左转半步角,您将在弧下方花费一些
步长
,在弧上方花费一些
步长
。这将产生一个比严格在弧外的弧更好的近似值

编辑

至于更新的圆方法的问题,它采用两个参数(海龟和圆的半径),然后相应地调用arc。现在,您的实现是:

def circle(t, r):
    arc(t, r, 90)

其中,
的第三个参数是您希望移动的弧的角度。要画一个圆,需要360度,而不是90度。

这段代码正确吗?“我使用的是Python 3.7,但我真的不认为这有什么区别”-在这段代码中-是的。“作者为什么使用n…”-你可以随意命名。“他是从哪里得到这个公式的”——很可能是从自己的大脑中得到的,如果是从某个地方得到的话,比第一作者还多。“其他注释代码背后的逻辑是什么?”-不知道你这是什么意思。我猜你指的是最后一个问题-使用的函数到底是如何工作的-你可以查看导入的库代码来理解它,但通常这是浪费时间的-库是为了不重新发明轮子和更快地编码。我认为这个公式有点武断。他只是在决定把一条弧线画成几步。类似于“我想以距离4的增量绘制圆弧,但我还想确保至少使用3个步骤”。对于第二部分,我希望他通过一点尝试和错误得出这个结论。他发现结果并不完全正确,于是又增加了一点机会,让事情变得更好。这通常在编程中完成。通常情况下,当您遇到数字精度问题时,就会执行此操作,如这里所示。该死的答案!:)
def circle(t, r):
    arc(t, r, 90)