最近备课时又翻到“3.3 Python图形编程”这一节。这个标题在教材目录里看着平平无奇,但真把它讲透、学透,容量其实远超一节常规课的体量——从终端里的字符输出,跨到带窗口、带坐标、带鼠标事件的图形界面,这是很多初学者第一次真正觉得“编程能做出东西”的临界点。这篇文章就把这一章完整展开,把我自己备课、带学生实操过程中攒下的经验、踩过的坑、验证过的代码都写出来,给正在啃这一节的同学,以及准备讲这一节的同行做个参考。
文章线路是这样的:先理清图形编程到底在解决什么问题,把Python里几套常用工具选型讲明白;然后从环境搭建开始,分别走完Tkinter窗口程序、matplotlib数据绘图、turtle海龟绘图三条主线;最后用一个综合小项目把几块内容串起来,附上我实际遇到的报错和排查思路。里面所有代码我都用本地环境跑过,Python版本是3.8到3.11都能跑通。
1. 图形编程的核心逻辑:为什么这一节这么重要
1.1 从“黑框程序”到“图形界面”的思维转变
前面几节学Python,大部分练习的输出结果都停留在控制台:print打印一行文字,input接收一次输入,循环跑完统计个结果。这种模式学起来直接,但有个天生的短板——程序和使用者之间只有“文本”这一条通道。你写一个计算器,用户只能按命令行一步步输入,很不直观。
图形编程解决的就是这个通道问题。它让程序具备窗口、画布、按钮、坐标轴这些可视化元素,用户可以用鼠标点击、拖拽,可以用图形而非文字来理解数据。从教学角度看,这一节实际上是“编程思维”的一次升级:以前你写代码是“告诉计算机做什么”,现在你是“设计一段持续运行的、等待事件驱动的程序”。
这也是很多教程把图形编程放在第三章而不是第一章的原因。学图形编程之前,你得先懂变量、函数、循环、条件分支——因为图形程序里的回调函数、事件循环、坐标计算全都要用这些基础。反过来,一旦你掌握了图形编程的基础套路,后边学爬虫写数据展示工具、学数据分析做可视化、学算法看排序过程动画,都会顺手很多。
1.2 Python图形编程的三大主流方向
“图形”这个词在Python生态里范围很广,不同需求对应完全不同的工具库。这一章节里最常见的三个方向是:
- GUI桌面应用:用Tkinter制作带窗口、按钮、输入框的桌面程序。Tkinter是Python标准库自带的,不需要额外安装,最适合入门。
- 数据可视化绘图:用matplotlib把一组数据画成折线图、柱状图、散点图、饼图。这是数据分析、论文绘图、量化交易展示最常用的工具。
- 教学动画绘图:用turtle海龟绘图,移动画笔在画布上留下轨迹,特别适合展示递归、循环这类逻辑的运行过程。
还有一个方向是游戏开发方向的Pygame,以及计算机视觉方向的OpenCV,在3.3这一节里一般不会展开,但如果学有余力,顺着matplotlib和turtle的路子往下延伸,会发现图形编程的大门越开越大。
我个人的建议是:初学者别贪多,先把Tkinter和matplotlib学好,turtle用来辅助理解抽象逻辑。三条线都走一遍后,再根据自己的目标方向专攻其中一个。
2. 环境准备:把图形编程的“地基”一次打好
2.1 Python安装与版本选择的经验
我见过太多图形编程代码跑不起来,最后排查发现是Python版本太老或者环境变量没配好。这里给一套我实测比较稳的方案。
先到Python官网下载安装包,建议选3.10或3.11版本,没必要追最新版——有些第三方库对最新版的支持会滞后。安装过程中有一个特别关键的选项:一定要勾选“Add Python to PATH”,不然安装完在命令行里敲python会提示找不到命令。装完之后打开命令行(Windows按Win+R输入cmd,macOS打开终端),分别执行:
python --version pip --version两条命令能正常打印出版本号,说明环境OK。如果提示pip不是内部或外部命令,大概率是Python安装时没勾选PATH选项,或者安装的是Windows应用商店版本导致的路径问题。此时最省事的办法是重装一遍Python,勾选Add to PATH;如果不想重装,也可以手动去系统环境变量里把Python的安装目录和Scripts目录加上。
这里提示一下:“3.3 Python图形编程”这节内容用到的库,全部可以通过pip安装,不需要动系统环境变量。后面每一步装库,我都给了对应的pip命令。
2.2 图形库的安装与验证(Tkinter、matplotlib、turtle)
先把需要用到的库装齐。Tkinter和turtle有点特殊:Tkinter在Windows官方安装包中默认自带,turtle则是Python标准库的一部分,不需要单独pip命令。但不同平台情况不完全一样,Linux下可能需要单独装:
# Windows用户一般跳过这一步 python -m tkinter如果弹出一个小窗口,说明Tkinter可用。Linux环境如果报ModuleNotFoundError,执行sudo apt-get install python3-tk即可。
matplotlib需要手动安装:
pip install matplotlib安装完成后用一个极简代码验证:
import matplotlib.pyplot as plt plt.plot([1, 2, 3, 4], [1, 4, 9, 16]) plt.title("Test Plot") plt.show()能弹出一个窗口显示折线图,说明matplotlib安装成功。
这里有个常见坑:有些读者反馈pip install很慢甚至超时,是因为默认源在国外。国内网络环境下,建议用清华镜像或阿里云镜像:
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple实测速度能从几百KB/s提到几MB/s。如果装完import时提示缺少某些底层依赖库(比如DLL加载失败),多半是操作系统缺少Visual C++运行库,去微软官网下载安装“Visual C++ Redistributable for Visual Studio”就能解决。
另外,如果你做的是数据分析相关项目,建议顺手装numpy和pandas:
pip install numpy pandasmatplotlib在绘图时经常要和这两个库配合。
2.3 开发工具的选择:VS Code配置Python环境
写图形编程代码,用IDLE也能跑,但体验不太好。推荐用VS Code,免费且跨平台。
装好VS Code后,在扩展市场搜索并安装两个扩展:Python(微软官方出的)和Python Indent(自动缩进辅助)。然后按Ctrl+Shift+P打开命令面板,输入“Python: Select Interpreter”,选择你刚装的那个Python版本。
这里我提醒一个细节:图形编程程序运行后会有窗口弹出,VS Code默认的终端和调试控制台都能正常显示窗口,但如果用了Jupyter Notebook的%matplotlib inline模式,弹出的窗口会变成内嵌图表。两种方式各有利弊:桌面窗口适合交互操作,内嵌图表适合写博客记录。你自己根据需求切换就行。
调试图形程序还有一个实用技巧:在VS Code的launch.json里设置"console": "integratedTerminal",这样printf打印的信息和图形窗口会同时出现,排查问题方便很多。
3. 核心实践一:Tkinter打造桌面图形界面
3.1 从“创建窗口”到“控件布局”的完整流程
Tkinter的代码风格和普通脚本差异很大——它不再是顺序执行完就退出,而是进入一个事件循环,持续等待用户的点击、输入等动作。
最基本的窗口代码:
import tkinter as tk root = tk.Tk() root.title("我的第一个窗口") root.geometry("400x300") root.mainloop()运行这段代码,会弹出一个400x300像素的空白窗口。mainloop()是Tkinter的事件循环入口,窗口关闭后程序才会退出。
有窗口之后,就要往里放控件。常用的控件有Label(标签)、Button(按钮)、Entry(输入框)、Text(多行文本框)、Canvas(画布)。放控件有两种布局方式:pack和grid。初学者建议先用pack,它按顺序自动排列,代码简洁;复杂界面用grid按行列摆放,控件位置更精确。
一个带按钮和标签的完整例子:
import tkinter as tk def show_message(): label.config(text="你点击了按钮!") root = tk.Tk() root.title("按钮示例") root.geometry("300x150") label = tk.Label(root, text="等待点击...") label.pack(pady=20) button = tk.Button(root, text="点我", command=show_message) button.pack(pady=10) root.mainloop()点击按钮后,label.config(text=...)会实时更新界面文字。这是Tkinter里最基础也最核心的交互逻辑——控件注册回调函数,事件触发时执行。
3.2 画布控件:Tkinter里最容易被忽略的绘图神器
多数教材讲到Tkinter的控件就结束了,但“图形编程”如果只停留在按钮和标签上是不够的。Tkinter有一个Canvas控件,可以在窗口内绘制直线、矩形、椭圆、弧线,还能绑定鼠标事件——这才算真正踏进“图形”的门槛。
用Canvas画一个简单图形:
import tkinter as tk root = tk.Tk() root.title("Canvas绘图") root.geometry("400x300") canvas = tk.Canvas(root, width=380, height=280, bg="white") canvas.pack() # 绘制直线 canvas.create_line(50, 50, 200, 50, fill="blue", width=3) # 绘制矩形 canvas.create_rectangle(50, 80, 150, 180, outline="red", fill="yellow") # 绘制椭圆(外接矩形方式) canvas.create_oval(200, 80, 320, 180, fill="green") # 绘制文字 canvas.create_text(100, 250, text="Hello Canvas", font=("Arial", 16)) root.mainloop()注意Canvas的坐标系:原点在左上角,x轴向右,y轴向下。这一点和数学课上的坐标系不同,很多初学者在这里懵。你画一个椭圆,create_oval(x1, y1, x2, y2)里的四个参数是椭圆外接矩形的左上角和右下角坐标。
Canvas结合鼠标事件可以做简易画板:
import tkinter as tk last_x = None last_y = None def on_press(event): global last_x, last_y last_x, last_y = event.x, event.y def on_drag(event): global last_x, last_y canvas.create_line(last_x, last_y, event.x, event.y, width=3) last_x, last_y = event.x, event.y root = tk.Tk() root.title("简易画板") root.geometry("500x400") canvas = tk.Canvas(root, width=500, height=400, bg="white") canvas.pack() canvas.bind("<Button-1>", on_press) canvas.bind("<B1-Motion>", on_drag) root.mainloop()这个例子有点意思的地方在于:<Button-1>是鼠标左键按下事件,<B1-Motion>是按住左键拖动事件。按下时记录坐标,拖动时不断从上一个坐标画到当前坐标,就实现了连续的画笔轨迹。
3.3 Tkinter布局避坑指南
布局这块我踩过不少坑,挑三个最典型的说:
- 混用pack和grid会直接报错。Tkinter要求同一个容器里只能用一种布局方式,混用会抛出“cannot use geometry manager pack inside . which already has slaves managed by grid”这类错误。同一个窗口里要么全用pack,要么全用grid。
- 主窗口退出问题。如果程序里忘记调用
mainloop(),窗口一闪而过,看起来像没运行成功。记得所有控件都创建完之后再调用mainloop()。 - 控件更新必须用config。很多人尝试通过
label = tk.Label(...); label["text"] = ...来更新文本,这在某些情况下不生效,推荐统一用label.config(text=...)。
4. 核心实践二:matplotlib绘制数据图形
4.1 从折线图开始,掌握pyplot基本流程
matplotlib的绘图逻辑可以概括为三步:准备数据、调用绘图函数、展示或保存。以最简单的折线图为例:
import matplotlib.pyplot as plt # 准备数据 x = [1, 2, 3, 4, 5] y = [1, 4, 9, 16, 25] # 绘图 plt.plot(x, y, marker="o", linestyle="--", color="blue", label="y=x^2") # 添加标签和图例 plt.xlabel("x值") plt.ylabel("y值") plt.title("折线图示例") plt.legend() # 展示 plt.show()plt.plot函数的参数里,marker控制数据点标记样式,linestyle控制线型,color控制颜色,label配合legend显示图例。这些参数看着琐碎,但在出图质量和后续调整时非常重要。
还有一步容易被忽略:plt.show()会阻塞程序直到关闭窗口,如果你在脚本里先show再执行后续代码,后续代码会在窗口关闭后才运行。想要不阻塞,可以改用plt.show(block=False),或者把plt.savefig("output.png")保存图片后再show。
4.2 解决“横坐标太密集”的经典问题
在热词里看到一个高频问题:python画图横坐标太密集。这个问题几乎每个用matplotlib画时间序列、分类数据的人都会遇到。当你横轴有几十上百个刻度时,matplotlib默认会把所有刻度都标出来,结果就是标签重叠成黑乎乎一条。
解决办法有三个层次:
第一个层次:手动旋转标签
plt.xticks(rotation=45)这能解决拥挤问题,但刻度多时依然无法根治。
第二个层次:控制刻度数量
import matplotlib.pyplot as plt x = range(0, 100) y = [i**2 for i in x] plt.plot(x, y) # 只显示10个刻度 plt.xticks(range(0, 100, 10)) plt.show()用plt.xticks手动指定需要显示的刻度位置和标签。实际项目中我经常结合这两个方法:先设置刻度数量,再旋转标签。
第三个层次:用MaxNLocator自动控制刻度数量
import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator plt.plot(x, y) ax = plt.gca() ax.xaxis.set_major_locator(MaxNLocator(nbins=10)) plt.xticks(rotation=45) plt.show()MaxNLocator会根据数据范围自动选取大约nbins个“整齐”的刻度,比手写range要稳妥,尤其当数据量不确定时。
这三种方法里,最推荐MaxNLocator方案,因为它对数据量变化不敏感。
4.3 画布、子图与样式配置:让图更像“专业的图”
实际项目里,单张图往往不够用,要在一张画布里放多个子图。我用得最多的是subplots函数:
import matplotlib.pyplot as plt fig, axes = plt.subplots(2, 2, figsize=(10, 8)) # 左上:折线图 axes[0, 0].plot([1, 2, 3], [3, 6, 9]) axes[0, 0].set_title("Line") # 右上:柱状图 axes[0, 1].bar(["A", "B", "C"], [10, 20, 15]) axes[0, 1].set_title("Bar") # 左下:散点图 axes[1, 0].scatter([1, 2, 3], [5, 7, 8]) axes[1, 0].set_title("Scatter") # 右下:饼图 axes[1, 1].pie([30, 40, 20, 10], labels=["A", "B", "C", "D"]) axes[1, 1].set_title("Pie") plt.tight_layout() plt.show()用subplots时最容易出的问题:子图坐标轴标签重叠。plt.tight_layout()一行就能自动调整子图间距,强烈建议每次多子图绘制后都加上。
如果你觉得默认样式不够好看,可以用plt.style.available查看可用样式,然后通过plt.style.use("ggplot")切换。我个人偏爱“seaborn-v0_8”和“ggplot”,配色更柔和,网格线也更清晰。
4.4 matplotlib中文字体显示问题的完整处理
这算是matplotlib最出名的一个坑:图上出现方块,中文乱码。原因很简单——matplotlib默认字体里没有中文字符。
解决方案:
import matplotlib.pyplot as plt # 查看当前支持的中文字体 from matplotlib.font_manager import FontProperties import matplotlib.font_manager as fm # 设置中文字体,Windows常用SimHei或Microsoft YaHei,macOS用PingFang SC plt.rcParams["font.sans-serif"] = ["SimHei"] # Windows # 或者 ["PingFang SC"] macOS plt.rcParams["axes.unicode_minus"] = False # 解决负号显示为方块的问题这行配置要在所有绘图代码之前执行。如果你用的是Linux服务器,还得先确认系统里有没有中文字体,没有的话需要安装fonts-wqy-zenhei或者通过fm.addfont()加载字体文件。
我踩过的坑是:设置了字体还是乱码,后来发现是因为代码里没有加axes.unicode_minus=False,负号显示成了方块。两个配置要一起写,少一个都会出问题。
5. 核心实践三:turtle海龟绘图
5.1 海龟绘图的基本玩法
turtle模块是Python标准库里最“好玩”的图形编程工具。它模仿一只带着画笔的海龟在画布上爬行,海龟移动的轨迹就形成了图形。对于理解循环、函数、递归非常有帮助。
基础命令一览:
import turtle # 创建画布和海龟 t = turtle.Turtle() t.speed(3) # 移动和转弯 t.forward(100) # 前进100像素 t.right(90) # 右转90度 t.forward(100) # 控制画笔 t.penup() # 抬笔,移动时不画线 t.goto(-100, -100) t.pendown() # 落笔 t.pensize(3) # 画笔粗细 t.pencolor("red") # 画笔颜色 turtle.done()一个经典练习:用for循环画正方形。
import turtle t = turtle.Turtle() for _ in range(4): t.forward(100) t.right(90) turtle.done()这个例子虽然简单,但它是“代码生成图形”的最直观演示:一次循环代表一条边,4次循环组成一个闭环。理解了它,就能理解后面更复杂的循环嵌套绘图。
5.2 循环、递归与随机:把海龟绘图玩出深度
画正多边形是for循环的经典扩展:正n边形每次转弯360/n度。画个六边形:
import turtle t = turtle.Turtle() t.speed(5) n = 6 side = 100 for _ in range(n): t.forward(side) t.right(360 / n) turtle.done()把循环再套一层,就能画出“旋转花瓣”效果:
import turtle t = turtle.Turtle() t.speed(10) for i in range(36): for _ in range(4): t.forward(100) t.right(90) t.right(10) turtle.done()外循环控制旋转角度,内循环画正方形,每次画完整体旋转10度,旋转36次就是360度。这个效果我第一次跑出来的时候还是挺激动的——原来几行代码就能生成这么漂亮的图案。
递归的威力也值得一提——比如画一棵简单分形树:
import turtle def draw_tree(t, branch_len): if branch_len < 10: return t.forward(branch_len) t.right(30) draw_tree(t, branch_len * 0.7) t.left(60) draw_tree(t, branch_len * 0.7) t.right(30) t.backward(branch_len) t = turtle.Turtle() t.speed(0) t.penup() t.goto(0, -200) t.pendown() t.left(90) draw_tree(t, 100) turtle.done()递归树看着复杂,核心就一行:先画当前长度的树干,再在左右两个方向递归画更短的树干。终止条件是枝干长度小于10像素。如果你刚学函数递归有点绕,用turtle跑一次这个例子,比在纸上推演省力一百倍。
5.3 海龟绘图窗口的常见问题
turtle有两个容易让人困惑的点:
第一,turtle.done()和turtle.exitonclick()的区别。done让窗口保持打开直到手动关闭;exitonclick则是点击画布才关闭。如果代码里没有这两者之一,窗口可能在绘图结束后立即关闭,你根本来不及看结果。
第二,海龟移动速度。t.speed(0)是最快速度,1到10依次加快。绘图复杂时建议用0,不然等待时间很长。另外,turtle.tracer(0)可以关闭逐帧动画,配合turtle.update()手动刷新,能大幅提升复杂图形的渲染速度。对于画分形树这种递归图形,我通常会先tracer(0),画完再update,几毫秒就能出图。
6. 实操汇总:从零实现一个“数据可视化小工具”
这一节把Tkinter、matplotlib、turtle三块知识串起来做一个完整小项目:一个桌面程序,用户输入一组数字,点击按钮后弹出对应折线图,同时用turtle在旁边画一个对应的柱状图。这个项目正好覆盖三种图形编程方式的综合运用。
先看完整代码:
import tkinter as tk import matplotlib.pyplot as plt import turtle def plot_line(): data_text = entry.get() numbers = [float(x) for x in data_text.split(",")] plt.figure() plt.plot(numbers, marker="o") plt.title("Line Plot") plt.show() def plot_turtle_bar(): data_text = entry.get() numbers = [float(x) for x in data_text.split(",")] t = turtle.Turtle() t.speed(0) t.penup() t.goto(-200, 0) t.pendown() for i, num in enumerate(numbers): t.forward(30) t.left(90) t.forward(num * 10) t.right(90) t.forward(15) t.right(90) t.forward(num * 10) t.left(90) t.forward(15) t.left(90) t.hideturtle() turtle.done() root = tk.Tk() root.title("数据可视化小工具") root.geometry("400x200") tk.Label(root, text="输入数字(用逗号分隔):").pack(pady=10) entry = tk.Entry(root, width=30) entry.pack(pady=5) tk.Button(root, text="画出折线图", command=plot_line).pack(pady=5) tk.Button(root, text="用turtle画柱状图", command=plot_turtle_bar).pack(pady=5) root.mainloop()拆解一下这个项目的设计思路:
- 输入层:Entry控件接收用户文本。通过
entry.get()获取输入内容,再用split(",")拆分成列表,float逐个转数值。这里如果用户输入了非数字内容,程序会直接抛异常,更严谨的做法是用try/except捕获,并弹出提示框——这个我留给大家自行扩展。 - matplotlib展示层:点击“画出折线图”按钮,弹出一个独立窗口显示折线图。因为plt.show()是阻塞的,所以窗口关闭前程序会暂停,但不影响Tkinter窗口再次点击。
- turtle展示层:点击“用turtle画柱状图”,会启动海龟画笔,按照输入数字的大小,以比例方式绘制柱状图。注意这里每个柱子的宽度和高度都经过简单换算,让柱子能完整显示在默认画布内。
这个项目看似简单,但它逼着你掌握了几件事:Tkinter控件与事件绑定、matplotlib基本绘图流程、turtle坐标移动与角度控制,以及三种图形工具在一套程序里的协作方式。
如果你要拿这个项目做练习,我建议按难度逐步升级:
- 给输入框加一个异常处理,输入错误时弹窗提示。
- 用matplotlib同时绘制折线图和柱状图,而不是只用turtle。
- 把turtle柱状图换成“排序过程可视化”——随机生成一组数字,每次交换两个数字就重新绘制柱状图,直观展示冒泡排序的运行过程。
第三步是我觉得最有价值的扩展。它把算法和数据可视化结合起来,做完之后你会对图形编程和算法都有更深的理解。
7. 常见问题与排查技巧实录
我把这段时间带学生、包括自己做项目时遇到的典型问题整理成一个排查表,遇到问题按表查就行。
7.1 安装与环境类问题
| 现象 | 原因 | 解决方案 |
|---|---|---|
| 命令行输入python提示不是内部或外部命令 | 安装时未勾选Add Python to PATH | 重装勾选,或手动配置环境变量 |
| import matplotlib提示ModuleNotFoundError | 库未安装或安装到了别的Python环境 | 检查当前Python路径,执行pip install matplotlib,或用python -m pip install matplotlib |
| pip安装非常慢或超时 | 默认源在国外 | 使用清华镜像pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple |
| import matplotlib报DLL加载失败 | 缺少Visual C++运行库 | 去微软官网安装Visual C++ Redistributable |
| Tkinter窗口显示不出来 | 环境缺少tk组件(Linux常见) | Linux执行sudo apt-get install python3-tk |
7.2 绘图与显示类问题
| 现象 | 原因 | 解决方案 |
|---|---|---|
| matplotlib横坐标标签重叠成黑块 | 刻度太多且未旋转 | axios上用plt.xticks(rotation=45)旋转,再用MaxNLocator限制刻度数量 |
| 图中中文显示为方块 | 字体配置未设置 | plt.rcParams["font.sans-serif"] = ["SimHei"],同时设置axes.unicode_minus=False |
| turtle窗口一闪而过 | 没有调用turtle.done()或exitonclick() | 在绘图代码末尾加上turtle.done() |
| matplotlib窗口不弹出,程序直接退出 | IDE设置了非交互后端 | 在代码开头添加import matplotlib; matplotlib.use("TkAgg") |
| plt.show()之后后续代码不执行 | show是阻塞式的 | 改用plt.show(block=False)或把后续代码放前面 |
7.3 代码逻辑类难点
Tkinter中按钮的command参数如果绑定了带参数的函数,不要写成command=myfunc(arg)这样,这会在创建按钮时立即执行函数。正确做法是用lambda:command=lambda: myfunc(arg)。这个点初学几乎必错。
另一个坑是matplotlib和turtle在运行时都要求有GUI环境,如果用的是纯命令行服务器或者云端notebook,需要考虑下面两种处理方式:一是把matplotlib的backend切换成Agg并保存图片(plt.savefig),二是在turtle代码里用turtle.getcanvas()配合保存画布,或者干脆换用matplotlib实现柱状图。
7.4 实测过程中的几个心得
最后分享几个我个人在教这一节时的经验体会。
Tkinter入门,一定要从一个带按钮的示例跑通再扩展。很多人一上来就试图写一个复杂界面,结果报错后根本不知道问题在哪。先跑通“窗口+按钮+回调函数”的最小闭环,后面所有复杂界面都是这个骨架。
matplotlib的坐标系问题要反复强调。x轴、y轴、刻度、标题,每一项都可以用代码控制。初学者最常见的困惑其实是“我到底应该调哪个函数”,记住一个准则:凡是影响全局的(字体、尺寸、整体风格)用plt.rcParams、plt.figure;凡是影响某个坐标轴的用plt.xlabel、plt.xticks这类;凡是针对某个子图的,在axes对象上调用对应方法。
turtle的价值不在于画多好看的图,而在于“让代码运行过程可见”。如果你觉得某个算法学不懂,用turtle把每一步画出来,通常很快就能理解。我在讲递归和分形时,要求学生必须写一遍递归树代码,这种视觉反馈带来的理解深度是纯文字讲解完全比不了的。
还有一点,图形编程写完之后,尽量把代码整理成“可复现”的格式:数据用变量统一管理,绘图参数集中在开头或函数参数里,注释写清楚每个窗口坐标参数的含义。这样不仅方便自己调试,也方便别人看懂你的代码。很多同学写完隔一周回来看就忘了当时坐标为什么这么设,统一管理能省下不少时间。