freeCodeCamp 课程解读:Drawing a Shape —— 用 Python print 语句在控制台绘制图形的视频课与课后测评全解析
本指南围绕 freeCodeCamp 开源课程中 Python 入门阶段的视频课 "Drawing a Shape"(drawing-a-shape-video.md)展开,它是 "Core Primitives in Python"(Python 核心原语)讲座块的第一节课,主题是如何用一条条 print 语句把一个基础图形(三角形)逐行打印到控制台。读完本文,你将掌握本课程在免费课程体系中的结构与文件规范,理解 print() 逐行输出的底层行为,并能逐条剖析其课后测评的四个选项,最终获得可直接在本地运行验证的完整示例代码。
一、这节课在 freeCodeCamp 课程体系中的位置
在深入了解文件本身之前,先看它属于哪个课程模块。根据 block 结构文件 core-primitives-in-python.json,Core Primitives in Python 是一个 challenge-list 布局的讲座块("blockLabel": "lecture"),共包含 5 个视频课时,按顺序为:
- Drawing a Shape
- Variables and Data Types
- Working with Strings
- Working with Numbers
- Getting Input from Users
这一块的 helpCategory 为 Python,说明它属于 Python 课程。向上追溯,superblock 结构文件 learn-python-for-beginners.json 列出了 Python 入门认证课程的 8 个块,core-primitives-in-python 位于第二位,前面是 python-setup-first-steps(含 Introduction / Installing Python and PyCharm / Hello World Program 等视频课,见 python-setup-first-steps 目录),后面依次是小型 Python 项目、列表与元组、控制流与函数等。也就是说,"Drawing a Shape" 是学习者完成环境搭建与 Hello World 之后、系统接触 Python 核心原语的第一课,承担着"体验多行输出"的入门角色。
二、挑战文件结构:front-matter、描述与测评区
本课内容存放在课程源文件中,采用 freeCodeCamp 的标准挑战 Markdown 格式:文件头部是 YAML front-matter,之后以 # --description-- 与 # --questions-- 分隔教学描述与随堂测评。
front-matter 字段逐项说明
源文档第 1~7 行定义了如下元信息:
| 字段 | 值 | 含义 |
|---|---|---|
id |
62baa9d28e8723f635a0093e |
挑战全局唯一 ID,用于块内排序、数据库关联与进度追踪 |
title |
Drawing a Shape |
课程标题,同时展示在学习界面的挑战列表 |
challengeType |
11 |
挑战类型,11 即 video 类型 |
videoId |
vcNZZSeyZkY |
视频平台上的外部视频标识 |
dashedName |
drawing-a-shape |
短横线命名,用于 URL 与文件定位 |
其中 challengeType 的取值定义在共享包 challenge-types.ts 中:const video = 11(第 13 行)。同一文件中还可以确认 video 类型的三条配套规则:它被列入 hasNoSolution(视频课没有传统意义上的代码答案,见第 75~103 行),其 viewTypes 为 generic(渲染为通用视频播放页,第 117 行),submitTypes 为 tests(完成以测评通过为准,第 159 行)。
这些约束在课程校验层同样生效。schema 定义 challenge-schema.js 要求所有挑战必须有 challengeType(第 180 行),并且当 challengeType 为 video 时:videoId 为必填(第 294 行附近),questions(随堂测评)也为必填(第 314 行附近)。因此本文件的 videoId 与 questions 部分都不是可选项,而是视频课格式的硬性要求。
教学描述与测评区
文件第 9~11 行的描述区只有一句话:
In this video, you will learn how to print a basic shape to the console using
(在这段视频中,你将学习如何使用 print 语句向控制台打印一个基础图形。)
随后第 13~54 行是 --questions-- 测评区:给出题干"Which of the following is the correct way to print a triangle to the console?"(下面哪个选项是在控制台打印三角形的正确方式),列出 4 个候选答案,最后以 --video-solution-- 标注正确答案序号 4。测评区必须紧跟视频内容,学习者看完视频后选择答案,以此验证是否真正理解了 print 的逐行输出机制。
三、核心知识点:print 是"一语句一行"
本课要解决的第一个概念问题,是为什么打印一个图形需要好几条 print 语句,而不是一条。这与 Python print() 的行为直接相关:
print()每次调用会输出其参数,并默认在末尾追加一个换行符\n;- 因此一次调用只产生一行控制台输出;
- 要构造一个多行的图形(例如 4 层高的三角形),就需要依次执行多条
print,每条负责一行; - 在 Python 中,多条
print顺序执行时,输出会按行自然堆叠,形成"字符画"。
第二个概念是字符串字面量必须用引号包裹。Python 中未经引号的裸字符(如 /|)会被当作表达式解析,/ 会被理解为除法运算符,从而导致语法错误(SyntaxError)。只有写成 " /|" 这样的字符串,斜杠、竖线、空格和下划线才会被原样作为文本输出。
第三个概念同样关键:字符串内部的空格是内容的一部分。字符串 " /|" 开头的三个空格会精确地出现在控制台上,正是这些前置空格决定了每一行图形的水平偏移,从而勾勒出三角形的斜边。控制台图形的核心技巧,就是精心计算每行字符串内的前置空格数量。
本课目标图形
四个选项都围绕同一个目标形状展开——一个由 /(斜边)、|(垂直边)与 _(底边)组成的直角三角形,期望输出效果如下:
print(" /|")
print(" / |")
print(" / |")
print("/___|")
运行后控制台显示:
/|
/ |
/ |
/___|
如果对齐四个字符画观察坐标系:第一行 / 位于第 4 个字符、第二行第 3 个、第三行第 2 个、第四行第 1 个,/ 每次左移一列,形成一条平滑的斜边;而 | 始终固定在同一列,构成竖直的直角边;末行用 _ 填充斜边与竖直边之间,构成底边。
四、课后测评:四个选项逐条剖析
本课测评要求选出"打印三角形的正确方式",正确答案是第 4 个选项(--video-solution-- 为 4)。下面把四个选项逐一拆解,弄清它们为什么错、为什么对。
选项 1:所有内容塞进一条 print
print(" /| / | / | /___|")
这条语句语法合法,但只调用了一次 print,因此控制台上只会出现一行长文本 /| / | / | /___|。三角形被横向"摊平"在同一条线上,且各段之间的空格数不一致(1、2、1 个),根本无法还原图形轮廓。它违背了"一个图形行对应一条 print"的核心原则。
选项 2:漏掉引号
print( /|)
print( / |)
print( / |)
print(/___|)
这组代码结构上分成了 4 行,思路正确,但致命错误是字符串没有加引号。Python 解释器看到裸的 / 会尝试把它当作运算符解析, /| 并不是合法表达式,会直接抛出 SyntaxError,程序根本无法运行。这一选项同时也说明了本课反复强调的"字符串必须加引号"这一前提。
选项 3:斜边没有逐行左移
print(" /|")
print(" / |")
print(" / |")
print("/___|")
这组代码每条都加了引号、也分了行,语法完全正确。但观察每行的 / 位置:前三行的 / 都停留在同一列,只有最后一行的 / 才跳到最左边,而竖直边 | 的位置每一行都不同。这样的字符画无法形成一条连续的斜边,视觉上只是几条参差不齐的散线,而不是一个规整的三角形。
选项 4:正确答案
print(" /|")
print(" / |")
print(" / |")
print("/___|")
这是唯一同时满足三个条件的写法:
- 引号完整:每个字符串都正确加引号,可正常执行;
- 逐行打印:4 次
print对应图形的 4 行,利用默认换行实现行堆叠; - 空格精确:前置空格从 3、2、1 到 0 逐行递减,使
/组成的斜边平滑左移,同时|始终对齐在同一列。
因此它是四个选项中唯一能在控制台正确呈现三角形的方式,也正是 --video-solution-- 取值为 4 的原因。
五、同一思路的延伸:让"图形打印"更灵活
掌握了"一语句一行 + 引号内空格即内容"之后,可以在不改变本课主题的前提下做几组小练习,加深对输出的掌控(以下为便于验证自行编写,非课程视频内容的转述):
延伸 1:用字符串重复生成对称图形
print 中可以使用字符串乘法快速生成重复字符。下面用 * 运算符构造一个逐行变宽的等腰三角形:
for i in range(1, 5):
print(" " * (5 - i) + "*" * (2 * i - 1))
输出:
*
***
*****
*******
这里同时用到了两个知识点:" " * n 生成前置空格(延续本课的偏移思想),"*" * m 生成本行的星号内容。
延伸 2:用三引号一次性输出多行
当图形行数固定且不需要循环时,Python 的多行字符串(三引号)也能实现同样效果,但要注意它会引入字符串内部的换行:
print(""" /|
/ |
/ |
/___|""")
输出与本课目标完全一致。对比可知,"多条 print"与"一条多行字符串"各有适用场景:前者适合用循环动态生成,后者适合静态整块输出。
延伸 3:用 end 参数控制行尾
print 默认以换行结束,但它的 end 参数可以改写行尾字符。例如下面用空格作结尾,在一行内铺开图形:
print(" /|", end=" ")
print(" / |", end=" ")
print(" / |", end=" ")
print("/___|")
理解 end 默认值为 "\n",也就理解了一开始"为什么一条 print 只输出一行"。
六、本地验证与仓库内的校验机制
本课没有传统意义上的"可提交代码"(video 类型在 challenge-types.ts 中属于 hasNoSolution),其测评在课程前端以选择题形式作答。如果你想本地验证选项 4 的输出,只需把对应 4 行代码保存为 shape.py,然后用 Python 解释器执行即可:
python3 shape.py
(若系统默认命令为 python,替换即可;本课代码不依赖任何第三方库。)
至于课程文件本身是否合法,则交由课程工具链校验。freeCodeCamp 仓库的 schema 校验代码 challenge-schema.js 与其配套测试 challenge-schema.test.mjs 会对所有挑战文件做结构化检查,例如 videoId、questions 是否在 video 类型下齐全;challengeTypes 常量则被 challenge-types.ts 集中维护。若你修改了本文件的 front-matter(例如误删 videoId 或把 challengeType 改成其他数字),这些测试便会失败,从而保证视频课的格式在长期演进中保持一致。
七、小结
"Drawing a Shape" 作为 Python 入门讲座块的第一个课时,用"在控制台画一个三角形"这件小事,把 print 的逐行输出、字符串必须加引号、字符串内空格即内容这三点讲透。其挑战源文件 drawing-a-shape-video.md 同时展示了 freeCodeCamp 视频课的标准文件结构——YAML front-matter 声明类型与视频 ID,description 描述学习目标,questions 与 video-solution 承载随堂测评。理解这一课的知识点与文件规范,既有助于你掌握 Python 的基础输出能力,也能帮你读懂整个 freeCodeCamp 课程体系中同类视频课的存储与校验方式。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00