Python带娃编程系列实践-第1周(彩蛋版):女儿说“翻牌子”——翻转卡墙的诞生记
【Python带娃编程系列实践】第1.5周:女儿说“翻牌子”——翻转卡墙的诞生记
专栏名称:Python带娃编程系列实践
专栏作者:制造数据与AI践行者老蒋(javy21)
作者CSDN:制造数据与AI践行者老蒋-CSDN博客
📌 写在前面
上一篇“明星呼吸灯墙”发出来后,女儿很开心。她盯着屏幕上那些会“呼吸”的偶像照片看了好一会儿,然后转过头来,眼睛亮晶晶地跟我说了一句话:
“老爸,能不能做一个更酷的?每一张卡片正面是统一的封面,点一下才翻过来看到明星?就像……玩翻牌子那样!”
你看,孩子一旦觉得“这个东西我能参与设计”,她的想象力就收不住了。
我当场答应了她。于是就有了今天这篇——第1.5周特别篇:明星翻转卡墙。
这篇不算正式的周更,算是“用户需求驱动的快速迭代版”。前后花了不到一个小时,从她提需求到跑通上线。全程她在一旁看着,时不时提点配色建议——“这个粉色太土了,换个马卡龙色!”
本文适合:已经跑通上一篇呼吸灯墙的读者,想带孩子体验“需求→实现”完整流程的家长。
预计耗时:如果你已有环境,复制代码+调试,20分钟搞定。
🤔 为什么要做这个“彩蛋版”?
因为“好玩”本身就是最大的学习动力。
女儿提出“翻转卡”的想法时,我意识到这是一个绝佳的教育机会——让她看到:
需求是怎么变成代码的——她提了一个交互想法,我把它拆解成“点击→翻转→显示背面”三个步骤。
调试是编程的一部分——第一次运行时页面报错了(后面会细说),我当着她的面一步步排查,她看到了“出bug→修bug”的真实过程。
改一个参数就能改变整个效果——她调整了卡片颜色,页面瞬间变样,她惊呼“原来颜色是这么控制的”。
这些体验,比单纯教她写for循环要珍贵得多。
🛠️ 核心原理(用大白话讲给孩子听)
这部分是给孩子看的,家长可以念给娃听。
问:卡片是怎么“翻”过去的?
答:想象一张扑克牌,正面朝上放在桌上。我们用 CSS 给这张牌加了一个“旋转轴”(Y轴),然后通过transform: rotateY(180deg)让它像门一样转了半圈——正面翻到了背面,背面翻到了正面。
问:为什么点击才翻,不是鼠标移上去就翻?
答:因为女儿说“点击才有掌控感”。鼠标移上去就翻,感觉卡片不受控制;点击一下翻过来,再点击翻回去——每个动作都是自己主动触发的,这种体验更适合初中生。
问:那个“封面颜色”是怎么做到每张不一样的?
答:我们在 Python 后端准备了一组马卡龙色板(粉色、黄色、薄荷绿、薰衣草紫……),每张卡片随机选一个,传给前端。这样每张卡片的封面都不同,看起来像一墙的“惊喜盲盒”。
💻 具体怎么做的(精简版)
第1步:新增一个路由(在app.py里加)
在原有的app.py中追加/flip路由,基本逻辑和呼吸灯墙一样——扫描照片文件夹,构建数据列表。唯一的区别是多传了一个cover_color(随机封面颜色)。
@app.route('/flip') def flip_cards(): star_images = scan_star_images(STAR_FOLDER) # 马卡龙色板(女儿亲自挑的) color_palette = [ '#FFB3BA', '#FFDFBA', '#FFFFBA', '#BAFFC9', '#BAE1FF', '#E8BAFF', '#FFB3E6', '#B3FFE5', '#FFD1DC', '#C9E4DE' ] star_data = [] for idx, filename in enumerate(star_images): display_name = os.path.splitext(filename)[0] star_data.append({ 'name': filename, 'display_name': display_name, 'rotation': random.randint(-2, 3), 'delay': round(idx * 0.1, 2), 'cover_color': random.choice(color_palette) }) return render_template('week01_flip.html', stars=star_data, week_num='1+ (彩蛋)')第2步:新建页面模板(week01_flip.html)
核心是 CSS 3D 翻转 + 点击切换 class:
<div class="flip-card"> <!-- 正面:彩色封面 --> <div class="card-front" style="background-color: {{ star.cover_color }};"> <div class="cover-icon">✨</div> <div class="cover-text">点击揭秘</div> </div> <!-- 背面:明星照片 --> <div class="card-back"> <img src="..."> <div class="back-name">⭐ {{ star.display_name }}</div> </div> </div>点击时用 JavaScript 切换.flipped类:
card.classList.toggle('flipped');CSS 里.flipped让卡片旋转 180 度。
🐛 调试实录:第一次运行报错了(这是最有价值的部分)
报错信息:
UndefinedError: 'star' is undefined原因分析:我在<style>标签里直接用了{{ star.rotation }},但{{ star.xxx }}是 Jinja2 模板变量,只能在 HTML 正文(<body>)的循环里使用,不能在<style>里用。
通俗解释(我给女儿讲的):就像你有一个装满零食的盒子(stars列表),你只能在餐厅里(<body>)打开盒子拿零食吃,不能在客厅(<style>)里伸手进去拿——客厅没有盒子。
解决方案:把所有动态样式从<style>移到 HTML 元素的内联样式(style="...")里。
修复前(报错版):
.flip-card-container { transform: rotate({{ star.rotation }}deg); /* ❌ 这里不能用 */ }修复后(正确版):
<div class="flip-card-container" style="transform: rotate({{ star.rotation }}deg);">启示:孩子可以看到——编程里“写在哪里”和“写什么”同样重要。同样的代码,位置不对就会报错。
🎯 女儿参与了哪些环节?
| 环节 | 她的参与 | 她的收获 |
|---|---|---|
| 需求提出 | “爸,做个翻牌的!” | 学会表达想法、定义需求 |
| 颜色选择 | 从色板里挑出她喜欢的马卡龙色 | 知道“颜色代码”是什么 |
| 调试观察 | 看我排查star is undefined错误 | 看到“出bug→修bug”是常态 |
| 验收测试 | 点击每张卡片,检查是否正常翻转 | 学会“测试”和“反馈” |
她最后说了一句:“原来做一个功能要经历这么多步骤啊。”
——这句话比她会写100行代码更有意义。
📢 下期预告:第2周 —— 双色球模拟器
下期我们要做一个和“运气”有关的案例:双色球模拟器。
女儿有时候会看到新闻里说“某某中了双色球头奖”,好奇地问“中奖概率到底有多低?”——这个问题正好可以用 Python 来回答。
我们将实现:
随机生成一注双色球号码(6个红球 + 1个蓝球)
模拟100万次开奖,统计中奖频率
用柱状图可视化展示每种奖级的出现概率
数学 + 编程 + 生活常识,一次讲透。
敬请期待!
💬 想听听你的反馈
这篇是呼吸灯墙的“彩蛋补充版”,不是正式周更,但我还是想知道:
你家孩子有没有类似“突发奇想”的需求?孩子提了什么“异想天开”的功能?
你带娃调试时遇到过什么有趣的bug?欢迎评论区分享。
你的反馈会帮助我把后面的教程写得更好。下一期双色球,我们不见不散!
📌源码地址:代码整理中,后续会在评论更新链接。
📌专栏目录:【Python带娃编程系列实践】——每周一篇,从零到一。
📌关于作者:制造数据与AI践行者老蒋(javy21),20多年软件行业老兵,CSDN博客专家。用代码陪伴女儿成长。