《Think Python》练习 4-1:本章示例代码栈图、停止点偏离思考
第4章 案例研究:接口设计
练习 4-1 本章示例代码栈图、停止点偏离思考
【习题 4.1.1】 画一个栈图来显示函数 circle(bob, radius) 运行时的程序状态。
《Think Python》第4章示例代码(仅circle相关,完整版点击):
"""This module contains a code example related toThink Python, 2nd Edition
by Allen Downey
http://thinkpython2.comCopyright 2015 Allen DowneyLicense: http://creativecommons.org/licenses/by/4.0/
"""from __future__ import print_function, divisionimport math
import turtledef polyline(t, n, length, angle):"""Draws n line segments.t: Turtle objectn: number of line segmentslength: length of each segmentangle: degrees between segments"""for i in range(n):t.fd(length)t.lt(angle)def arc(t, r, angle):"""Draws an arc with the given radius and angle.t: Turtler: radiusangle: angle subtended by the arc, in degrees"""arc_length = 2 * math.pi * r * abs(angle) / 360n = int(arc_length / 4) + 3step_length = arc_length / nstep_angle = float(angle) / n# making a slight left turn before starting reduces# the error caused by the linear approximation of the arct.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: Turtler: radius"""arc(t, r, 360)# the following condition checks whether we are
# running as a script, in which case run the test code,
# or being imported, in which case don't.if __name__ == '__main__':bob = turtle.Turtle()# draw a circle centered on the originradius = 100bob.pu()bob.fd(radius)bob.lt(90)bob.pd()circle(bob, radius)# wait for the user to close the windowturtle.mainloop()
【求解】 在加入 print
语句之后,发现 bob 的值是 <turtle.Turtle object at 0x10eb04a90>,而不是 turtle.Turtle()
所属函数 | 变量 |
---|---|
__ main__ | bob ——> <turtle.Turtle object at 0x10eb04a90> |
__ main__ | radios ——> 100 |
circle | t ——> <turtle.Turtle object at 0x10eb04a90> |
circle | r ——> 100 |
arc | t ——> <turtle.Turtle object at 0x10eb04a90> |
arc | r ——> 100 |
arc | angle ——> 360 |
polyline | t ——> <turtle.Turtle object at 0x103ba5518> |
polyline | n ——> 160 |
polyline | length ——> 3.9269908169872414 |
polyline | angle ——> 2.25 |
因为 CSDN 的 Markdown 文字两侧连打2个下划线是加粗,所以main的前面多了个空格(强迫症勿怪)
【习题 4.1.2】 在 4.7 节中的 arc 函数并不准确,因为使用多边形模拟近似圆,总是会在真实的圆之外。因此,Turtle 画完线之后会停在偏离正确的目标几个像素的地方。我的解决方案里展示了一种方法可以减少这种错误的效果。阅读代码并考虑是否合理。如果你自己画图,可能会发现它是如何生效的。
【求解】 先对比代码有何不同
《4.7 节》的 arc 函数:
def arc(t, r, angle):arc_length = 2 * math.pi * r * angle / 360n = int(arc_length / 3) + 1step_length = arc_length / nstep_angle = angle / nfor i in range(n):t.fd(step_length)t.lt(step_angle)
《练习 4-1》的arc 函数:
def polyline(t, n, length, angle):"""Draws n line segments.t: Turtle objectn: number of line segmentslength: length of each segmentangle: degrees between segments"""for i in range(n):t.fd(length)t.lt(angle)def arc(t, r, angle):"""Draws an arc with the given radius and angle.t: Turtler: radiusangle: angle subtended by the arc, in degrees"""arc_length = 2 * math.pi * r * abs(angle) / 360n = int(arc_length / 4) + 3step_length = arc_length / nstep_angle = float(angle) / n# making a slight left turn before starting reduces# the error caused by the linear approximation of the arct.lt(step_angle/2)polyline(t, n, step_length, step_angle)t.rt(step_angle/2)
《练习 4-1》示例代码给出的解决方案是“在画圆前轻微左偏”,理由是“错误是由弧的线性相似导致的”。
关于 弧的线性相似误差 :
《Think Python》又名《重拾三角函数》。
由于本人脱离学校太久,总之根据本人已经没法证明的三角函数求极限理论,当近似圆中每个小三角夹角足够小的时候,近似圆就越接近圆,真实的圆并不完全在近似圆之内或之外,真实圆的弧不停的跨过近似圆的边,像这样:
这种近似圆与真实圆的误差会导致多边形的角在真实圆之外,即每当开始或停止画直线的时候,乌龟会停在多边形的角上,即真实圆之外。
关于处理方案:
#左转半个step_angle
t.lt(step_angle/2)#画一个近似圆
for i in range(n):t.fd(length)t.lt(angle)#右转半个step_angle
t.rt(step_angle/2)
我将 arc 函数引用的 polyline 函数中的 for 循环展开了,可以先看出来处理方案的 arc 函数是先左转半个 step_angle 的角度,再画一个 完整的 近似圆,画完后再讲乌龟右转半个 step_angle 归位:
老实说我并不觉得这种 “再画圈前稍微左转一点点(making a slight left turn before starting reduces)”的骚操作除了让画出的近似圆比之前的右偏半个 step_angle 对于画出的多边形本身并没有任何影响,为何作者会认为这种操作减小了误差呢?虽然作者说了“如果你自己画图,可能会发现它是如何生效的”,但是我画了更理解不了……
我打算写完第四章作业后,发个帖子找人问问,如果有大佬指点的话,会更新在这里。
我回来了……
在做【练习 4-4:字母表】时发现,如果删除掉
#左转半个step_angle
t.lt(step_angle/2)#右转半个step_angle
t.rt(step_angle/2)
仅保留
#画一个近似圆
for i in range(n):t.fd(length)t.lt(angle)
当你在画J的时候,如果先画一竖,再左移直径画一个半圆,你会发现,根本接不上……
代码:
#引入数学模块、乌龟模块
import math
import turtle#调用乌龟画图、提高画弧速度
bob = turtle.Turtle()
bob.delya = 0.01#多边线
def polyline(t, n, length, angle):for i in range(n):t.fd(length)t.lt(angle)#弧
def arc(t, r, angle):arc_length = 2 * math.pi * r * abs(angle) / 360n = int(arc_length / 4) + 3step_length = arc_length / nstep_angle = float(angle) / n#t.lt(step_angle/2)polyline(t, n, step_length, step_angle)#t.rt(step_angle/2)#线段
def line(t, l):t.fd(l)#test:J
def draw_j(t, l):t.rt(90)line(t, l)t.pu()t.rt(90)line(t, l/2)t.lt(90)t.pd()arc(t, l/4, 180)draw_j(bob,200)
turtle.mainloop()
效果:
说明 t.lt(step_angle/2)
转的微小角度才是正确的,不转所画的弧线虽然尺寸没问题,但是位置以起点为中心左偏了 t.lt(step_angle/2)
角度。
加上这两行代码(解除注释)后:
#弧
def arc(t, r, angle):arc_length = 2 * math.pi * r * abs(angle) / 360n = int(arc_length / 4) + 3step_length = arc_length / nstep_angle = float(angle) / nt.lt(step_angle/2)polyline(t, n, step_length, step_angle)t.rt(step_angle/2)
效果:
仔细想了下函数 arc(t, r, angle)
的画法,如果开头不左转 t.lt(step_angle/2)
的话,相直线向下画第1笔,再开始“转一个小角度 - 再画一笔”的循环:
这就造成了一个问题:终点没有跟起点水平(没有 t.lt(step_angle/2)
的终点是红色,有 t.lt(step_angle/2)
的终点是绿色),造成了这种效果:
仔细想了一下,数学原因是:由于我们是用很短的直线模拟的曲线,起点和终点的切线斜度就是第一根线和最后一根线的斜度,第一根直线的斜度是0、最后一根切线的斜度是 cot(step_angle),没办法像真正的弧线一样做到起点和终点的切线斜度相同,故需要匀一下,让起点多 step_angle/2,终点少 step_angle/2。
《Think Python》练习 4-1:本章示例代码栈图、停止点偏离思考相关推荐
- python代码示例下载-python爬取音频下载的示例代码
抓取"xmly"鬼故事音频 import json # 在这个url,音频链接为JSON动态生成,所以用到了json模块 import requests headers = { & ...
- python画-使用python画个小猪佩奇的示例代码
基本原理 选好画板大小,设置好画笔颜色.粗细,定位好位置,依次画鼻子.头.耳朵.眼睛.腮.嘴.身体.手脚.尾巴,完事儿. 都知道,Turtle 是 Python 内置的一个比较有趣味的模块,俗称&qu ...
- python代码示例下载-Python实现多线程下载脚本的示例代码
0x01 分析 一个简单的多线程下载资源的Python脚本,主要实现部分包含两个类: Download类:包含download()和get_complete_rate()两种方法.download() ...
- 在哪里能收到python实例代码-python实现网站微信登录的示例代码
最近微信登录开放公测,为了方便微信用户使用,我们的产品也决定加上微信登录功能,然后就有了这篇笔记. 根据需求选择相应的登录方式 python实现网站微信登录的示例代码 微信现在提供两种登录接入方式 移 ...
- python界面不同按钮实现不同功能-python tkinter实现界面切换的示例代码
跳转实现思路 主程序相当于桌子: import tkinter as tk root = tk.Tk() 而不同的Frame相当于不同的桌布: face1 = tk.Frame(root) face2 ...
- python停止线程池_详解python中Threadpool线程池任务终止示例代码
需求 加入我们需要处理一串个位数(0~9),奇数时需要循环打印它:偶数则等待对应时长并完成所有任务:0则是错误,但不需要终止任务,可以自定义一些处理. 关键点 定义func函数处理需求 callbac ...
- Python实现炸金花游戏的示例代码
本文主要介绍了Python实现炸金花游戏的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下.编程学习资料点击领取. 今天的第二个作品,哈哈哈哈,搞起来感觉还挺 ...
- 用python画佩奇_使用python画个小猪佩奇的示例代码
基本原理 选好画板大小,设置好画笔颜色.粗细,定位好位置,依次画鼻子.头.耳朵.眼睛.腮.嘴.身体.手脚.尾巴,完事儿. 都知道,Turtle 是 Python 内置的一个比较有趣味的模块,俗称&qu ...
- 用python画苹果的代码_使用python画个小猪佩奇的示例代码
基本原理 选好画板大小,设置好画笔颜色.粗细,定位好位置,依次画鼻子.头.耳朵.眼睛.腮.嘴.身体.手脚.尾巴,完事儿. 都知道,Turtle 是 Python 内置的一个比较有趣味的模块,俗称&qu ...
最新文章
- 安装Properties Editor插件,解决XXX.properties文件中文乱码的问题
- mysql删除重复文章标题_MySQL中查询、删除重复记录的方法大全
- 通过案例对 spark streaming 透彻理解三板斧之三:spark streaming运行机制与架构
- QT学习:多国语言国际化
- BOMbing The System
- 我理解的invoke和begininvoke
- 广州科目三考试 不得不看的十条提醒(图)
- linux不挂断运行python文件
- 修改数据库参数oracle,Oracle 修改数据库基本参数
- iPhone 12发布当天,罗永浩开“旧机发布会”:香得不行!
- 套接字,TCP,UDP
- ie中弹出框中元素的定位
- matlab学习网站
- mysql服务注册表删除_怎么彻底删除mysql服务(清理注册表)详解
- 网站中网页最优色彩搭配方案学习--Java免费学习网
- 国庆八天乐,码农长假怎么过?别加班了
- 百度文字识别官方Demo
- apicloud 项目常用插件
- 小程序下载图片、文件、wx.downloadFile,废话少说直接上代码
- 基于云原生的私有化交付PAAS平台