表达式 · 类型 · 循环 · 字符串 · 凯撒加密
每一段代码上面都有「接下来我们要做什么」任务提示,下面配了「豆豆老师小课堂」:先讲一句话目的,再讲实现思路、逐行注释和输出为什么是这样。学完一个知识点,马上有「豆豆点一点」小练习和每章末尾的小测验——点点选项,选哪个都有讲解!
全部展开讲解
共 131 节小课堂 · 9 个答疑站 · 9 套小测验 + 知识点练习
提示:① 先读代码上方的「接下来」提示,想想“这一步要做什么”;② 点一下每段代码下方的「豆豆老师小课堂」卡片展开讲解;③ 遇到「豆豆点一点」/「豆豆小测验」,随便点个选项,看看讲解学得更牢;④ 每学到一个新概念,就会有一块「新积木」在你面前亮起来,隔一段还有「积木收藏盒」帮你盘点。
🧭 豆豆老师的 Python 概念地图
学编程就像搭积木:程序就是由一些「积木」组成的——语句、表达式、运算符……这些积木我们一个一个学:学到哪个,哪块积木就会出现在你面前,地图越拼越完整!
程序 = 一串「语句」statement(先记住这个大框架就够了)
01
表达式与语句 expression
include operator and operand
2 + 3
2 < 3
2 < 3 and 5 < 4
width * height
terminal expression
each expression will be evaluated
statement
input-process-output
input function/statement
output function/statement
assignment statement
豆豆老师小课堂 这一页先认识几个“接头暗号”:表达式、运算符、操作数。看懂它们,后面每段代码都能拆开读懂。
▸
它是怎么实现的 电脑做事,靠的是“表达式”——一段能算出答案的代码。比如 2 + 3:它不是一个死的字,电脑会真的把它算成 5。里面干活的是“运算符”(+ - * / < > 这些符号),被运算的“值”叫“操作数”(2 和 3)。就连单独一个 3 或一个 'a',电脑也会“算出它自己”,所以值本身就是最简单的表达式。
逐行讲解(带注释版代码)
2 + 3 # + 是运算符,2 和 3 是操作数,电脑算出 5
2 < 3 # < 是比较运算符,电脑算出一个“真假”答案
width * height # * 是乘号,等你有 width、height 两个数,它就算面积
3 # 单独一个数字,也是表达式——电脑算出它自己
'a' # 单独一个文字,也是表达式——电脑原样还给你
2 + 3+ 是运算符,2 和 3 是操作数,电脑算出 5
2 < 3< 是比较运算符,电脑算出一个“真假”答案
width * height* 是乘号,等你有 width、height 两个数,它就算面积
3单独一个数字,也是表达式——电脑算出它自己
'a'单独一个文字,也是表达式——电脑原样还给你
为什么输出是这个 这些写法都会“被求值”:电脑把每一段都算成一个具体的值。所以写代码就像给电脑出题,它负责算。
豆豆提醒 判断运算符干什么,先看操作数是什么类型:数字配数字做算术,文字配文字做拼接——后面马上会见到这两种“+”。
🧱 新积木 1/10 值 value3、'a' 这种具体的“东西”,电脑一看就懂,直接等于它自己
🧱 新积木 2/10 表达式 expression会算出“值”的算式:2 + 3 会算出 5
接下来 把数字 2 存进变量 a——认识“变量”:给数据贴一张名字标签,以后叫 a 就能找到它。
In [1] 复制
a = 2
name = 'arianna'
豆豆老师小课堂 把两个“值”装进两个贴了名字的盒子里:a 装数字 2,name 装文字 'arianna'。
▸
它是怎么实现的 编程里的“变量”就像一个贴了标签的小盒子。等号右边是要装进去的东西——而且右边的 2 或 'arianna' 自己也是表达式,电脑先把它们“算出自己”,再装进盒子。以后喊名字,电脑就把盒子里的东西拿出来。这个等号叫 assignment operator(赋值运算符),这一整行叫 assignment statement(赋值语句)——它的作用,就是给变量赋一个全新的值。
逐行讲解(带注释版代码)
a = 2 # 造一个叫 a 的小盒子,把数字 2 放进去
name = 'arianna' # 再造一个叫 name 的小盒子,把文字 'arianna' 放进去。注意文字要穿“引号”小外套
a = 2造一个叫 a 的小盒子,把数字 2 放进去
name = 'arianna'再造一个叫 name 的小盒子,把文字 'arianna' 放进去。注意文字要穿“引号”小外套
为什么输出是这个 这两行只是“放东西”,没有让电脑显示任何字,所以运行后没有输出。
豆豆提醒 变量名有规矩:只能由字母、数字、下划线组成,不能以数字开头(比如 2name 不行),一般就用一个小写单词,如 a、name、width。文字(字符串)一定要用引号包起来,数字不用——这也是 Python 的规矩。
🧱 新积木 3/10 变量 variable给数据贴一张名字标签,以后叫它就能找到
接下来 让电脑问用户长方形的宽和高,把答案存起来,下一步就要算面积了。
In [2] 复制
# ask user input width and height of a rectangle
# output area of rectangle
豆豆老师小课堂 写代码前的“小计划”:告诉电脑接下来要做两件事——问长方形的宽和高,再算出面积。
▸
它是怎么实现的 以 # 开头的行叫“注释”,是写给人类看的小便签,电脑会直接跳过,不执行。写代码前先写计划,思路会更清楚。
逐行讲解(带注释版代码)
# ask user input width and height of a rectangle
# output area of rectangle
# ask user input width and height of a rectangle计划第 1 步:让用户输入长方形的宽和高
# output area of rectangle计划第 2 步:输出长方形的面积
为什么输出是这个 两行都是注释,电脑什么都不做,所以没有输出。
接下来 用 float 这个“翻译机”,把文字 '2.3' 翻译成小数 2.3——看看翻译得对不对。
In [3] 复制
float('2.3')
豆豆老师小课堂 把文字 '2.3' 变成真正的小数 2.3。
▸
它是怎么实现的 float 就像一台“文字变小数”的翻译机:把穿引号的数字文字,翻译成能参加数学计算的小数。
逐行讲解(带注释版代码)
float('2.3') # 把文字 '2.3' 翻译成小数 2.3,翻译好的结果就是这个 cell 的答案
float('2.3')把文字 '2.3' 翻译成小数 2.3,翻译好的结果就是这个 cell 的答案
为什么输出是这个 输出 2.3:翻译机成功把文字变成了小数。这个 2.3 就是 float 函数的“返回值”(return value)——机器加工完吐出来的结果,可以存进变量继续用。注意输出的小数没有引号,说明它是真的数,不是文字。
豆豆提醒 函数都会返回一个值:float('2.3') 返回 2.3,int('2') 返回 2,input(...) 返回你输入的文字。拿到返回值,就能接着往下算。
接下来 先猜一猜:文字 '2.2' 翻译成整数会怎样?小数部分是被砍掉还是四舍五入?
In [4] 复制
int('2.2')
ValueError: invalid literal for int() with base 10: '2.2'
---------------------------------------------------------------------------ValueError Traceback (most recent call last)Cell In[4], line 1
----> 1 int('2.2')
ValueError: invalid literal for int() with base 10: '2.2'
豆豆老师小课堂 试着把文字 '2.2' 变成整数,结果电脑生气了,报错。
▸
它是怎么实现的 int 是“文字变整数”的翻译机。但它只认“干干净净”的整数文字,比如 '2';'2.2' 带着小数点,翻译机不认识,就报错了。
逐行讲解(带注释版代码)
int('2.2') # 想请 int 把文字 '2.2' 变成整数——但 2.2 不是整数,翻译机罢工
int('2.2')想请 int 把文字 '2.2' 变成整数——但 2.2 不是整数,翻译机罢工
为什么输出是这个 报 ValueError(值错误):int 说“你给我的 '2.2' 不是合法的整数,我没法翻译”。想保留小数要用 float。
豆豆提醒 int 只做“取整截断”式翻译:int('2') 可以,int('2.2') 不行——它根本不认识带小数点的文字。
接下来 文字 '2' 翻译成整数 2——int 只收“整整齐齐”的整数文字,记住它的脾气。
In [5] 复制
int('2')
豆豆老师小课堂 把文字 '2' 变成整数 2。
▸
它是怎么实现的 还是那台 int 翻译机,这次输入是干净的整数文字 '2',翻译成功。
逐行讲解(带注释版代码)
int('2') # 把文字 '2' 翻译成整数 2
为什么输出是这个 输出 2(没有引号),说明变成了真正的整数。
接下来 数字加法:123 + 4。两个数字放一起,电脑按数学规则算。
In [6] 复制
123 + 4
豆豆老师小课堂 两个数字相加:123 + 4。
▸
它是怎么实现的 两个都是真正的数字,Python 就做数学加法。记住加号的规矩:两边必须是同一种东西——数字配数字,就按数学算。
逐行讲解(带注释版代码)
123 + 4 # 数字 123 和数字 4 用 + 连接,做数学加法,算出 127
123 + 4数字 123 和数字 4 用 + 连接,做数学加法,算出 127
为什么输出是这个 输出 127。数字相加就是数学里的加法,结果也是数字。
豆豆提醒 判断加号干什么,先看两边的类型:数字 + 数字 → 算术加法。
接下来 文字拼接:'123' + '4'。都是文字,中间的 + 就变成“粘在一起”,可不是加法哦。
In [7] 复制
'123' + '4'
豆豆老师小课堂 两个带引号的文字 '123' 和 '4' 相加。
▸
它是怎么实现的 带引号的是文字(字符串),加号对文字来说不是“加钱”,而是“手拉手排队”——把两串文字接在一起,叫“拼接”。
逐行讲解(带注释版代码)
'123' + '4' # 把文字 '123' 和文字 '4' 拼接成一串 '1234'
'123' + '4'把文字 '123' 和文字 '4' 拼接成一串 '1234'
为什么输出是这个 输出 '1234':不是 127!因为它们是文字不是数字,加号只是把它们并排贴在一起。
豆豆提醒 判断加号是“加法”还是“拼接”,就看两边有没有引号。
🧱 新积木 4/10 运算符 + 操作数 operator + operand运算的两边都是表达式:+ 号两边站的,就是操作数
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. 下面代码会输出什么?
print('123' + '4')
A 127B '1234'C 1234D 报错
127 是数字相加的结果,但这里两边都带引号,是文字。
✓ 对!文字 + 文字 = 拼接,得到 '1234'。
1234 不带引号是数字的写法,Python 输出带引号的文字。
文字 + 文字完全合法,不会报错。
📖 完整思路:两边都是文字,+ 是拼接:'123' 和 '4' 粘在一起。
2. 下面代码会输出什么?
print(123 + 4)
A 127B '1234'C 1234D 报错
✓ 对!数字 + 数字 = 数学加法,127。
'1234' 是文字拼接的结果,这里两边没有引号。
1234 是把 123 和 4 连起来,加法不会这么算。
数字 + 数字完全合法,不会报错。
📖 完整思路:两边都是数字,+ 是数学加法:123 + 4 = 127。
接下来 数字 2 加文字 '2'——两种类型混搭,猜猜 Python 会怎么反应?
In [8] 复制
2 + '2'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
---------------------------------------------------------------------------TypeError Traceback (most recent call last)Cell In[8], line 1
----> 1 2 + '2'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
豆豆老师小课堂 让数字 2 和文字 '2' 相加,电脑报错。
▸
它是怎么实现的 加号有个规矩:两边必须是同一种东西。这一行左边是数字 2(int),右边却来了文字 '2'(str)。加号一看:咦,我这边是数字,那边怎么是文字?类型不一致,电脑不知道按算术算还是按拼接算,干脆拒绝。
逐行讲解(带注释版代码)
2 + '2' # 数字 2 想加文字 '2'——左边是数字,右边是文字,类型不一样,加不了
2 + '2'数字 2 想加文字 '2'——左边是数字,右边是文字,类型不一样,加不了
为什么输出是这个 报 TypeError(类型错误):int 和 str 不能混着用 +。就像“3 个苹果 + 3 个梨”没法直接说成 6。
豆豆提醒 口诀:加号两边必须同类——数字配数字做算术,文字配文字做拼接;左边是数字,右边也必须来数字。
接下来 这次反过来:文字 '2' 加数字 2。看看报错信息,记住这个坑。
In [9] 复制
'2' + 2
TypeError: can only concatenate str (not "int") to str
---------------------------------------------------------------------------TypeError Traceback (most recent call last)Cell In[9], line 1
----> 1 '2' + 2
TypeError: can only concatenate str (not "int") to str
豆豆老师小课堂 反过来的搭配:文字 '2' 加数字 2,同样报错。
▸
它是怎么实现的 这一行反过来:加号先看左边——是文字 '2',那右边也必须是文字才能拼接。结果右边来了个数字 2,类型不一致,加号说:你要拼接,怎么给我数字?报错。
逐行讲解(带注释版代码)
'2' + 2 # 文字 '2' 想加数字 2——左边是文字,右边也必须是文字,结果来了数字
'2' + 2文字 '2' 想加数字 2——左边是文字,右边也必须是文字,结果来了数字
为什么输出是这个 报 TypeError:只能把文字和文字拼接,不能把数字硬塞进来。
豆豆提醒 看加号左边是什么类型,右边就得跟它一样:左边是字符串,右边必须是字符串,否则就报错。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. 下面代码会输出什么?
print('2' + 2)
A 4B '22'C 22D 报错
4 需要两边都是数字才能算出来。
'22' 需要两边都是文字才能拼接。
22 是拼接写法,但这里类型不一致。
✓ 对!文字和数字不能相加,报 TypeError。
📖 完整思路:左边文字 '2'、右边数字 2,类型不匹配,Python 报 TypeError。
2. 想让 '2' + 2 正常运行,应该先?
A int('2') 把左边变数字B float(2) 把右边变文字C 什么都不用做D 删掉一个引号
✓ 对!int('2') = 2,两边都变数字,就能相加了。
float(2) 还是数字,类型还是对不上。
不处理会一直报错,类型必须统一。
删引号就变成变量名了,会报 NameError。
📖 完整思路:把文字 '2' 翻译成数字 2,两边就都是数字了:2 + 2 = 4。
接下来 用 input 问用户要一个数,存进变量 a——先跑跑看它返回的是什么。
In [11] 复制
a = input("num: ")
b = input("num: ")
c = a + b
print(c)
豆豆老师小课堂 用 input() 让用户输入两个数,再打印相加结果。
▸
它是怎么实现的 input 像一台“会问问题的机器”:程序停在这里,等你在终端打字回车。注意:input 问回来的东西永远是“文字”,所以 a 和 b 都是文字,加号是拼接。
逐行讲解(带注释版代码)
a = input("num: ") # 问用户“num: ”,把输入存进盒子 a——存的是文字
b = input("num: ") # 再问一次,把输入存进盒子 b——也是文字
c = a + b # 两个文字拼接,c = '22' + '33'
print(c) # 把 c 显示出来
a = input("num: ")问用户“num: ”,把输入存进盒子 a——存的是文字
b = input("num: ")再问一次,把输入存进盒子 b——也是文字
c = a + b两个文字拼接,c = '22' + '33'
print(c)把 c 显示出来
为什么输出是这个 输入 22 和 33,输出 2233:因为 input 返回的是文字,加号把 '22' 和 '33' 拼接成了 '2233',不是数学里的 22+33=55。
🧱 新积木 5/10 输入语句 input statement让电脑停下来等你打字,把答案拿进来
接下来 再问一次 input,这次重点看:拿到手的到底是数字还是文字?
In [12] 复制
a = input("num: ")
b = input("num: ")
c = a + b
print(c)
豆豆老师小课堂 和上个 cell 一模一样的代码,只是输入变成了小数。
▸
它是怎么实现的 代码没变,变的只是用户输入。input 依然返回文字,加号依然是拼接。
逐行讲解(带注释版代码)
a = input("num: ") # 输入 2.2,存进 a(文字 '2.2')
b = input("num: ") # 输入 3.3,存进 b(文字 '3.3')
c = a + b # 文字拼接
print(c) # 打印拼接结果
a = input("num: ")输入 2.2,存进 a(文字 '2.2')
b = input("num: ")输入 3.3,存进 b(文字 '3.3')
c = a + b文字拼接
print(c)打印拼接结果
为什么输出是这个 输出 2.23.3:'2.2' 和 '3.3' 拼接成 '2.23.3',证明了 input 拿到的都是文字。
接下来 请 type 侦探出场:查一查 '2' 是什么类型?
In [13] 复制
# input function return str type value
豆豆老师小课堂 一条注释,提醒我们一个重要的知识点:input 函数返回的是字符串(文字)类型。
▸
它是怎么实现的 这句话是给学习者的小抄,记下 input 的“性格”:不管用户输数字还是字母,它都当文字收下。
逐行讲解(带注释版代码)
# input function return str type value
# input function return str type value小抄:input 函数返回的是 str(字符串/文字)类型的值
🧱 新积木 6/10 函数调用 function callint() float() str() 是“翻译机”,传进一个值,返回一个新值
接下来 再查:数字 2 是什么类型?和 '2' 比一比,差一个引号差多少。
In [14] 复制
type('2')
豆豆老师小课堂 问一下:'2' 是什么类型?答案是文字(str)。
▸
它是怎么实现的 type() 像一台“类型体检机”,把东西放进去,它告诉你这是文字还是数字。
逐行讲解(带注释版代码)
type('2') # 给文字 '2' 做体检,看它是什么类型
type('2')给文字 '2' 做体检,看它是什么类型
为什么输出是这个 输出 str:str 是 string(字符串)的缩写,意思就是“文字类型”。
接下来 双引号和单引号里的 2,类型一样吗?type 一下见分晓。
In [15] 复制
type(2)
豆豆老师小课堂 问一下:2 是什么类型?答案是整数(int)。
▸
它是怎么实现的 还是 type 体检机,这次体检对象是不带引号的 2。
逐行讲解(带注释版代码)
type(2) # 给数字 2 做体检
为什么输出是这个 输出 int:int 是 integer(整数)的缩写,意思是“整数类型”。
🧰 积木收藏盒 · 学到这里,你已经点亮 4 块积木
值 value表达式 expression变量 variable运算符+操作数 operator + operand
新学的积木会自动掉进盒子,继续往下学吧!
接下来 带提示的 input:括号里的 'num:' 是参数——input 函数要的“小纸条”。
In [16] 复制
a = input("num: ") # num: is argument of input function
b = input("num: ")
a = int(a) # f(f(g(x)))
b = int(b) # a, b argument
c = a + b
print(c)
豆豆老师小课堂 把 input 拿到的文字用 int() 翻译成整数,再做真正的加法。
▸
它是怎么实现的 上一课发现 input 给的是文字,加法变成拼接。这里用 int() 把文字翻译回整数,加号就恢复成数学加法了。注释里 f(f(g(x))) 表示“一层套一层”:最里面 g(x) 是 input 问用户,外面再套 int() 翻译。
逐行讲解(带注释版代码)
a = input("num: ") # num: is argument of input function # 问用户拿文字,存进 a;# 后面是注释:num: 是 input 的参数
b = input("num: ") # 再问一次拿文字,存进 b
a = int(a) # f(f(g(x))) # 用 int 把 a 的文字翻译成整数,放回 a;f(f(g(x))) 表示嵌套调用
b = int(b) # a, b argument # 把 b 也翻译成整数;a、b 是参数
c = a + b # 两个整数做数学加法
print(c) # 打印结果
a = input("num: ") # num: is argument of input function问用户拿文字,存进 a;# 后面是注释:num: 是 input 的参数
b = input("num: ")再问一次拿文字,存进 b
a = int(a) # f(f(g(x)))用 int 把 a 的文字翻译成整数,放回 a;f(f(g(x))) 表示嵌套调用
b = int(b) # a, b argument把 b 也翻译成整数;a、b 是参数
c = a + b两个整数做数学加法
print(c)打印结果
为什么输出是这个 输入 2 和 3,输出 5:因为 a、b 先被 int() 变成整数 2 和 3,加号做的是数学加法。
接下来 查查你的名字 arianna 是什么类型?文字都是同一个家族。
In [18] 复制
type("2"), type('2')
豆豆老师小课堂 同时给两个文字做类型体检。
▸
它是怎么实现的 type() 可以一次体检多个对象,中间用逗号隔开,结果放在括号里。
逐行讲解(带注释版代码)
type("2"), type('2') # 给文字 '2' 体检两次(双引号和单引号写法不同,意思一样)
type("2"), type('2')给文字 '2' 体检两次(双引号和单引号写法不同,意思一样)
为什么输出是这个 输出 (str, str):两个都是文字类型。双引号和单引号在 Python 里都能包文字。
接下来 再确认一次:不管双引号单引号,文字统统是 str 类型。
In [19] 复制
type("arianna"), type("arianna")
豆豆老师小课堂 给名字 'arianna' 做类型体检。
▸
它是怎么实现的 跟上个 cell 一样,体检对象换成了一串字母。
逐行讲解(带注释版代码)
type("arianna"), type("arianna") # 给 'arianna' 体检两次,验证它也是文字
type("arianna"), type("arianna")给 'arianna' 体检两次,验证它也是文字
为什么输出是这个 输出 (str, str):字母组成的一串也是文字类型。
接下来 组合拳:先 input 问用户,再用 int 把文字翻译成整数,一步到位。
In [20] 复制
a = int(input("num: ")) # num: is argument of input function
b = int(input("num: "))
c = a + b
print(c)
豆豆老师小课堂 把 input 直接包在 int() 里面:边问边翻译,一步到位。
▸
它是怎么实现的 int(input(...)) 是“嵌套调用”:先执行里面的 input() 问用户,拿到文字后立刻交给外面的 int() 翻译成整数。就像先伸手接住东西、马上递进翻译机。括号里喂给函数的材料叫“实参”(actual argument):input("num: ") 里的 "num: " 就是实参——它告诉机器“提问时屏幕上显示什么字”。
逐行讲解(带注释版代码)
a = int(input("num: ")) # num: is argument of input function # 先问用户拿文字,立刻翻译成整数,存进 a
b = int(input("num: ")) # 同样,问完立刻翻译,存进 b
c = a + b # 两个整数相加
print(c) # 打印结果
a = int(input("num: ")) # num: is argument of input function先问用户拿文字,立刻翻译成整数,存进 a
b = int(input("num: "))同样,问完立刻翻译,存进 b
c = a + b两个整数相加
print(c)打印结果
为什么输出是这个 输入 2 和 3,输出 5。和 cell 15 结果一样,但代码更短——因为翻译动作直接写进了 input 的外面。
接下来 再看一遍这个组合——input 和 int 是怎么手拉手配合的。
In [21] 复制
a = int(input("num: ")) # num: is argument of input function
b = int(input("num: "))
c = a + b
print(c)
ValueError: invalid literal for int() with base 10: '2.3'
---------------------------------------------------------------------------ValueError Traceback (most recent call last)Cell In[21], line 1
----> 1 a = int(input("num: ")) # num: is argument of input function
2 b = int(input("num: "))
4 c = a + b
ValueError: invalid literal for int() with base 10: '2.3'
豆豆老师小课堂 同样的代码,这次用户输入了 2.3,int() 翻译失败报错。
▸
它是怎么实现的 int 翻译机只收“整数文字”,2.3 带小数点,它不认。
逐行讲解(带注释版代码)
a = int(input("num: ")) # num: is argument of input function # 问用户,用户输入 2.3,int 拿到 '2.3'——不认,报错
a = int(input("num: ")) # num: is argument of input function问用户,用户输入 2.3,int 拿到 '2.3'——不认,报错
为什么输出是这个 报 ValueError:invalid literal for int() with base 10: '2.3'。意思是:'2.3' 不是 int 认得的整数文字。想收小数,应该用 float()。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. a = int(input())
用户输入 5,a 的类型是?
A strB intC floatD bool
input 给的是文字,但 int() 已经把它翻译掉了。
✓ 对!int() 把文字 '5' 变成数字 5。
float 是小数类型,int 是整数类型。
bool 是真假类型,和数字无关。
📖 完整思路:input 先拿到文字 '5',int() 立刻翻译成数字 5。
2. 不写 int(),直接 a = input(),用户输入 5,a 的类型是?
A strB intC floatD 报错
✓ 对!input 永远给文字(str),这是它的默认脾气。
不翻译不会自动变数字。
不会自动变小数。
input 正常执行,不会报错。
📖 完整思路:input 永远返回文字,哪怕输入的是数字。
接下来 先用 print 亮出一句提示,让用户知道要输入什么,下一步才问。
In [22] 复制
print("please input a number: ")
a = int(input("num: ")) # num: is argument of input function
b = int(input("num: "))
c = a + b
print(c)
ValueError: invalid literal for int() with base 10: '2.3'
---------------------------------------------------------------------------ValueError Traceback (most recent call last)Cell In[22], line 2
1 print("please input a number: ")
----> 2 a = int(input("num: ")) # num: is argument of input function
3 b = int(input("num: "))
5 c = a + b
ValueError: invalid literal for int() with base 10: '2.3'
豆豆老师小课堂 在输入前先打印一句提示语,然后 int() 依然因 2.3 报错。
▸
它是怎么实现的 print("please input a number: ") 先输出一句提示,让用户知道该输数字了。但后面的 int() 还是遇到 '2.3' 而失败。
逐行讲解(带注释版代码)
print("please input a number: ") # 先打印提示语,请用户输入数字
a = int(input("num: ")) # num: is argument of input function # 问用户,拿到 '2.3',int 不认
b = int(input("num: ")) # 这一行还没轮到执行,程序已经报错了
c = a + b # 没执行到
print(c) # 没执行到
print("please input a number: ")先打印提示语,请用户输入数字
a = int(input("num: ")) # num: is argument of input function问用户,拿到 '2.3',int 不认
b = int(input("num: "))这一行还没轮到执行,程序已经报错了
c = a + b没执行到
print(c)没执行到
为什么输出是这个 先打印了提示语,然后报 ValueError:int 不认识 '2.3'。报错后程序立刻停止,后面的行都不会执行。
🧱 新积木 7/10 输出语句 print statement把“值”显示到屏幕上
接下来 换个写法:print 提示和 input 读取分开做,看看顺序的重要性。
In [23] 复制
print("please input a number: ")
a = float(input("num: ")) # num: is argument of input function
b = float(input("num: "))
c = a + b
print(c)
豆豆老师小课堂 改用 float() 翻译,小数输入也能成功相加。
▸
它是怎么实现的 float 是“文字变小数”的翻译机,'2.3' 和 '2.333' 它都认识。
逐行讲解(带注释版代码)
print("please input a number: ") # 打印提示语
a = float(input("num: ")) # num: is argument of input function # 问用户,把 '2.3' 翻译成小数 2.3
b = float(input("num: ")) # 把 '2.333' 翻译成小数 2.333
c = a + b # 两个小数做数学加法
print(c) # 打印结果
print("please input a number: ")打印提示语
a = float(input("num: ")) # num: is argument of input function问用户,把 '2.3' 翻译成小数 2.3
b = float(input("num: "))把 '2.333' 翻译成小数 2.333
c = a + b两个小数做数学加法
print(c)打印结果
为什么输出是这个 输入 2.3 和 2.333,输出 4.633:2.3 + 2.333 = 4.633。用 float 就能处理带小数点的输入了。
🧰 积木收藏盒 · 学到这里,你已经点亮 7 块积木
值 value表达式 expression变量 variable运算符+操作数 operator + operand输入语句 input函数调用 function call输出语句 print
新学的积木会自动掉进盒子,继续往下学吧!
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 '2' + 3 为什么报错?
加号两边“性格不合”:左边 '2' 是文字(str),右边 3 是数字(int)。Python 说:文字只能跟文字拼接。想让它们相加,得先 int('2') 把文字翻译成数字。
📌 来自课堂:学生混淆了文字拼接和数字相加
💬 value 到底是什么?
value(值 /ˈvæljuː/)就是“一个具体的数或文字”,比如 3、'a'、2.5。表达式算完会得到一个 value,变量存的也是 value。
📌 基础概念
💬 expression、operator、operand 怎么记?
expression 表达式 /ɪkˈspreʃn/:一段会算出答案的代码;operator 运算符 /ˈɒpəreɪtə/:干活的符号(+ - *);operand 操作数 /ˈɒpərænd/:被运算的数。2 + 3 里,+ 是 operator,2 和 3 是 operand。
📌 课堂术语
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. 表达式 2 + 3 的结果是什么?
A '23'B 5C 23D 报错
'23' 是文字拼接的结果,但 2 和 3 都是数字,走的是数学加法。
✓ 对!数字 + 数字 = 数学加法,2 + 3 = 5。
23 是“2 和 3 连起来写”,Python 不会这么处理数字相加。
数字和数字相加完全合法,不会报错。
📖 完整思路:两个数字相加,Python 按数学规则算,结果是 5。
2. 2 + 3 里,哪个是运算符(operator)?
A 2B +C 3D 2 + 3 整体
2 是被运算的操作数,不是运算符。
✓ 对!+ 是运算符,它指挥 2 和 3 相加。
3 也是操作数,不是符号。
整段是表达式,不是一个符号。
📖 完整思路:干活的符号 + 是运算符;被运算的 2 和 3 是操作数(operand)。
3. 值(value)可能是以下哪种?
A 只能是一个数字B 一个数字或一段文字C 只能是一段文字D 只能是 True
数字是 value,但文字(如 'a')也是 value。
✓ 对!数字和文字都是 value,表达式的计算结果就是 value。
文字是 value,但数字(如 3)也是。
True 只是 value 的一种,数字和文字也算。
📖 完整思路:value 就是具体的数或文字,3、'a'、2.5 都是 value。
02
算术与字符串运算 接下来 数字乘法:2 × 4。数字之间的 * 就是数学里的乘号。
In [24] 复制
2 * 4
豆豆老师小课堂 数字乘法:2 × 4。
▸
它是怎么实现的 两个都是数字,* 就是数学里的乘号。
逐行讲解(带注释版代码)
2 * 4 # 2 乘 4
接下来 文字 × 4:'2' 会复制 4 遍变成 '2222'——先猜再看输出。
In [25] 复制
'2' * 4
豆豆老师小课堂 文字 '2' 乘 4。
▸
它是怎么实现的 文字乘数字的意思是“把这段文字重复写 N 遍”——乘号对文字来说不是乘法,是一台复印机。
逐行讲解(带注释版代码)
'2' * 4 # 把文字 '2' 复印 4 遍
为什么输出是这个 输出 '2222':'2' 写了 4 遍。
豆豆提醒 别搞混:数字 * 数字是数学乘法(2 * 4 = 8),文字 * 数字是复印机('2' * 4 = '2222')。看乘号两边有没有引号就知道。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. 下面代码会输出什么?
print('2' * 4)
A 8B '2222'C 2222D 报错
8 是数字乘法 2×4 的结果,但 '2' 是文字。
✓ 对!文字 × 数字 = 复制拼接,'2' 出现 4 次。
2222 不带引号,Python 输出文字时会带引号。
文字 × 数字完全合法,不会报错。
📖 完整思路:文字 × 数字 = 复制:'2' 复制 4 遍 = '2222'。
2. 下面代码会输出什么?
print('ab' * 3)
A 'ababab'B 'ab3'C 'aaabbb'D 报错
✓ 对!'ab' 整段复制 3 遍 = 'ababab'。
'ab3' 是把 3 当成字符拼上去,乘法不会这样。
'aaabbb' 是每个字符分开复制,乘法是整段复制。
文字 × 数字合法,不会报错。
📖 完整思路:整段 'ab' 复制 3 遍:ab ab ab,拼起来是 'ababab'。
接下来 任务:让用户输入宽和高,算出长方形面积。先自己打草稿,再往下看。
In [29] 复制
# ask user input a number with prompt width:
# input function return the str (string) value user input
# use float function convert the string user input to float number type
# for arithmetic operation and then
# assign the retrun value of float to variable width
# because input and float both return value or tell us a result
# just like expression will be evaluated to specific value
# so also called function call expression
width = float(input("width: ")) # num: is argument of input function
height = float(input("height: "))
area = width * height
print(area)
# basic concept
豆豆老师小课堂 完整的小程序:输入长方形的宽和高,算出并打印面积。
▸
先想一想(任务说明) 任务:让用户输入长方形的宽和高,电脑算出面积并打印。先别急着看代码,自己想一想:要分几步?要“问”用户几次?拿到的东西是文字还是数字?能不能直接相乘?想清楚再往下看——这就是写代码前先打草稿。
它是怎么实现的 思路:input 问宽和高 → float 把文字变成小数 → 面积 = 宽 × 高 → print 打印。注释里还讲了两个概念:input/float 都会“返回一个结果”,所以它们组成的式子叫“函数调用表达式”。
逐行讲解(带注释版代码)
# ask user input a number with prompt width:
# input function return the str (string) value user input
# use float function convert the string user input to float number type
# for arithmetic operation and then
# assign the retrun value of float to variable width
# because input and float both return value or tell us a result
# just like expression will be evaluated to specific value
# so also called function call expression
width = float(input("width: ")) # num: is argument of input function # 问宽,翻译成小数,存进 width
height = float(input("height: ")) # 问高,翻译成小数,存进 height
area = width * height # 面积 = 宽 × 高
print(area) # 打印面积
# basic concept
# ask user input a number with prompt width:注释:用 input 问用户宽,括号里的提示词叫 prompt
# input function return the str (string) value user input注释:input 返回的是用户输入的字符串(文字)
# use float function convert the string user input to float number type注释:用 float 把文字翻译成小数
# for arithmetic operation and then注释:这样才能做数学运算
# assign the retrun value of float to variable width注释:把 float 翻译好的数存进变量 width
# because input and float both return value or tell us a result注释:input 和 float 都会返回一个值
# just like expression will be evaluated to specific value注释:就像表达式会被算成一个具体的值
# so also called function call expression注释:所以这叫“函数调用表达式”
width = float(input("width: ")) # num: is argument of input function问宽,翻译成小数,存进 width
height = float(input("height: "))问高,翻译成小数,存进 height
area = width * height面积 = 宽 × 高
print(area)打印面积
# basic concept注释:这些都是基础概念
为什么输出是这个 输入宽 2、高 3,输出 6.0:2.0 × 3.0 = 6.0。因为 float 翻译后是小数,所以结果带着 .0。
接下来 BMI 大任务的开场白——先看看我们接下来要解决什么问题。
In [30] 复制
# bmi
# ask user input weigth and height
# bmi is body mass index
# weight divide (power of height)
# weight in kg
# height in m
豆豆老师小课堂 BMI 小程序的“设计图”:先想清楚要输入体重(千克)和身高(米),BMI = 体重 ÷ 身高²。
▸
它是怎么实现的 这节全是注释,是写代码前的思路整理——先计划,再动手。
逐行讲解(带注释版代码)
# bmi
# ask user input weigth and height
# bmi is body mass index
# weight divide (power of height)
# weight in kg
# height in m
# bmi注释:这是 BMI(身体质量指数)程序
# ask user input weigth and height注释:让用户输入体重和身高
# bmi is body mass index注释:BMI 是身体质量指数
# weight divide (power of height)注释:公式是体重除以身高的平方
# weight in kg注释:体重单位是千克 kg
# height in m注释:身高单位是米 m
接下来 把体重输入翻译成小数,存进变量 w,准备算 BMI。
In [33] 复制
w = float(input())
h = float(input())
bmi = w / (h ** 2)
print('bmi is: ' + bmi)
TypeError: can only concatenate str (not "float") to str
---------------------------------------------------------------------------TypeError Traceback (most recent call last)Cell In[33], line 6
2 h = float(input())
4 bmi = w / (h ** 2)
----> 6 print('bmi is: ' + bmi)
TypeError: can only concatenate str (not "float") to str
豆豆老师小课堂 算 BMI,但打印时直接把文字和数字相加——报错。
▸
它是怎么实现的 print('bmi is: ' + bmi) 想拼接文字和数字 bmi,可加号只能拼接文字和文字。
逐行讲解(带注释版代码)
w = float(input()) # 输入体重(文字)翻译成小数,存进 w
h = float(input()) # 输入身高翻译成小数,存进 h
bmi = w / (h ** 2) # 算 BMI:w 除以 h 的平方(** 是“几次方”)
print('bmi is: ' + bmi) # 想把文字和数字拼在一起打印——类型不同,报错
w = float(input())输入体重(文字)翻译成小数,存进 w
h = float(input())输入身高翻译成小数,存进 h
bmi = w / (h ** 2)算 BMI:w 除以 h 的平方(** 是“几次方”)
print('bmi is: ' + bmi)想把文字和数字拼在一起打印——类型不同,报错
为什么输出是这个 报 TypeError:文字只能拼接文字,不能拼接小数(float)。数字要先变成文字才能拼,见下一个 cell。
接下来 再写一遍——这次故意输入一个非数字,看看程序怎么应对。
In [35] 复制
w = float(input())
h = float(input())
bmi = w / (h ** 2)
print('bmi is: ' + str(bmi))
bmi is: 0.0022408178985329646
豆豆老师小课堂 用 str() 把 BMI 数字变成文字,再拼接打印。
▸
它是怎么实现的 str() 是“数字变文字”的翻译机。先把 bmi 翻译成文字,再用 + 拼接,就成功了。
逐行讲解(带注释版代码)
w = float(input()) # 输入体重,翻译成小数
h = float(input()) # 输入身高,翻译成小数
bmi = w / (h ** 2) # BMI = 体重 ÷ 身高²
print('bmi is: ' + str(bmi)) # 把 bmi 先变成文字,再和 'bmi is: ' 拼接打印
w = float(input())输入体重,翻译成小数
h = float(input())输入身高,翻译成小数
bmi = w / (h ** 2)BMI = 体重 ÷ 身高²
print('bmi is: ' + str(bmi))把 bmi 先变成文字,再和 'bmi is: ' 拼接打印
为什么输出是这个 输入 64 和 169,输出 bmi is: 0.0022408178985329646。这里身高输成了 169(米就太大了),64 ÷ 169² ≈ 0.00224,数很小——这是个“错误输入”的示范。
豆豆提醒 身高应该用米(比如 1.69),输成 169 会得到离谱的结果。
接下来 第三遍:试试输入超大体重,程序会不会自己拦住它?
In [37] 复制
w = float(input())
h = float(input("height(m)"))
bmi = w / (h ** 2)
print('bmi is: ' + str(bmi))
bmi is: 22.40817898532965
豆豆老师小课堂 这次身高提示写成 height(m),输入 1.69 米,BMI 就正常了。
▸
它是怎么实现的 和上个 cell 几乎一样,只是 input 里加了提示词 height(m),提醒用户输米。
逐行讲解(带注释版代码)
w = float(input()) # 输入体重 64,翻译成小数
h = float(input("height(m)")) # 输入身高(提示用米)1.69,翻译成小数
bmi = w / (h ** 2) # BMI = 64 ÷ 1.69²
print('bmi is: ' + str(bmi)) # 把结果变成文字后拼接打印
w = float(input())输入体重 64,翻译成小数
h = float(input("height(m)"))输入身高(提示用米)1.69,翻译成小数
bmi = w / (h ** 2)BMI = 64 ÷ 1.69²
print('bmi is: ' + str(bmi))把结果变成文字后拼接打印
为什么输出是这个 输出 bmi is: 22.40817898532965:64 ÷ 1.69² ≈ 22.41,是正常的 BMI 数值。
接下来 发现问题了:身高输了错的值,程序直接往下跑——它需要一个“守卫”。
In [38] 复制
# if user input invalid height
# prompot user you input invalid or error value
# just once
豆豆老师小课堂 思考题:如果用户输入了不合理的身高(比如 22 米),怎么提醒他一次?
▸
它是怎么实现的 注释里在规划:当输入的身高不合法时,提示用户“你输错了”。但“只提示一次”的办法不够好,因为用户可能一直输错。
逐行讲解(带注释版代码)
# if user input invalid height
# prompot user you input invalid or error value
# just once
# if user input invalid height注释:如果用户输入了无效的身高
# prompot user you input invalid or error value注释:提示用户:你输入了无效/错误的值
# just once注释:只提示一次
为什么输出是这个 没有代码,没有输出。接下来几个 cell 会一步步实现这个想法。
🧱 新积木 8/10 条件语句 if statement电脑按条件选一条路走,比如“身高不合法就提示错误”
接下来 同样是非法输入——想一想:程序该怎么拦住这种捣乱?
In [39] 复制
# if user input invalid value
# ask user input value until user input valid value
豆豆老师小课堂 更好的思路:只要输入不合法,就一直重新问,直到用户输入合法为止。
▸
它是怎么实现的 这就是“循环”的雏形:不合法就再问、再问、再问。后面会用 while 实现。
逐行讲解(带注释版代码)
# if user input invalid value
# ask user input value until user input valid value
# if user input invalid value注释:如果用户输入了无效的值
# ask user input value until user input valid value注释:就一直问,直到用户输入有效的值
接下来 给体重加上 while 守卫:不合法就重新问,直到输入正确为止。
In [40] 复制
w = float(input())
h = float(input("height(m)"))
bmi = w / (h ** 2)
print('bmi is: ' + str(bmi))
bmi is: 0.2222222222222222
豆豆老师小课堂 回到 BMI 计算:输入体重 2、身高 3,算出 BMI。
▸
它是怎么实现的 代码和 cell 28 一样,输入不同,结果不同。
逐行讲解(带注释版代码)
w = float(input()) # 输入体重 2
h = float(input("height(m)")) # 输入身高 3(不合理,但程序还没做检查)
bmi = w / (h ** 2) # BMI = 2 ÷ 9
print('bmi is: ' + str(bmi)) # 拼接打印
w = float(input())输入体重 2
h = float(input("height(m)"))输入身高 3(不合理,但程序还没做检查)
bmi = w / (h ** 2)BMI = 2 ÷ 9
print('bmi is: ' + str(bmi))拼接打印
为什么输出是这个 输出 bmi is: 0.2222222222222222:2 ÷ 3² = 2 ÷ 9 ≈ 0.222。数值离谱,说明需要加“身高合法性检查”。
🧰 积木收藏盒 · 学到这里,你已经点亮 8 块积木
值 value表达式 expression变量 variable运算符+操作数 operator + operand输入语句 input函数调用 function call输出语句 print条件语句 if
新学的积木会自动掉进盒子,继续往下学吧!
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 '2' * 4 为什么是 2222 而不是 8?
因为 '2' 是文字不是数字。文字 × 数字 = “把这个文字复制几遍”,所以 '2' × 4 = '2222'。这就像复印机:复印 4 次,出来的还是那行字,只是多了几份。
📌 来自课堂:复印机比喻
💬 2 * 4 和 '2' * 4 到底差在哪?
差在类型。数字 × 数字 = 数学乘法(8);文字 × 数字 = 复制拼接('2222')。类型决定运算符的“性格”,这就是为什么 Python 那么看重类型。
📌 课堂重点
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. '2' * 4 的输出是?
A 8B 2222C 24D 报错
8 是数字乘法 2 × 4 的结果,但这里是带引号的文字 '2'。
✓ 对!文字 × 数字 = 复制:'2' 复制 4 遍得到 '2222'。
24 是“2 和 4 拼一起”,乘法不会这么算。
文字 × 数字是合法的(复制拼接),不会报错。
📖 完整思路:文字 × 数字 = 复制拼接:'2' 复制 4 遍 = '2222'。
2. 2 + '2' 会怎样?
A 输出 4B 输出 '22'C 报错(TypeError)D 输出 22
数字 + 文字不能按数学算,Python 不会算出 4。
'22' 是文字拼接,但左边 2 是数字,不是文字。
✓ 对!数字和文字类型不匹配,Python 报 TypeError。
22 是拼接写法,但 2(数字)和 '2'(文字)不能直接拼。
📖 完整思路:数字加文字类型不匹配,Python 报 TypeError:不能把 str 和 int 相加。
3. 123 + 4 和 '123' + '4' 的结果分别是?
A 127 和 '1234'B 1234 和 127C 都报错D '1234' 和 127
✓ 对!数字走算术 127,文字走拼接 '1234'。
反了:数字相加是 127,文字相加是 '1234'。
两组都类型一致,完全合法,不会报错。
顺序反了:数字相加得 127,不是 '1234'。
📖 完整思路:数字相加是算术(127);文字相加是拼接('1234')。类型决定 + 的性格。
03
BMI 与条件判断 接下来 if 条件入门:num 等于 2 时做什么?条件判断让程序会“选择”。
In [ ] 复制
num = 2
if num % 2 == 0:
print('even')
else:
print('odd')
豆豆老师小课堂 判断一个数是偶数还是奇数:num = 2,检查 num % 2 是否为 0。
▸
它是怎么实现的 % 叫“取余”,就是算除法后剩多少。偶数 ÷ 2 一定余 0。if/else 是“岔路口”:条件成立走 if,不成立走 else。
逐行讲解(带注释版代码)
num = 2 # 把 2 放进盒子 num
if num % 2 == 0: # 如果 num 除以 2 的余数等于 0(== 是“等于”的意思)
print('even') # 就打印 even(偶数)——注意前面要缩进
else: # 否则(余数不是 0)
print('odd') # 打印 odd(奇数)
num = 2把 2 放进盒子 num
if num % 2 == 0:如果 num 除以 2 的余数等于 0(== 是“等于”的意思)
print('even')就打印 even(偶数)——注意前面要缩进
else:否则(余数不是 0)
print('odd')打印 odd(奇数)
为什么输出是这个 输出 even:2 % 2 = 0,条件成立,走 if 分支。
豆豆提醒 == 才是“判断相等”,单个 = 是“放东西进盒子”,别搞混。
接下来 给 BMI 加第一道判断——体重在不在合理范围?
In [42] 复制
weight = float(input())
height = float(input("height(m)"))
if height >= 2.5:
print('the height is invalid')
else:
bmi = weight / (height * height)
print('bmi is: ' + str(bmi))
bmi is: 21.007667798746546
豆豆老师小课堂 给 BMI 程序加上身高检查:身高 ≥ 2.5 米就提示无效,否则算 BMI。
▸
它是怎么实现的 if height >= 2.5 是守卫:先检查身高合不合理,不合理就提示,合理才计算。else 里才是真正的计算。
逐行讲解(带注释版代码)
weight = float(input()) # 输入体重 60
height = float(input("height(m)")) # 输入身高 1.69
if height >= 2.5: # 如果身高 ≥ 2.5 米(太夸张了)
print('the height is invalid') # 提示:这个身高无效
else: # 否则(身高合理)
bmi = weight / (height * height) # 算 BMI:体重 ÷ 身高²(这里用乘法写平方)
print('bmi is: ' + str(bmi)) # 打印 BMI
weight = float(input())输入体重 60
height = float(input("height(m)"))输入身高 1.69
if height >= 2.5:如果身高 ≥ 2.5 米(太夸张了)
print('the height is invalid')提示:这个身高无效
else:否则(身高合理)
bmi = weight / (height * height)算 BMI:体重 ÷ 身高²(这里用乘法写平方)
print('bmi is: ' + str(bmi))打印 BMI
为什么输出是这个 输出 bmi is: 21.007667798746546:60 ÷ 1.69² ≈ 21.01。身高合理,正常计算。
接下来 再补一层判断:这次拦身高,不合法就重来。
In [43] 复制
weight = float(input())
height = float(input("height(m)"))
if height >= 2.5:
print('the height is invalid')
else:
bmi = weight / (height * height)
print('bmi is: ' + str(bmi))
豆豆老师小课堂 同样的代码,这次输入身高 22,触发了“无效”提示。
▸
它是怎么实现的 身高 22 米超过 2.5,if 条件成立,走提示分支,不计算 BMI。
逐行讲解(带注释版代码)
weight = float(input()) # 输入体重 2
height = float(input("height(m)")) # 输入身高 22——太夸张了
if height >= 2.5: # 22 ≥ 2.5,条件成立
print('the height is invalid') # 打印:这个身高无效
weight = float(input())输入体重 2
height = float(input("height(m)"))输入身高 22——太夸张了
if height >= 2.5:22 ≥ 2.5,条件成立
print('the height is invalid')打印:这个身高无效
为什么输出是这个 输出 the height is invalid:身高检查起作用了,拦住不合理的数据。
接下来 判断加守卫:输入合法才继续,程序开始“有原则”了。
In [44] 复制
weight = float(input())
height = float(input("height(m)"))
while weight > 2.5:
height = float(input("please input a valid height(m) < 2.5: "))
print(height)
60
height(m) 22
please input a valid height(m) < 2.5: 33
please input a valid height(m) < 2.5: 22
please input a valid height(m) < 2.5: -2
KeyboardInterrupt: Interrupted by user
---------------------------------------------------------------------------KeyboardInterrupt Traceback (most recent call last)Cell In[44], line 5
2 height = float(input("height(m)"))
4 while weight > 2.5:
----> 5 height = float(input("please input a valid height(m) < 2.5: "))
7 print(height)
File /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/ipykernel/kernelbase.py:1282, in Kernel.raw_input(self, prompt)
1280 msg = "raw_input was called, but this frontend does not support input requests."
1281 raise StdinNotImplementedError(msg)
-> 1282 return self._input_request(
1283 str(prompt),
1284 self._parent_ident["shell"],
1285 self.get_parent("shell"),
1286 password=False,
1287 )
File /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/ipykernel/kernelbase.py:1325, in Kernel._input_request(self, prompt, ident, parent, password)
1322 except KeyboardInterrupt:
1323 # re-raise KeyboardInterrupt, to truncate traceback
1324 msg = "Interrupted by user"
-> 1325 raise KeyboardInterrupt(msg) from None
1326 except Exception:
1327 self.log.warning("Invalid Message:", exc_info=True)
KeyboardInterrupt: Interrupted by user
豆豆老师小课堂 想用 while 循环让用户重新输入身高,但条件写错了(用 weight 判断),变成死循环。
▸
它是怎么实现的 while 的意思是“只要条件成立,就一直重复做下面的事”。这行写的是 while weight > 2.5,检查的是体重而不是身高,而且循环里改的是 height——体重一直没变,条件永远成立,就永远循环下去。
逐行讲解(带注释版代码)
weight = float(input()) # 输入体重 60
height = float(input("height(m)")) # 输入身高 22
while weight > 2.5: # 只要体重 > 2.5 就一直循环——写错了!应该判断 height
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入身高,但体重没变
print(height) # 循环结束后打印身高——永远等不到
weight = float(input())输入体重 60
height = float(input("height(m)"))输入身高 22
while weight > 2.5:只要体重 > 2.5 就一直循环——写错了!应该判断 height
height = float(input("please input a valid height(m) < 2.5: "))重新输入身高,但体重没变
print(height)循环结束后打印身高——永远等不到
为什么输出是这个 用户输入几次后一直循环,最后按了 Ctrl+C,报 KeyboardInterrupt。教训:循环条件要检查“正在改的那个变量”。
接下来 继续打磨 BMI:把错误输入统统挡在门外。
In [46] 复制
weight = float(input())
height = float(input("height(m)"))
while height > 2.5:
height = float(input("please input a valid height(m) < 2.5: "))
print(height)
64
height(m) 22
please input a valid height(m) < 2.5: 33
please input a valid height(m) < 2.5: -2
豆豆老师小课堂 把条件改成判断 height,但只挡住了“太高”,没挡住“负数”。
▸
它是怎么实现的 while height > 2.5 只检查大于 2.5,用户输 -2 时条件不成立,循环结束,把 -2 当成合法身高。
逐行讲解(带注释版代码)
weight = float(input()) # 输入体重 64
height = float(input("height(m)")) # 输入身高 22
while height > 2.5: # 只要身高 > 2.5 就一直问
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入身高
print(height) # 循环结束后打印身高
weight = float(input())输入体重 64
height = float(input("height(m)"))输入身高 22
while height > 2.5:只要身高 > 2.5 就一直问
height = float(input("please input a valid height(m) < 2.5: "))重新输入身高
print(height)循环结束后打印身高
为什么输出是这个 输入 -2 时,-2 不大于 2.5,循环结束,输出 -2.0。问题:负数身高也被放过了。
接下来 换个角度写:哪个条件先查、哪个后查,顺序有讲究。
In [47] 复制
weight = float(input())
height = float(input("height(m)"))
# loop repeat, condition loop
while height > 2.5 or height <= 0: # guard
height = float(input("please input a valid height(m) < 2.5: "))
print(height)
60
height(m) 22
please input a valid height(m) < 2.5: -2
please input a valid height(m) < 2.5: 1.69
豆豆老师小课堂 用“或”把两个条件合起来:太高(>2.5)或太矮/负数(≤0)都重新问。
▸
它是怎么实现的 or 表示“只要有一个成立就走循环”。height > 2.5 or height <= 0 把上下两个边界都挡住了,这叫“守卫条件”(guard)。
逐行讲解(带注释版代码)
weight = float(input()) # 输入体重 60
height = float(input("height(m)")) # 输入身高 22
# loop repeat, condition loop
while height > 2.5 or height <= 0: # guard # 只要太高或太矮(≤0),就重新问;# guard 表示这是守卫
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入身高
print(height) # 打印最终合格的身高
weight = float(input())输入体重 60
height = float(input("height(m)"))输入身高 22
# loop repeat, condition loop注释:循环重复执行,条件循环
while height > 2.5 or height <= 0: # guard只要太高或太矮(≤0),就重新问;# guard 表示这是守卫
height = float(input("please input a valid height(m) < 2.5: "))重新输入身高
print(height)打印最终合格的身高
为什么输出是这个 输入 22 → 重新问 → -2 → 重新问 → 1.69 → 结束,输出 1.69。两个边界都被守住了。
接下来 BMI 守卫升级:体重范围改成 0 到 500,试试边界值。
In [49] 复制
weight = float(input())
height = float(input("height(m)"))
while weight <= 0 or weight > 500:
weight = float(input("valid weight: "))
# loop repeat, condition loop
while height > 2.5 or height <= 0: # guard
height = float(input("please input a valid height(m) < 2.5: "))
print(height)
bmi = weight / (height * height)
print('bmi is: ' + str(bmi))
KeyboardInterrupt: Interrupted by user
---------------------------------------------------------------------------KeyboardInterrupt Traceback (most recent call last)Cell In[49], line 2
1 weight = float(input())
----> 2 height = float(input("height(m)"))
4 while weight <= 0 or weight > 500:
5 weight = float(input("valid weight: "))
File /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/ipykernel/kernelbase.py:1282, in Kernel.raw_input(self, prompt)
1280 msg = "raw_input was called, but this frontend does not support input requests."
1281 raise StdinNotImplementedError(msg)
-> 1282 return self._input_request(
1283 str(prompt),
1284 self._parent_ident["shell"],
1285 self.get_parent("shell"),
1286 password=False,
1287 )
File /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/ipykernel/kernelbase.py:1325, in Kernel._input_request(self, prompt, ident, parent, password)
1322 except KeyboardInterrupt:
1323 # re-raise KeyboardInterrupt, to truncate traceback
1324 msg = "Interrupted by user"
-> 1325 raise KeyboardInterrupt(msg) from None
1326 except Exception:
1327 self.log.warning("Invalid Message:", exc_info=True)
KeyboardInterrupt: Interrupted by user
豆豆老师小课堂 给体重也加上守卫:体重 ≤ 0 或 > 500 都重新问。
▸
它是怎么实现的 第一个 while 守体重(<= 0 或 > 500),第二个 while 守身高。但注意:第一个循环里如果一直输入无效体重,会一直循环。
逐行讲解(带注释版代码)
weight = float(input()) # 输入体重 -2
height = float(input("height(m)")) # 先输入身高 22(其实顺序有点乱)
while weight <= 0 or weight > 500: # 只要体重 ≤ 0 或 > 500,就重新问体重
weight = float(input("valid weight: ")) # 重新输入体重
# loop repeat, condition loop
while height > 2.5 or height <= 0: # guard # 身高守卫循环
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入身高
print(height) # 打印身高
bmi = weight / (height * height) # 算 BMI
print('bmi is: ' + str(bmi)) # 打印 BMI
weight = float(input())输入体重 -2
height = float(input("height(m)"))先输入身高 22(其实顺序有点乱)
while weight <= 0 or weight > 500:只要体重 ≤ 0 或 > 500,就重新问体重
weight = float(input("valid weight: "))重新输入体重
# loop repeat, condition loop注释
while height > 2.5 or height <= 0: # guard身高守卫循环
height = float(input("please input a valid height(m) < 2.5: "))重新输入身高
print(height)打印身高
bmi = weight / (height * height)算 BMI
print('bmi is: ' + str(bmi))打印 BMI
为什么输出是这个 体重 -2 不合法,程序一直问体重,用户按了中断,报 KeyboardInterrupt。这个 cell 故意演示了“先输入了身高,但体重还没合法”的混乱顺序。
接下来 最后一版守卫:看看程序遇到各种怪输入还稳不稳。
In [51] 复制
weight = float(input())
while weight <= 0 or weight > 500:
weight = float(input("valid weight: "))
height = float(input("height(m)"))
# loop repeat, condition loop
while height > 2.5 or height <= 0: # guard
height = float(input("please input a valid height(m) < 2.5: "))
bmi = weight / (height * height)
print('bmi is: ' + str(bmi))
-2
valid weight: 1000
valid weight: 2000
valid weight: 200
height(m) -2
please input a valid height(m) < 2.5: 1111
please input a valid height(m) < 2.5: 1.69
1.69
bmi is: 70.02555932915514
豆豆老师小课堂 整理顺序:先让体重合法,再问身高,最后算 BMI。完整的双守卫程序。
▸
它是怎么实现的 流程:体重循环守卫 → 身高循环守卫 → 计算。每一步都等上一步通过。
逐行讲解(带注释版代码)
weight = float(input()) # 输入体重 -2
while weight <= 0 or weight > 500: # 体重不合法就循环
weight = float(input("valid weight: ")) # 重新输入:1000 → 2000 → 200(终于合法)
height = float(input("height(m)")) # 体重合法后才问身高
# loop repeat, condition loop
while height > 2.5 or height <= 0: # guard # 身高守卫
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入:-2 → 1111 → 1.69(合法)
bmi = weight / (height * height) # BMI = 200 ÷ 1.69²
print('bmi is: ' + str(bmi)) # 打印 BMI
weight = float(input())输入体重 -2
while weight <= 0 or weight > 500:体重不合法就循环
weight = float(input("valid weight: "))重新输入:1000 → 2000 → 200(终于合法)
height = float(input("height(m)"))体重合法后才问身高
# loop repeat, condition loop注释
while height > 2.5 or height <= 0: # guard身高守卫
height = float(input("please input a valid height(m) < 2.5: "))重新输入:-2 → 1111 → 1.69(合法)
bmi = weight / (height * height)BMI = 200 ÷ 1.69²
print('bmi is: ' + str(bmi))打印 BMI
为什么输出是这个 输出 bmi is: 70.02555932915514:体重 200、身高 1.69,200 ÷ 1.69² ≈ 70.03。两个守卫都正常工作。
接下来 身高也要守卫:0 到 2.5 之间才算合法,超出就重新问。
In [53] 复制
height = float(input("height(m)"))
while height <= 0 or height > 2.5:
if height > 30: # how to construct condition
ans = input("do you mean centimeter?[yes/no] ")
if ans == 'yes':
height = height / 100 # convert cm to m
break
else:
height = float(input("please input a valid height(m) < 2.5: "))
else:
height = float(input("please input a valid height(m) < 2.5: "))
print(height)
height(m) 170
do you mean centimeter?[yes/no] yes
豆豆老师小课堂 聪明一点的守卫:如果身高 > 30,猜测用户可能输的是“厘米”,问是否要换算成米。
▸
它是怎么实现的 在 while 里加 if:> 30 时先问“你输的是厘米吗?”如果答 yes,就把 height 除以 100 变成米,并用 break 跳出循环;答 no 就重新输入。这是 if 套在 while 里的“嵌套结构”。while 这种用法叫 guard(守卫循环):只要不符合条件,就让用户重复输入,直到满足条件为止——就像考托福,考不到 100 分就继续考。
逐行讲解(带注释版代码)
height = float(input("height(m)")) # 输入 170
while height <= 0 or height > 2.5: # 170 不合法,进入循环
if height > 30: # how to construct condition # 如果身高 > 30,可能是厘米
ans = input("do you mean centimeter?[yes/no] ") # 问:你输的是厘米吗?
if ans == 'yes': # 如果回答 yes
height = height / 100 # convert cm to m # 除以 100 换算成米:170 ÷ 100 = 1.7
break # break:立刻跳出整个 while 循环
else: # 如果回答 no
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入
else: # 如果身高 ≤ 30(但不合法)
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入
print(height) # 打印最终身高
height = float(input("height(m)"))输入 170
while height <= 0 or height > 2.5:170 不合法,进入循环
if height > 30: # how to construct condition如果身高 > 30,可能是厘米
ans = input("do you mean centimeter?[yes/no] ")问:你输的是厘米吗?
if ans == 'yes':如果回答 yes
height = height / 100 # convert cm to m除以 100 换算成米:170 ÷ 100 = 1.7
breakbreak:立刻跳出整个 while 循环
else:如果回答 no
height = float(input("please input a valid height(m) < 2.5: "))重新输入
else:如果身高 ≤ 30(但不合法)
height = float(input("please input a valid height(m) < 2.5: "))重新输入
print(height)打印最终身高
为什么输出是这个 输入 170,答 yes,输出 1.7:170 厘米 ÷ 100 = 1.7 米。break 让循环立刻结束。
接下来 身高守卫再确认:输入 1.7 放行,输入 3 或 -5 会怎样?
In [54] 复制
height = float(input("height(m)"))
while height <= 0 or height > 2.5:
if height > 30: # how to construct condition
ans = input("do you mean centimeter?[yes/no] ")
if ans == 'yes':
height = height / 100 # convert cm to m
break
else:
height = float(input("please input a valid height(m) < 2.5: "))
else:
height = float(input("please input a valid height(m) < 2.5: "))
print(height)
height(m) 170
do you mean centimeter?[yes/no] no
please input a valid height(m) < 2.5: 20
please input a valid height(m) < 2.5: 1.69
豆豆老师小课堂 同样的程序,这次答 no——170 不是厘米,那就重新输入。
▸
它是怎么实现的 流程和 cell 40 一样,只是用户选择不同,走的分支不同。
逐行讲解(带注释版代码)
height = float(input("height(m)")) # 输入 170
while height <= 0 or height > 2.5: # 进入循环
if height > 30: # 170 > 30,猜是厘米
ans = input("do you mean centimeter?[yes/no] ") # 问是否厘米
if ans == 'yes': # 答 no,不成立
height = height / 100 # 没执行
break # 没执行
else: # 走 else 分支
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入:20
else: # 20 还是 > 2.5,但 ≤ 30,走这个 else
height = float(input("please input a valid height(m) < 2.5: ")) # 重新输入:1.69
print(height) # 输出 1.69
height = float(input("height(m)"))输入 170
while height <= 0 or height > 2.5:进入循环
if height > 30:170 > 30,猜是厘米
ans = input("do you mean centimeter?[yes/no] ")问是否厘米
if ans == 'yes':答 no,不成立
height = height / 100没执行
break没执行
else:走 else 分支
height = float(input("please input a valid height(m) < 2.5: "))重新输入:20
else:20 还是 > 2.5,但 ≤ 30,走这个 else
height = float(input("please input a valid height(m) < 2.5: "))重新输入:1.69
print(height)输出 1.69
为什么输出是这个 输出 1.69:答 no 后重新输入 20(仍不合法)再输入 1.69(合法),循环结束。
豆豆提醒 答 no 就回到循环开头重新输入,直到合格为止——这就是 guard 循环的威力:不满足条件,就绝不放过你。
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 height = height / 100 有必要吗?
有!用户可能把身高输成厘米(170),可程序要的是米(1.7)。这一句就是“单位换算翻译机”:把 170 厘米 ÷ 100 变成 1.7 米,再存回 height。学生问过这个问题,郎老师现场演示了不换算会算出什么离谱的 BMI。
📌 来自课堂:学生真实提问
💬 input 返回的到底是什么类型?
永远是文字(str)!哪怕你输入的是 60,拿到手也是 '60'。所以要用 int(input()) 或 float(input()) 把它“翻译”成数字,才能做算术。
📌 课堂反复强调
💬 while 当守卫是怎么工作的?
while 条件成立就一直循环。当“体重不在 0~500”时一直重新问,直到输入合法才放行——这就是“守卫”(guard),像保安一样把坏数据挡在门外。
📌 课堂概念
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. input() 返回的值是什么类型?
A intB floatC str(文字)D bool
input 不会自动变数字,哪怕你输入的是 60。
input 不会自动变小数,它先给你文字。
✓ 对!input 永远返回文字(str),这是它最重要的脾气。
input 不会返回真假值。
📖 完整思路:input 永远返回文字。要做算术必须先 int() 或 float() 翻译。
2. 身高 170 输进来,想变成 1.7 米,应写?
A height = height + 100B height = height / 100C height = 100 / heightD height = height * 100
加 100 是 270,不是换算,单位换算要除以 100。
✓ 对!170 ÷ 100 = 1.7,厘米变米。
100 ÷ 170 ≈ 0.59,方向反了。
× 100 会变成 17000,方向反了。
📖 完整思路:厘米 ÷ 100 = 米。这就是单位换算翻译机。
3. while 当守卫的意思是?
A 让程序更快B 输入不合法就重新问,直到合法C 永远循环D 跳过所有输入
守卫不是用来提速的,是负责检查数据的。
✓ 对!不合法就重问,直到合法才放行。
守卫有放行条件,不是无条件永远循环。
守卫不会跳过输入,它会反复检查输入。
📖 完整思路:guard 守卫:条件不满足就一直重新输入,像保安一样挡坏数据。
04
while 循环与乘法表 接下来 while 循环第一课:i 从 0 开始,数到几会停?
In [55] 复制
i = 0
while i < 5:
print(i)
i += 1
豆豆老师小课堂 while 循环入门:从 0 打印到 4。
▸
它是怎么实现的 i 从 0 开始,每次打印后 i += 1(i 自己加 1)。当 i 变成 5 时,i < 5 不成立,循环停止。这就像一个“计数器”。循环变量从 0 开始是个好习惯:在计数、取编号时都有优势,后面学索引你就懂了。
逐行讲解(带注释版代码)
i = 0 # 计数器从 0 开始
while i < 5: # 只要 i 小于 5 就重复
print(i) # 打印当前的 i
i += 1 # i 加 1(i += 1 就是 i = i + 1 的简写)
i = 0计数器从 0 开始
while i < 5:只要 i 小于 5 就重复
print(i)打印当前的 i
i += 1i 加 1(i += 1 就是 i = i + 1 的简写)
为什么输出是这个 输出 0 1 2 3 4:i 依次是 0、1、2、3、4,到 5 时条件不成立停止。注意没有 5。
🧱 新积木 9/10 循环语句 while loop把一段话一遍遍重复,别忘了加计数器 i += 1
接下来 再试一个 while:让 i 自己加 1,看看循环转了几圈。
In [57] 复制
i = 0
total = 0
while i < 5:
print(i)
total += i
i += 1
print(total)
豆豆老师小课堂 循环里顺便把每个数累加起来,最后打印总和。
▸
它是怎么实现的 total = 0 先准备好一个“存钱罐”,循环里 total += i 把每个 i 都投进去。
逐行讲解(带注释版代码)
i = 0 # 计数器从 0 开始
total = 0 # 存钱罐 total 从 0 开始
while i < 5: # 循环 5 次(i=0 到 4)
print(i) # 打印 i
total += i # 把 i 累加进 total
i += 1 # i 加 1
print(total) # 循环结束后打印总和
i = 0计数器从 0 开始
total = 0存钱罐 total 从 0 开始
while i < 5:循环 5 次(i=0 到 4)
print(i)打印 i
total += i把 i 累加进 total
i += 1i 加 1
print(total)循环结束后打印总和
为什么输出是这个 先打印 0~4,最后打印 10:0+1+2+3+4 = 10。
接下来 九九乘法表第一行:先找规律——哪一部分在重复?找到它,循环就写出来了。
In [58] 复制
# 2x1=2 2x2=4
i = 1
while i < 5:
print(str(i) + "*5=" + str(i*5))
i += 1
1*5=5
2*5=10
3*5=15
4*5=20
豆豆老师小课堂 打印 5 的乘法表:1×5 到 4×5。
▸
它是怎么实现的 写循环前先问自己:哪一段话要一遍遍说?找到它,循环就成功了。这个 cell 里 i 从 1 开始,每次打印 i*5,i 到 5 时停止(i < 5),所以只到 4×5。
逐行讲解(带注释版代码)
# 2x1=2 2x2=4
i = 1 # 从 1 开始
while i < 5: # i 小于 5 就循环
print(str(i) + "*5=" + str(i*5)) # 把数字变成文字再拼接打印,如 1*5=5
i += 1 # i 加 1
# 2x1=2 2x2=4注释:这是乘法表的例子格式
i = 1从 1 开始
while i < 5:i 小于 5 就循环
print(str(i) + "*5=" + str(i*5))把数字变成文字再拼接打印,如 1*5=5
i += 1i 加 1
为什么输出是这个 输出 1*5=5 到 4*5=20:因为 i < 5,i 最大是 4,所以没有 5*5。
豆豆提醒 1×5、2×5 里变化的只是被乘数和乘积;算出来的数字要先用 str() 变成文字,才能和 '*5=' 拼在一起打印。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. 下面代码会输出什么?
i = 0
while i < 3:
print(i)
i += 1
A 0 1 2B 1 2 3C 0 1 2 3D 无限循环
✓ 对!i 依次是 0、1、2,到 3 就停了。
从 1 开始是 i=1 的写法,这里 i 从 0 开始。
i=3 时条件不成立,不会打印 3。
循环里有 i += 1,i 在前进,不会死循环。
📖 完整思路:i 从 0 开始,打印后 +1,直到 i=3 不满足条件停:0、1、2。
2. 把上面的 i += 1 删掉,会怎样?
A 输出 0 1 2B 输出 0 0 0C 无限循环D 报错
没有 i += 1,i 不会自己变,不可能输出 0 1 2。
不只输出三次,它会一直打印 0。
✓ 对!i 永远小于 3,程序永远打印 0,死循环。
代码语法没错,不会报错,但会一直跑。
📖 完整思路:i 永远停在 0,条件永远成立——死循环!循环体里必须有让条件走向结束的一步。
接下来 最熟悉的 hello——但今天看的是它打完后怎么换行。
In [59] 复制
print("hello")
print("world")
print('very')
豆豆老师小课堂 三个 print 连续打印三行字。
▸
它是怎么实现的 print 默认打印完会“换行”,所以三个 print 各占一行。
逐行讲解(带注释版代码)
print("hello") # 打印 hello,然后换行
print("world") # 打印 world,换行
print('very') # 打印 very
print("hello")打印 hello,然后换行
print("world")打印 world,换行
print('very')打印 very
为什么输出是这个 输出三行:hello / world / very,每行一个词。
接下来 print 的 end 参数:原来“换行”是它默认干的事。
In [61] 复制
print("hel\nlo", end="\n")
print("world")
print('very')
豆豆老师小课堂 认识换行符 \n:它藏在文字里,负责“换行”。
▸
它是怎么实现的 \n 是一个特殊的字符,写在引号里表示“从这里换行”。end="\n" 表示打印完用换行收尾(这是默认行为)。
逐行讲解(带注释版代码)
print("hel\nlo", end="\n") # hel 和 lo 中间有 \n,所以拆成两行;end="\n" 结尾换行
print("world") # 打印 world
print('very') # 打印 very
print("hel\nlo", end="\n")hel 和 lo 中间有 \n,所以拆成两行;end="\n" 结尾换行
print("world")打印 world
print('very')打印 very
为什么输出是这个 输出 hel / lo / world / very 四行:"hel\nlo" 里的 \n 把一行拆成了两行。
接下来 把 end 改成 %:输出末尾就变成 % 了——end 可以换成任何东西。
In [63] 复制
print("hel\nlo", end="%")
print("world", end="%")
print('very')
豆豆老师小课堂 把 end 改成 "%",打印完就不换行了,改用 % 收尾。
▸
它是怎么实现的 end="%" 意思是“打印完用 % 结尾而不是换行”,所以三个 print 接成了一行。
逐行讲解(带注释版代码)
print("hel\nlo", end="%") # 打印 hel 换行 lo,结尾用 %
print("world", end="%") # 打印 world,结尾用 %
print('very') # 打印 very,默认换行
print("hel\nlo", end="%")打印 hel 换行 lo,结尾用 %
print("world", end="%")打印 world,结尾用 %
print('very')打印 very,默认换行
为什么输出是这个 输出 hel / lo%world%very:lo 后面跟 %,world 后面跟 %,very 最后换行。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. print('a', end='')
print('b') 会输出?
A a bB abC a\nbD ba
end='' 时中间没有空格。
✓ 对!不换行,两个字符连在一起:ab。
a\nb 是默认换行的效果,但 end='' 取消了换行。
先打印 a 再打印 b,顺序不会反。
📖 完整思路:end='' 取消了换行,b 直接接在 a 后面。
2. print('a', end='%')
print('b') 会输出?
A a%bB a%\nbC ab%D a b
✓ 对!a 打完放 %,b 接在后面:a%b。
end='%' 取消了换行,不会出现 a%\nb。
ab% 是 % 放在最后,但 % 在 a 和 b 中间。
end='%' 不放空格。
📖 完整思路:end='%' 表示 a 打完后结尾放 %,不换行,b 接着来:a%b。
接下来 乘法表一行行搭起来:先看看 2 × 1 到 2 × 9 怎么用循环写。
In [64] 复制
# 2x1=2 2x2=4
i = 1
while i < 5:
print(str(i) + "*5=" + str(i*5), end=" ")
i += 1
1*5=5 2*5=10 3*5=15 4*5=20
豆豆老师小课堂 乘法表一行打印:用 end=" " 让每次打印之间用空格连接,不换行。
▸
它是怎么实现的 循环里每个 print 结尾用空格,这样 1*5=5、2*5=10 就在同一行了。
逐行讲解(带注释版代码)
# 2x1=2 2x2=4
i = 1 # 从 1 开始
while i < 5: # 循环
print(str(i) + "*5=" + str(i*5), end=" ") # 打印并用空格结尾,不换行
i += 1 # i 加 1
# 2x1=2 2x2=4注释
i = 1从 1 开始
while i < 5:循环
print(str(i) + "*5=" + str(i*5), end=" ")打印并用空格结尾,不换行
i += 1i 加 1
为什么输出是这个 输出 1*5=5 2*5=10 3*5=15 4*5=20 (尾部有个空格):因为 end=" "。
接下来 再往上搭:这一行是 3 的乘法表,哪里变了?
In [66] 复制
# 2x1=2 2x2=4
num = 5
i = 1
while i < num + 1:
print(str(i) + "*5=" + str(i*5), end=" ")
i += 1
print()
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
豆豆老师小课堂 把循环次数做成变量 num,打印完整的 1×5 到 5×5。
▸
它是怎么实现的 num = 5,条件 i < num + 1 等价于 i < 6,所以 i 能到 5,打印出 5*5。循环结束后 print() 补一个换行。
逐行讲解(带注释版代码)
# 2x1=2 2x2=4
num = 5 # 要乘的数字存进 num
i = 1 # 从 1 开始
while i < num + 1: # i < 6,i 能取到 5
print(str(i) + "*5=" + str(i*5), end=" ") # 打印并用空格结尾
i += 1 # i 加 1
print() # 循环结束后打印一个空行
# 2x1=2 2x2=4注释
num = 5要乘的数字存进 num
i = 1从 1 开始
while i < num + 1:i < 6,i 能取到 5
print(str(i) + "*5=" + str(i*5), end=" ")打印并用空格结尾
i += 1i 加 1
print()循环结束后打印一个空行
为什么输出是这个 输出 1*5=5 … 5*5=25 一行:这次包含 5*5=25 了。
接下来 继续:4 的乘法表。规律已经出现,重复的代码越来越短。
In [67] 复制
# 2x1=2 2x2=4
num = 5
i = 1
while i < num + 1:
print(str(i) + "*5=" + str(i*5), end=" ")
i += 1
print()
num = 6
i = 1
while i < num + 1:
print(str(i) + "*5=" + str(i*5), end=" ")
i += 1
print()
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 6*5=30
豆豆老师小课堂 把同样的循环写两遍:先打 5 的乘法表,再打 6 的。
▸
它是怎么实现的 第一段 num=5 循环,第二段把 num 改成 6 再循环一遍。代码重复了,但能用。
逐行讲解(带注释版代码)
num = 5 # 第一段:num = 5
i = 1 # 计数器归 1
while i < num + 1: # 打印 1×5 到 5×5
print(str(i) + "*5=" + str(i*5), end=" ") # 拼接打印
i += 1 # i 加 1
print() # 换行
num = 6 # 第二段:num 改成 6
i = 1 # 计数器重新归 1(重要!)
while i < num + 1: # 打印 1×5 到 6×5
print(str(i) + "*5=" + str(i*5), end=" ") # 拼接打印
i += 1 # i 加 1
print() # 换行
num = 5第一段:num = 5
i = 1计数器归 1
while i < num + 1:打印 1×5 到 5×5
print(str(i) + "*5=" + str(i*5), end=" ")拼接打印
i += 1i 加 1
print()换行
num = 6第二段:num 改成 6
i = 1计数器重新归 1(重要!)
while i < num + 1:打印 1×5 到 6×5
print(str(i) + "*5=" + str(i*5), end=" ")拼接打印
i += 1i 加 1
print()换行
为什么输出是这个 两行输出:第一行到 5*5=25,第二行多一个 6*5=30。
接下来 最后一块:5 的乘法表。你有没有发现——变的是数字,不变的是结构?
In [68] 复制
# 2x1=2 2x2=4
num = 5
i = 1
while i < num + 1:
print(str(i) + "*5=" + str(i*5), end=" ")
i += 1
print()
num = 6
i = 1
while i < num + 1:
print(str(i) + "*5=" + str(i*5), end=" ")
i += 1
print()
num = 7
i = 1
while i < num + 1:
print(str(i) + "*5=" + str(i*5), end=" ")
i += 1
print()
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 6*5=30
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 6*5=30 7*5=35
豆豆老师小课堂 同样的套路再来一遍:5、6、7 的乘法表。
▸
它是怎么实现的 复制粘贴第三段,num = 7。代码越来越长了——这正是后面要用“嵌套循环”压缩的原因。
逐行讲解(带注释版代码)
num = 5 # 第一段 num=5
i = 1 # 计数器归 1
while i < num + 1: # 打印 5 的乘法表
print(str(i) + "*5=" + str(i*5), end=" ") # 拼接打印
i += 1 # i 加 1
print() # 换行
num = 6 # 第二段 num=6
i = 1 # 计数器归 1
while i < num + 1: # 打印 6 的乘法表
print(str(i) + "*5=" + str(i*5), end=" ") # 拼接打印
i += 1 # i 加 1
print() # 换行
num = 7 # 第三段 num=7
i = 1 # 计数器归 1
while i < num + 1: # 打印 7 的乘法表
print(str(i) + "*5=" + str(i*5), end=" ") # 拼接打印
i += 1 # i 加 1
print() # 换行
num = 5第一段 num=5
i = 1计数器归 1
while i < num + 1:打印 5 的乘法表
print(str(i) + "*5=" + str(i*5), end=" ")拼接打印
i += 1i 加 1
print()换行
num = 6第二段 num=6
i = 1计数器归 1
while i < num + 1:打印 6 的乘法表
print(str(i) + "*5=" + str(i*5), end=" ")拼接打印
i += 1i 加 1
print()换行
num = 7第三段 num=7
i = 1计数器归 1
while i < num + 1:打印 7 的乘法表
print(str(i) + "*5=" + str(i*5), end=" ")拼接打印
i += 1i 加 1
print()换行
为什么输出是这个 三行输出:5、6、7 的乘法表各一行。代码重复三次,显得笨重。
接下来 收尾对比:print 的默认换行行为,再确认一次。
In [70] 复制
print("hello")
print()
print("world")
豆豆老师小课堂 print() 不带参数:打印一个空行。
▸
它是怎么实现的 print() 括号里什么都没有,就只换行,不打印任何字。
逐行讲解(带注释版代码)
print("hello") # 打印 hello
print() # 打印一个空行
print("world") # 打印 world
print("hello")打印 hello
print()打印一个空行
print("world")打印 world
为什么输出是这个 输出 hello / (空行)/ world:中间的 print() 制造了一个空行。
🧰 积木收藏盒 · 学到这里,你已经点亮 9 块积木
值 value表达式 expression变量 variable运算符+操作数 operator + operand输入语句 input函数调用 function call输出语句 print条件语句 if循环语句 while
新学的积木会自动掉进盒子,继续往下学吧!
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 写 while 忘了 i += 1 会怎样?
会无限循环!i 永远不变,条件永远成立,程序永远跑不完。课堂上就发生过:学生写完循环忘了“让计数器前进”,程序卡死。记住:while 循环体里必须有让条件“走向结束”的那一步。
📌 来自课堂:学生真实事故
💬 为什么计数器要从 0 开始?
这是计算机的习惯(也和你学的字符串索引一致)。0 代表“还没开始”,循环第 1 次 i=0、第 2 次 i=1……数到 n-1 就结束。用 0 开始,很多公式(比如 5-i)会更好写。
📌 课堂重点
💬 end 参数是干什么的?
print 默认打完一行就换行(end='\n')。把 end 改成别的(比如 '' 或 '%'),它就不换行了,下一个 print 接着往后写——打印图案就靠它。
📌 课堂重点
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. 下面哪段会无限循环?
A i = 0
while i < 5:
i += 1B i = 0
while i < 5:
print(i)C i = 5
while i > 0:
i -= 1D i = 0
while i <= 4:
i += 1
i 每次都 +1,数到 5 就停,正常。
✓ 就是它!只打印不改变 i,i 永远小于 5,循环永远转。
i 从 5 一路减到 0,正常结束。
i 加到 5 就停,正常。
📖 完整思路:B 里 i 从不变化,条件永远成立——死循环!循环体里必须有让条件走向结束的一步。
2. print('a', end='') 再 print('b'),输出是?
A a\nbB abC a bD 报错
a\nb 是默认换行的效果,但这里 end='' 取消了换行。
✓ 对!end='' 不换行,b 直接接在 a 后面。
中间没有空格,两个 print 是连着写的。
end 参数是合法的,不会报错。
📖 完整思路:end='' 让第一个 print 不换行,第二个 print 接在 a 后面,输出 ab。
3. 九九乘法表的“重复部分”是?
A 打印完整个表B 一行里 2×1、2×2……2×9 的规律C 输入用户D 算 BMI
整张表是“很多行”,先看一行内的重复。
✓ 对!一行内 2×1 到 2×9 在重复变化,正是循环要干的活。
输入用户和乘法表没关系。
算 BMI 是上一章的内容,这里在讲乘法表。
📖 完整思路:找重复 = 找规律:一行内乘数从 1 变到 9,这就是要交给循环的部分。
05
嵌套循环与星号图案 *****
*****
*****
*****
*****
* ** *** ****
*****
豆豆老师小课堂 目标图案展示:上面是 5 行 5 颗星的正方形,下面是逐行递增的三角形。
▸
先想一想(任务说明) 任务来了:先用星号打印一个 5 行 × 5 颗的正方形,再打印一个三角形(第 1 行 1 颗、第 2 行 2 颗……第 5 行 5 颗)。先别写代码,像侦探一样观察规律:每一行在重复做什么?(打几颗星 + 换行)三角形里,星的数量和行数有什么关系?(第 n 行就是 n 颗)找规律 → 定计划 → 再动手。想不出来也没关系,先自己试一次,错了就看看下面的代码怎么想。
它是怎么实现的 这一页没有代码,是“任务目标”——你要用 while 循环让电脑画出这两个图案。重点不是背代码,而是学会像计算机一样思考:把任务拆成“每一行做什么”,再找出“行数变化时数量怎么变”的规律(pattern)。
逐行讲解(带注释版代码)
***** # 正方形:每行 5 颗,共 5 行——每行都一样
* # 三角形第 1 行:1 颗
** # 第 2 行:2 颗
*** # 第 3 行:3 颗
**** # 第 4 行:4 颗
***** # 第 5 行:5 颗——行数和星数一样
*****正方形:每行 5 颗,共 5 行——每行都一样
*三角形第 1 行:1 颗
**第 2 行:2 颗
***第 3 行:3 颗
****第 4 行:4 颗
*****第 5 行:5 颗——行数和星数一样
为什么输出是这个 这是目标图。看完它,你可以先合上答案自己写一遍,再对比下面的代码。
豆豆提醒 找规律的诀窍:写一张小表格——第几行 → 几颗星。表格填完,规律就自己跳出来了。
接下来 打印星号前先认识 lines:它记录“现在是第几行”。
In [72] 复制
lines = 1
while lines <= 5:
stars = 1
row = ""
while stars <= lines:
row += "*"
stars += 1
print(row)
lines += 1
豆豆老师小课堂 用嵌套循环打印递增的星号三角形:1 行、2 行……5 行。
▸
它是怎么实现的 外层 while 管“行数”(lines 1~5),内层 while 管“每行几个星”(stars 从 1 到 lines)。每行先攒进 row,再一起打印。这就是“大循环套小循环”。
逐行讲解(带注释版代码)
lines = 1 # 从第 1 行开始
while lines <= 5: # 一共 5 行
stars = 1 # 每行从 1 颗星开始
row = "" # row 是装这一行星的“小篮子”,先清空
while stars <= lines: # 这行要放 lines 颗星
row += "*" # 往篮子里放一颗星
stars += 1 # 星星计数器加 1
print(row) # 整行星一起打印
lines += 1 # 行数加 1,去下一行
lines = 1从第 1 行开始
while lines <= 5:一共 5 行
stars = 1每行从 1 颗星开始
row = ""row 是装这一行星的“小篮子”,先清空
while stars <= lines:这行要放 lines 颗星
row += "*"往篮子里放一颗星
stars += 1星星计数器加 1
print(row)整行星一起打印
lines += 1行数加 1,去下一行
为什么输出是这个 输出:* / ** / *** / **** / *****。第 n 行有 n 颗星。
🧱 新积木 10/10 复合语句(嵌套) nested statement语句里还能再装语句,一层套一层
接下来 再看一眼 lines 怎么变——它是循环的“计数器”。
In [74] 复制
lines = 1
while lines <= 5:
stars = 1
while stars <= lines:
print("*", end="")
stars += 1
print()
lines += 1
豆豆老师小课堂 同样的三角形,换一种写法:不攒篮子,直接一颗颗打印。
▸
它是怎么实现的 内层循环用 print("*", end="") 一颗颗打星不换行,内层结束再 print() 换行。效果和 cell 54 一样,实现方式不同。
逐行讲解(带注释版代码)
lines = 1 # 从第 1 行开始
while lines <= 5: # 5 行
stars = 1 # 每行从 1 颗星开始
while stars <= lines: # 内层循环:打 lines 颗星
print("*", end="") # 打印一颗星,不换行(end="" 是空结尾)
stars += 1 # 星星计数器加 1
print() # 一行打完,换行
lines += 1 # 行数加 1
lines = 1从第 1 行开始
while lines <= 5:5 行
stars = 1每行从 1 颗星开始
while stars <= lines:内层循环:打 lines 颗星
print("*", end="")打印一颗星,不换行(end="" 是空结尾)
stars += 1星星计数器加 1
print()一行打完,换行
lines += 1行数加 1
为什么输出是这个 输出同样的三角形:* / ** / *** / **** / *****。
接下来 新任务:倒三角——第 1 行 5 颗、第 2 行 4 颗。先填表格找公式。
In [ ] 复制
*****
****
***
**
*
豆豆老师小课堂 目标图案展示:这次要的是“倒三角”——5 行、4 行……1 行。
▸
先想一想(任务说明) 新任务:这次要的是“倒三角”——第 1 行 5 颗、第 2 行 4 颗……第 5 行 1 颗。先填一张小表格:行号 1 到 5,分别几颗星?发现了吗——行数越大,星越少。你能不能写出“几颗星 = 几减几”的公式?先自己想,再看下面的代码。
它是怎么实现的 这个 cell 的“代码”其实只有目标结果(星号),没有可执行代码。它是下一个 cell 要实现的目标图。
逐行讲解(带注释版代码)
***** # 目标:第 1 行 5 颗星
**** # 第 2 行 4 颗星
*** # 第 3 行 3 颗星
** # 第 4 行 2 颗星
* # 第 5 行 1 颗星
*****目标:第 1 行 5 颗星
****第 2 行 4 颗星
***第 3 行 3 颗星
**第 4 行 2 颗星
*第 5 行 1 颗星
为什么输出是这个 这个 cell 保存的是运行结果:一个从 5 递减到 1 的倒三角。
接下来 偷看答案前,先想清楚“5 - lines + 1”里的 +1 为什么不能省。
In [76] 复制
lines = 1
while lines <= 5:
stars = 1
row = ""
while stars <= 5 - lines + 1:
row += "*"
stars += 1
print(row)
lines += 1
豆豆老师小课堂 实现倒三角:第 lines 行打印 5 - lines + 1 颗星。
▸
先想一想(任务说明) 在偷看答案之前,再想想你的公式:如果行号是 lines,那这行要打 5 - lines + 1 颗星。你能说清楚为什么“+1”吗?(第 1 行要 5 颗,5 - 1 只有 4 颗,所以加 1 补回来。)下面的代码就是按这个公式写的,看看和你想的一不一样。
它是怎么实现的 关键在条件 stars <= 5 - lines + 1:行数越大,要打的星越少。lines=1 时打 5 颗,lines=5 时打 1 颗。
逐行讲解(带注释版代码)
lines = 1 # 从第 1 行开始
while lines <= 5: # 5 行
stars = 1 # 从 1 颗星开始
row = "" # 清空篮子
while stars <= 5 - lines + 1: # 这行打 5-lines+1 颗星
row += "*" # 放一颗星
stars += 1 # 计数加 1
print(row) # 打印整行
lines += 1 # 行数加 1
lines = 1从第 1 行开始
while lines <= 5:5 行
stars = 1从 1 颗星开始
row = ""清空篮子
while stars <= 5 - lines + 1:这行打 5-lines+1 颗星
row += "*"放一颗星
stars += 1计数加 1
print(row)打印整行
lines += 1行数加 1
为什么输出是这个 输出 5 到 1 颗星的倒三角:***** / **** / *** / ** / *。
接下来 这是目标图:看看我们要打印的三角形长什么样。
In [ ] 复制
*
***
*
***
*****
*
***
*****
*******
豆豆老师小课堂 目标图案:三个叠在一起的三角形(1、2、3 层)。
▸
它是怎么实现的 目标图展示:第 1 层 1 行、第 2 层 2 行、第 3 层 3 行,每层都是递增的奇数星行。
逐行讲解(带注释版代码)
* # 第 1 层:1 行
*** # 第 2 层开始:1 行 1 颗
* # ……
*** # 第 2 层:2 行 3 颗
***** # 第 2 层:3 行 5 颗
* # 第 3 层:……
*** # ……
***** # ……
******* # 第 3 层最高:7 颗
*第 1 层:1 行
***第 2 层开始:1 行 1 颗
*……
***第 2 层:2 行 3 颗
*****第 2 层:3 行 5 颗
*第 3 层:……
***……
*****……
*******第 3 层最高:7 颗
为什么输出是这个 这是目标图(保存的结果)。接下来用代码实现它。
接下来 再看一遍目标图——数一数每一行的星号个数。
In [ ] 复制
*
**
***
****
*****
豆豆老师小课堂 目标图案:右对齐的三角形(前面带空格)。
▸
它是怎么实现的 每一行前面有空格,让星号靠右对齐。这是“带缩进”的图案目标。
逐行讲解(带注释版代码)
* # 4 个空格 + 1 颗星
** # 3 个空格 + 2 颗星
*** # 2 个空格 + 3 颗星
**** # 1 个空格 + 4 颗星
***** # 0 个空格 + 5 颗星
*4 个空格 + 1 颗星
**3 个空格 + 2 颗星
***2 个空格 + 3 颗星
****1 个空格 + 4 颗星
*****0 个空格 + 5 颗星
接下来 记住这个形状:它是接下来所有图案练习的“地基”。
In [ ] 复制
*
***
*
***
*****
*
***
*****
*******
豆豆老师小课堂 目标图案再次展示:三层金字塔叠放。
▸
它是怎么实现的 和 cell 58 一样的图,是课堂的目标图。
逐行讲解(带注释版代码)
* # 第 1 层
*** # 第 2 层第 1 行
* # ……
*** # 第 2 层
***** # ……
* # 第 3 层
*** # ……
***** # ……
******* # 第 3 层最高行
*第 1 层
***第 2 层第 1 行
*……
***第 2 层
*****……
*第 3 层
***……
*****……
*******第 3 层最高行
接下来 代码第一版:i 从 1 开始,一行行把三角形打出来。
In [77] 复制
i = 1
while i <= 5:
i += 1
豆豆老师小课堂 一个“空转”的循环:循环体里忘了打印,什么也不输出。
▸
它是怎么实现的 while i <= 5 循环 5 次,但循环体里只有 i += 1,没有 print。电脑默默数数,什么也没显示。
逐行讲解(带注释版代码)
i = 1 # 从 1 开始
while i <= 5: # 循环 5 次
i += 1 # 只做 i 加 1——忘了打印!
i = 1从 1 开始
while i <= 5:循环 5 次
i += 1只做 i 加 1——忘了打印!
为什么输出是这个 没有输出:循环确实跑了 5 次,但一次都没打印。这是个“陷阱”示范。
接下来 找重复:这四段三角形,什么不变?什么在变?(提示:只换了一个数)
In [90] 复制
lines = 1
while lines <= 2:
stars = 1
row = ""
while stars <= lines * 2 - 1:
row += "*"
stars += 1
print(row)
lines += 1
lines = 1
while lines <= 3:
stars = 1
row = ""
while stars <= lines * 2 - 1:
row += "*"
stars += 1
print(row)
lines += 1
lines = 1
while lines <= 4:
stars = 1
row = ""
while stars <= lines * 2 - 1:
row += "*"
stars += 1
print(row)
lines += 1
lines = 1
while lines <= 5:
stars = 1
row = ""
while stars <= lines * 2 - 1:
row += "*"
stars += 1
print(row)
lines += 1
*
***
*
***
*****
*
***
*****
*******
*
***
*****
*******
*********
豆豆老师小课堂 用四段几乎一样的代码,分别打印 2 行、3 行、4 行、5 行的三角形,拼成金字塔。
▸
先想一想(任务说明) 看看下面的代码——它打了 4 段几乎一模一样的三角形。先找“重复”:这四段里,什么是不变的?(每段内部的结构完全一样)什么在变?(只换了一个数:2、3、4、5)。如果你来当程序员,会不会觉得“写四遍”太累?想一想:能不能只写一段,让电脑自己换那个数?这个念头,就是下一节课“嵌套循环”的火种。
它是怎么实现的 四段 while 循环,区别只是循环次数(<=2、<=3、<=4、<=5)和星数公式 stars <= lines*2 - 1(打奇数颗星)。代码又长又重复。
逐行讲解(带注释版代码)
lines = 1 # 第 1 段:从 1 行开始
while lines <= 2: # 只打 2 行
stars = 1 # 每行从 1 颗星开始
row = "" # 清空篮子
while stars <= lines * 2 - 1: # 打奇数颗星(1、3)
row += "*" # 放一颗星
stars += 1 # 计数加 1
print(row) # 打印整行
lines += 1 # 行数加 1
lines = 1 # 第 2 段:重新从 1 行开始
while lines <= 3: # 打 3 行(1、3、5 颗星)
stars = 1 # 每行从 1 颗星开始
row = "" # 清空篮子
while stars <= lines * 2 - 1: # 打奇数颗星
row += "*" # 放一颗星
stars += 1 # 计数加 1
print(row) # 打印整行
lines += 1 # 行数加 1
lines = 1 # 第 3 段:重新从 1 行开始
while lines <= 4: # 打 4 行(1、3、5、7 颗星)
stars = 1 # 每行从 1 颗星开始
row = "" # 清空篮子
while stars <= lines * 2 - 1: # 打奇数颗星
row += "*" # 放一颗星
stars += 1 # 计数加 1
print(row) # 打印整行
lines += 1 # 行数加 1
lines = 1 # 第 4 段:重新从 1 行开始
while lines <= 5: # 打 5 行(1、3、5、7、9 颗星)
stars = 1 # 每行从 1 颗星开始
row = "" # 清空篮子
while stars <= lines * 2 - 1: # 打奇数颗星
row += "*" # 放一颗星
stars += 1 # 计数加 1
print(row) # 打印整行
lines += 1 # 行数加 1
lines = 1第 1 段:从 1 行开始
while lines <= 2:只打 2 行
stars = 1每行从 1 颗星开始
row = ""清空篮子
while stars <= lines * 2 - 1:打奇数颗星(1、3)
row += "*"放一颗星
stars += 1计数加 1
print(row)打印整行
lines += 1行数加 1
lines = 1第 2 段:重新从 1 行开始
while lines <= 3:打 3 行(1、3、5 颗星)
stars = 1每行从 1 颗星开始
row = ""清空篮子
while stars <= lines * 2 - 1:打奇数颗星
row += "*"放一颗星
stars += 1计数加 1
print(row)打印整行
lines += 1行数加 1
lines = 1第 3 段:重新从 1 行开始
while lines <= 4:打 4 行(1、3、5、7 颗星)
stars = 1每行从 1 颗星开始
row = ""清空篮子
while stars <= lines * 2 - 1:打奇数颗星
row += "*"放一颗星
stars += 1计数加 1
print(row)打印整行
lines += 1行数加 1
lines = 1第 4 段:重新从 1 行开始
while lines <= 5:打 5 行(1、3、5、7、9 颗星)
stars = 1每行从 1 颗星开始
row = ""清空篮子
while stars <= lines * 2 - 1:打奇数颗星
row += "*"放一颗星
stars += 1计数加 1
print(row)打印整行
lines += 1行数加 1
为什么输出是这个 输出一个金字塔:* / ***(2 行),然后 1、3、5,再 1、3、5、7,再 1、3、5、7、9。代码重复 4 遍,很啰嗦——下一个 cell 用循环压缩它。
接下来 答案揭晓前最后一想:如果有个东西能替我们依次变成 2、3、4、5,是不是只需一段代码?
In [94] 复制
layer = 2
while layer <= 5:
lines = 1
while lines <= layer:
stars = 1
row = ""
while stars <= lines * 2 - 1:
row += "*"
stars += 1
print(row)
lines += 1
layer += 1
*
***
*
***
*****
*
***
*****
*******
*
***
*****
*******
*********
豆豆老师小课堂 用“外层循环管层数”把 4 段重复代码压缩成一段。
▸
先想一想(任务说明) 答案揭晓前的最后一想:上一段代码,四段之间“只换一个数”(2、3、4、5)。如果有个东西能替我们“依次变成 2、3、4、5”,每变一次就把三角形打一遍——是不是就只需要一段代码了?这个东西就是“外层循环”。先自己写写看,卡住了再看下面的答案。
它是怎么实现的 layer 从 2 到 5(表示每段要打多少行)。外层循环每走一轮,内层就把 1~layer 行的三角形打一遍。这就是“两层嵌套循环”。
逐行讲解(带注释版代码)
layer = 2 # 从 2 层开始
while layer <= 5: # layer 从 2 到 5,共 4 轮
lines = 1 # 每轮都从第 1 行开始
while lines <= layer: # 这一轮要打 layer 行
stars = 1 # 每行从 1 颗星开始
row = "" # 清空篮子
while stars <= lines * 2 - 1: # 打奇数颗星
row += "*" # 放星
stars += 1 # 计数
print(row) # 打印整行
lines += 1 # 行数加 1
layer += 1 # 层数加 1,进入下一轮
layer = 2从 2 层开始
while layer <= 5:layer 从 2 到 5,共 4 轮
lines = 1每轮都从第 1 行开始
while lines <= layer:这一轮要打 layer 行
stars = 1每行从 1 颗星开始
row = ""清空篮子
while stars <= lines * 2 - 1:打奇数颗星
row += "*"放星
stars += 1计数
print(row)打印整行
lines += 1行数加 1
layer += 1层数加 1,进入下一轮
为什么输出是这个 输出 2 行、3 行、4 行、5 行的金字塔,和 cell 62 一模一样,但代码短多了。
接下来 圣诞树来了:layer 是层数——先看它和三角形的区别。
In [103] 复制
layer = 2
while layer <= 5:
lines = 0
while lines < layer:
stars = 0
row = ""
while stars < lines * 2 + 1:
row += "*"
stars += 1
print(row)
lines += 1
layer += 1
*
***
*
***
*****
*
***
*****
*******
*
***
*****
*******
*********
豆豆老师小课堂 换一种计数习惯:从 0 开始计数,重写同一个金字塔。
▸
它是怎么实现的 lines 和 stars 都从 0 开始,条件改成 < layer 和 < lines*2+1。数学上等价,只是起点不同。
逐行讲解(带注释版代码)
layer = 2 # 层数从 2 开始
while layer <= 5: # 4 轮
lines = 0 # 从第 0 行开始(计数习惯)
while lines < layer: # 打 layer 行
stars = 0 # 从 0 颗星开始
row = "" # 清空篮子
while stars < lines * 2 + 1: # 打 lines*2+1 颗星
row += "*" # 放星
stars += 1 # 计数
print(row) # 打印
lines += 1 # 行数加 1
layer += 1 # 层数加 1
layer = 2层数从 2 开始
while layer <= 5:4 轮
lines = 0从第 0 行开始(计数习惯)
while lines < layer:打 layer 行
stars = 0从 0 颗星开始
row = ""清空篮子
while stars < lines * 2 + 1:打 lines*2+1 颗星
row += "*"放星
stars += 1计数
print(row)打印
lines += 1行数加 1
layer += 1层数加 1
为什么输出是这个 输出和 cell 63 完全一样的金字塔:从 0 开始计数,结果不变。
接下来 圣诞树的目标图:数一数每层每行的星号,找 2n-1 的规律。
In [ ] 复制
*
***
*
***
*****
*
***
*****
*******
*
*
*
*
豆豆老师小课堂 目标图案:右对齐的三层金字塔。
▸
它是怎么实现的 目标图展示:每层都带前导空格,星号靠右对齐。
逐行讲解(带注释版代码)
* # 第 1 层:3 空格 1 星
*** # 第 2 层:2 空格 3 星
* # ……
*** # ……
***** # ……
* # 第 3 层:……
* # ……
* # ……
* # 第 3 层的小尖尖
*第 1 层:3 空格 1 星
***第 2 层:2 空格 3 星
*……
***……
*****……
*第 3 层:……
*……
*……
*第 3 层的小尖尖
为什么输出是这个 目标图(右对齐金字塔),无新代码。
接下来 圣诞树完整代码:外层管层、中层管行、内层管星——三个循环叠罗汉。
In [104] 复制
layer = 2
while layer <= 5:
lines = 0
while lines < layer:
stars = 0
row = ""
while stars < lines * 2 + 1:
row += "*"
stars += 1
print(row)
lines += 1
layer += 1
*
***
*
***
*****
*
***
*****
*******
*
***
*****
*******
*********
豆豆老师小课堂 用 cell 64 的“从 0 开始”写法再跑一遍金字塔(代码相同,复习验证)。
▸
它是怎么实现的 代码和 cell 64 完全一样,是课堂上的重复练习,验证结果稳定。
逐行讲解(带注释版代码)
layer = 2 # 层数从 2 开始
while layer <= 5: # 4 轮
lines = 0 # 行从 0 开始
while lines < layer: # 打 layer 行
stars = 0 # 星从 0 开始
row = "" # 清空篮子
while stars < lines * 2 + 1: # 打奇数颗星
row += "*" # 放星
stars += 1 # 计数
print(row) # 打印
lines += 1 # 行数加 1
layer += 1 # 层数加 1
layer = 2层数从 2 开始
while layer <= 5:4 轮
lines = 0行从 0 开始
while lines < layer:打 layer 行
stars = 0星从 0 开始
row = ""清空篮子
while stars < lines * 2 + 1:打奇数颗星
row += "*"放星
stars += 1计数
print(row)打印
lines += 1行数加 1
layer += 1层数加 1
为什么输出是这个 输出和之前一样的金字塔,验证代码稳定可复现。
🧰 积木收藏盒 · 学到这里,你已经点亮 10 块积木
值 value表达式 expression变量 variable运算符+操作数 operator + operand输入语句 input函数调用 function call输出语句 print条件语句 if循环语句 while复合语句 nested
🎉 10 块积木全部拼完,整张概念地图完成啦!
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 外层管行、内层管星,怎么理解?
外层循环转一圈 = 打印一行;内层循环转一圈 = 打印这一行里的一个星。外层慢(1 秒一行),内层快(1 秒好几个星)。先看外层,再想内层。
📌 课堂口诀
💬 为什么第 n 行就是 n 颗星?
这是你自己找出来的规律!行号 1→1 颗、2→2 颗……所以“星数 = 行号”。规律找对了,代码就是把这个规律翻译成循环。
📌 找规律方法
💬 倒三角的公式 5 - lines + 1 为什么有 +1?
第 1 行要 5 颗:5 - 1 = 4,少了 1 颗,所以要 +1 补回来。把行号代进去验算:第 1 行 5-1+1=5 ✓,第 5 行 5-5+1=1 ✓。
📌 课堂验算
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. 外层循环控制什么?
A 每一行有几个星B 打印几行C 星号的大小D 颜色
每行几个星是内层循环管的。
✓ 对!外层循环转一圈 = 打印一行。
星号大小由字符决定,不是循环管的。
print 不控制颜色。
📖 完整思路:外层慢、管行数;内层快、管每行的星。口诀:外层管行、内层管星。
2. 第 n 行 n 颗星的三角形,第 4 行有几颗?
A 3B 4C 5D 不确定
3 颗是第 3 行,不是第 4 行。
✓ 对!星数 = 行号,第 4 行 4 颗。
5 颗是第 5 行的。
规律已经找到,答案很确定。
📖 完整思路:规律就是“星数 = 行号”,第 4 行 4 颗。
3. 倒三角第 3 行(总共 5 行)有几颗星?
A 3B 4C 5D 2
✓ 对!5 - 3 + 1 = 3 颗。
4 颗是第 2 行的。
5 颗是第 1 行的。
2 颗是第 4 行的。
📖 完整思路:公式 5 - lines + 1:5 - 3 + 1 = 3 颗。
06
综合练习:出租车计费 接下来 综合大任务:出租车计费。先拆问题:起步费 + 超出费 + 等时费,再写代码。
In [106] 复制
dist = int(input())
wait = int(input())
if dist <= 2:
fee = 6.0
elif dist <= 10:
fee = 6.0 + (dist - 2) * 1.8
else:
fee = 6.0 + 8 * 1.8 + (dist - 10) * 1.8 * 1.5
fee = fee + wait // 3
fee = int(fee * 10 + 0.5) / 10.0
if fee == int(fee):
print(int(fee))
else:
print(fee)
豆豆老师小课堂 综合练习:算出租车费。起步 6 元(2 公里内),超出部分每公里 1.8 元,超过 10 公里加价 1.5 倍,等时每 3 分钟加 1 元。
▸
先想一想(任务说明) 综合大任务:出租车计费。规则有三条——2 公里内 6 元;超出部分每公里 1.8 元;超过 10 公里再加价 1.5 倍;另外等时每 3 分钟加 1 元。先别写代码,像拆积木一样把问题拆开:费 = 起步费 + 超出费 + 等时费。每一块怎么算?哪块需要判断(if)?哪块是死算?拆完再写,代码就自己长出来了。
它是怎么实现的 这是 if/elif/else 多分支:距离 ≤2 用起步价;≤10 用中间公式;>10 用加价公式。再算等时费,最后四舍五入到一位小数。
逐行讲解(带注释版代码)
dist = int(input()) # 输入距离(公里)1
wait = int(input()) # 输入等时(分钟)3
if dist <= 2: # 如果距离 ≤ 2 公里
fee = 6.0 # 起步价 6 元
elif dist <= 10: # 否则如果 ≤ 10 公里
fee = 6.0 + (dist - 2) * 1.8 # 6 元 + 超出 2 公里的部分 × 1.8
else: # 否则(> 10 公里)
fee = 6.0 + 8 * 1.8 + (dist - 10) * 1.8 * 1.5 # 前 8 公里 × 1.8,超出 10 公里的部分 × 1.8 × 1.5(加价)
fee = fee + wait // 3 # 等时费:每 3 分钟 1 元(// 是整除)
fee = int(fee * 10 + 0.5) / 10.0 # 四舍五入保留 1 位小数的小技巧
if fee == int(fee): # 如果 fee 是整数(比如 7.0)
print(int(fee)) # 打印成整数 7,不带小数点
else: # 否则
print(fee) # 打印小数
dist = int(input())输入距离(公里)1
wait = int(input())输入等时(分钟)3
if dist <= 2:如果距离 ≤ 2 公里
fee = 6.0起步价 6 元
elif dist <= 10:否则如果 ≤ 10 公里
fee = 6.0 + (dist - 2) * 1.86 元 + 超出 2 公里的部分 × 1.8
else:否则(> 10 公里)
fee = 6.0 + 8 * 1.8 + (dist - 10) * 1.8 * 1.5前 8 公里 × 1.8,超出 10 公里的部分 × 1.8 × 1.5(加价)
fee = fee + wait // 3等时费:每 3 分钟 1 元(// 是整除)
fee = int(fee * 10 + 0.5) / 10.0四舍五入保留 1 位小数的小技巧
if fee == int(fee):如果 fee 是整数(比如 7.0)
print(int(fee))打印成整数 7,不带小数点
else:否则
print(fee)打印小数
为什么输出是这个 输入距离 1、等时 3:距离 ≤ 2,fee=6;等时 3 分钟加 1,fee=7;7.0 是整数,打印 7。
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 int(c) == c 是啥意思?
c 是费用,可能是 9.5 或 9.0。int(c) 把小数部分砍掉。如果 int(c) == c,说明费用本来就是整数(比如 9.0 → 9),可以省掉小数。这是学生想出来的巧妙判断!
📌 来自课堂:学生的巧妙思路
💬 int(input()) 能一步做完吗?
能。input() 拿到文字,int() 立刻翻译成数字——两步并一步。等价于:a = input(); a = int(a)。
📌 课堂简化写法
💬 分段计费为什么要 if / elif?
因为费用要“看情况”:2 公里内一个价,超出 2 公里另一个价,超过 10 公里还要加价。if/elif 就是让程序按情况选一条路算。
📌 综合练习
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. int(9.0) == 9.0 的结果是?
A TrueB FalseC 报错D 9
✓ 对!int(9.0) 是 9,9 和 9.0 相等,结果是 True。
9 和 9.0 在 Python 里数值相等,不会返回 False。
int 和比较都合法,不会报错。
结果是 True/False,不是数字 9。
📖 完整思路:int(9.0) = 9,9 == 9.0 为 True。用它判断费用是不是整数。
2. a = int(input()) 等价于下面哪组?
A a = input()B a = input()
a = int(a)C a = int()D int(input(a))
只拿文字不翻译,a 还是 str,不能做算术。
✓ 对!先 input 再 int,和一步写法完全等价。
int() 里要放内容,空着会报错。
input(a) 里 a 还没定义,而且顺序写反了。
📖 完整思路:两步并一步:先 input 拿文字,再 int 翻译成数字。
3. 超过 10 公里的加价,该用哪个?
A ifB elseC elifD while
if 只管第一段(2 公里内)。
else 是“剩下所有情况”,没法单独表达“超过 10 公里”。
✓ 对!elif 表示“再如果”,多段判断用它。
while 是循环,不是条件判断。
📖 完整思路:多段计费逐级判断:2 公里内 if、超出 elif、超过 10 公里再 elif。
07
字符串索引与遍历 接下来 让电脑问你一句话,再原样还给你——input 和 print 的第一支双人舞。
In [107] 复制
a = input("> ")
豆豆老师小课堂 用 input("> ") 问用户,> 是提示符。
▸
它是怎么实现的 括号里的 "> " 是给用户看的提示,表示“请在这里输入”。
逐行讲解(带注释版代码)
a = input("> ") # 显示 > 提示,等用户输入并回车,存进 a
a = input("> ")显示 > 提示,等用户输入并回车,存进 a
为什么输出是这个 输出 > 2:提示符出现了,用户输入了 2。这里只是演示 input 的用法。
豆豆提醒 老师特别提醒:> 只是提示符,不是要输入的符号,看到它别觉得奇怪。
接下来 把老师的名字 langxm 存进变量 name——字符串变量诞生。
In [2] 复制
name = "langxm"
# str is a sequence of characters
# index start from zero
豆豆老师小课堂 认识字符串:文字是一串字符,每个字符有编号(索引),从 0 开始。
▸
它是怎么实现的 name = "langxm" 共 6 个字母。字符串像一个“座位排”,第 1 个座位编号是 0(不是 1!),这是编程世界的习惯。它叫 string,是一串字符 a sequence of characters;每个字符的编号叫 index(索引),从 0 开始编号。
逐行讲解(带注释版代码)
name = "langxm" # 把文字 'langxm' 存进盒子 name
# str is a sequence of characters
# index start from zero
name = "langxm"把文字 'langxm' 存进盒子 name
# str is a sequence of characters注释:str(字符串)就是一串字符
# index start from zero注释:索引(编号)从 0 开始
接下来 name[0]:取出第一个字符。记住:编号从 0 开始,不是 1!
In [3] 复制
print(name[0])
豆豆老师小课堂 取出字符串的第 0 号字符:name[0]。
▸
它是怎么实现的 方括号 [0] 是“按座位号取人”:name[0] 取第 1 个字符(编号 0)。
逐行讲解(带注释版代码)
print(name[0]) # 打印 name 的 0 号字符
print(name[0])打印 name 的 0 号字符
为什么输出是这个 输出 l:'langxm' 的第 1 个字母是 l。
接下来 name[1]:第二个字符是谁?数一数 langxm 的第 2 个字母。
In [5] 复制
print(name[1])
print(name[2])
print(name[3])
print(name[4])
print(name[5])
豆豆老师小课堂 依次取 1~5 号字符,把每个字母打出来。
▸
它是怎么实现的 name[1] 到 name[5],一个位置一个位置地取。
逐行讲解(带注释版代码)
print(name[1]) # 取 1 号:a
print(name[2]) # 取 2 号:n
print(name[3]) # 取 3 号:g
print(name[4]) # 取 4 号:x
print(name[5]) # 取 5 号:m
print(name[1])取 1 号:a
print(name[2])取 2 号:n
print(name[3])取 3 号:g
print(name[4])取 4 号:x
print(name[5])取 5 号:m
为什么输出是这个 输出 a n g x m:'langxm' 的第 2~6 个字母。
接下来 name[6]:第 7 个字符?先数清楚名字到底有几个字母。
In [6] 复制
print(name[6])
IndexError: string index out of range
---------------------------------------------------------------------------IndexError Traceback (most recent call last)Cell In[6], line 1
----> 1 print(name[6])
IndexError: string index out of range
豆豆老师小课堂 想取 6 号字符,但字符串只有 0~5 号——越界了,报错。
▸
它是怎么实现的 langxm 只有 6 个字符(编号 0-5),name[6] 想取第 7 个,不存在。记住:编号是 0~5,不包含 6——from zero to six exclusive,越界就报 string index out of range。
逐行讲解(带注释版代码)
print(name[6]) # 取 6 号字符——不存在!
print(name[6])取 6 号字符——不存在!
为什么输出是这个 报 IndexError: string index out of range(字符串索引越界)。就像去只有 6 个座位的影院找 7 号座。
接下来 单引号也能存字符串——再练一次中括号取字符。
In [7] 复制
name = 'langxm'
print(len(name))
豆豆老师小课堂 用 len() 数一数字符串有几个字符。
▸
它是怎么实现的 len 是 length(长度)的缩写,像一把“字符数数尺”。
逐行讲解(带注释版代码)
name = 'langxm' # 定义字符串
print(len(name)) # 数一数 name 有几个字符
name = 'langxm'定义字符串
print(len(name))数一数 name 有几个字符
为什么输出是这个 输出 6:'langxm' 有 6 个字母。和索引编号 0~5 对上:编号从 0 到 5,一共 6 个。
接下来 一句话也能一个字一个字取:msg[0] 是什么?
In [8] 复制
msg = "very good"
print(len(msg))
豆豆老师小课堂 数一数带空格的字符串长度。
▸
它是怎么实现的 len 会连空格一起数——空格也是一个字符。老师说过:because space is a valid character,空格是合法字符,所以 'very good' 的长度是 9。
逐行讲解(带注释版代码)
msg = "very good" # 定义字符串 'very good'
print(len(msg)) # 数长度
msg = "very good"定义字符串 'very good'
print(len(msg))数长度
为什么输出是这个 输出 9:very(4) + 空格(1) + good(4) = 9。空格也算一个字符!
接下来 越界了会怎样?先猜,再看 Python 的报错长什么样。
In [9] 复制
name = "langxm"
print(name[0])
print(name[1])
print(name[2])
print(name[3])
print(name[4])
print(name[5])
豆豆老师小课堂 复习:用索引把 'langxm' 的每个字母依次打印。
▸
它是怎么实现的 手写 6 行 print,把 0~5 号都取一遍。可要是字符串有 1 万个字符,手写 1 万行显然不现实——想想怎么用循环?
逐行讲解(带注释版代码)
name = "langxm" # 定义字符串
print(name[0]) # 打印 0 号 l
print(name[1]) # 打印 1 号 a
print(name[2]) # 打印 2 号 n
print(name[3]) # 打印 3 号 g
print(name[4]) # 打印 4 号 x
print(name[5]) # 打印 5 号 m
name = "langxm"定义字符串
print(name[0])打印 0 号 l
print(name[1])打印 1 号 a
print(name[2])打印 2 号 n
print(name[3])打印 3 号 g
print(name[4])打印 4 号 x
print(name[5])打印 5 号 m
为什么输出是这个 输出 l a n g x m,拼起来就是 langxm。
接下来 再往深处取一次:超出长度的编号,会得到什么?
In [11] 复制
name = "langxm"
i = 0
while i < len(name):
print(name[i])
i += 1
豆豆老师小课堂 用 while 循环自动遍历字符串,不用手写 6 行。
▸
它是怎么实现的 i 从 0 开始,i < len(name)(6),每次打印 name[i] 再 i += 1。循环替我们完成了 6 次取字符。
逐行讲解(带注释版代码)
name = "langxm" # 定义字符串
i = 0 # 计数器从 0 开始
while i < len(name): # 只要 i 小于长度(6)就循环
print(name[i]) # 打印第 i 号字符
i += 1 # i 加 1,取下一个
name = "langxm"定义字符串
i = 0计数器从 0 开始
while i < len(name):只要 i 小于长度(6)就循环
print(name[i])打印第 i 号字符
i += 1i 加 1,取下一个
为什么输出是这个 输出 l a n g x m:循环 6 次,把每个字母都打了一遍。
接下来 '*' × 10:用乘法快速画一条星号线——字符串乘法的妙用。
In [12] 复制
"*" * 10
豆豆老师小课堂 用乘号把一颗星变成 10 颗星。
▸
它是怎么实现的 字符串 * 数字 = 把字符串重复写 N 遍。"*" * 10 就是 10 颗星。
逐行讲解(带注释版代码)
"*" * 10 # 把 '*' 重复写 10 遍
为什么输出是这个 输出 '**********':10 颗星。这是“字符串复印机”的又一次登场。
接下来 'abc ' × 4:一段文字复制 4 遍,看到规律了吗?
In [13] 复制
"abc " * 4
豆豆老师小课堂 把 'abc ' 重复 4 遍。
▸
它是怎么实现的 同样用 * 复印:'abc ' 带一个空格,重复 4 次。
逐行讲解(带注释版代码)
"abc " * 4 # 把 'abc ' 重复写 4 遍
"abc " * 4把 'abc ' 重复写 4 遍
为什么输出是这个 输出 'abc abc abc abc ':4 遍 'abc ' 连在一起。
接下来 字符串加法:把名字和其他文字拼成一句完整的话。
In [14] 复制
name = "langxm"
i = 0
rst = ""
while i < len(name):
print(name[i])
i += 1
print(rst)
# llaannggxxmm
豆豆老师小课堂 想做一个“重复字母”的字符串,但循环里只打印、没往 rst 里加,结果 rst 还是空的。
▸
它是怎么实现的 rst = "" 是准备好的“空篮子”,但循环体里只有 print(name[i]),忘了写 rst = rst + ...。篮子一直是空的。
逐行讲解(带注释版代码)
name = "langxm" # 定义字符串
i = 0 # 计数器
rst = "" # 准备空篮子 rst
while i < len(name): # 循环 6 次
print(name[i]) # 只打印了字符——忘了加进 rst!
i += 1 # i 加 1
print(rst) # 打印篮子
# llaannggxxmm
name = "langxm"定义字符串
i = 0计数器
rst = ""准备空篮子 rst
while i < len(name):循环 6 次
print(name[i])只打印了字符——忘了加进 rst!
i += 1i 加 1
print(rst)打印篮子
# llaannggxxmm注释:本来想要的理想结果
为什么输出是这个 打印了 l a n g x m,然后输出空行:因为 rst 从来没被加过东西。
接下来 'a' + 'a' 等于什么?先猜——文字加文字是拼接,不是数学。
In [15] 复制
"a" + "a"
豆豆老师小课堂 两个文字相加:'a' + 'a'。
▸
它是怎么实现的 文字的 + 是拼接:把两串文字接在一起。
逐行讲解(带注释版代码)
"a" + "a" # 把 'a' 和 'a' 拼接
接下来 拼接升级:用变量拼句子,顺便看看空格怎么加。
In [17] 复制
name = "langxm"
i = 0
rst = ""
while i < len(name):
rst = rst + name[i] + name[i]
i += 1
print(rst)
# llaannggxxmm
豆豆老师小课堂 真正实现“每个字母写两遍”:rst = rst + name[i] + name[i]。
▸
它是怎么实现的 循环里每次把当前字符加两遍进篮子:第一次 i=0 时 rst=''+'l'+'l'='ll',第二次 'lla'... 一点点长大。
逐行讲解(带注释版代码)
name = "langxm" # 定义字符串
i = 0 # 计数器
rst = "" # 空篮子
while i < len(name): # 循环 6 次
rst = rst + name[i] + name[i] # 把当前字符加两遍进篮子
i += 1 # i 加 1
print(rst) # 打印篮子
# llaannggxxmm
name = "langxm"定义字符串
i = 0计数器
rst = ""空篮子
while i < len(name):循环 6 次
rst = rst + name[i] + name[i]把当前字符加两遍进篮子
i += 1i 加 1
print(rst)打印篮子
# llaannggxxmm注释:预期结果
为什么输出是这个 输出 llaannggxxmm:每个字母都写了 2 遍。
接下来 把名字复制成两遍:字符串 × 2 的小魔法。
In [18] 复制
name = "langxm"
i = 0
rst = ""
while i < len(name):
rst = rst + name[i] + name[i] + name[i]
i += 1
print(rst)
# llaannggxxmm
豆豆老师小课堂 每个字母写 3 遍。
▸
它是怎么实现的 把加号里的 name[i] 多写一个:rst + name[i] + name[i] + name[i]。
逐行讲解(带注释版代码)
name = "langxm" # 定义字符串
i = 0 # 计数器
rst = "" # 空篮子
while i < len(name): # 循环
rst = rst + name[i] + name[i] + name[i] # 每个字符加 3 遍
i += 1 # i 加 1
print(rst) # 打印
# llaannggxxmm
name = "langxm"定义字符串
i = 0计数器
rst = ""空篮子
while i < len(name):循环
rst = rst + name[i] + name[i] + name[i]每个字符加 3 遍
i += 1i 加 1
print(rst)打印
# llaannggxxmm注释
为什么输出是这个 输出 lllaaannngggxxxmmm:每个字母 3 遍。
接下来 复制三遍呢?乘法的数字想写几就写几。
In [20] 复制
name = "langxm"
i = 0
rst = ""
while i < len(name):
rst = rst + name[i] * 4
i += 1
print(rst)
# llaannggxxmm
豆豆老师小课堂 用乘法简写:name[i] * 4,每个字母写 4 遍。
▸
它是怎么实现的 之前的写法是“加 4 遍”,这里直接用 * 4,更简洁。
逐行讲解(带注释版代码)
name = "langxm" # 定义字符串
i = 0 # 计数器
rst = "" # 空篮子
while i < len(name): # 循环
rst = rst + name[i] * 4 # 当前字符复印 4 遍加进篮子
i += 1 # i 加 1
print(rst) # 打印
# llaannggxxmm
name = "langxm"定义字符串
i = 0计数器
rst = ""空篮子
while i < len(name):循环
rst = rst + name[i] * 4当前字符复印 4 遍加进篮子
i += 1i 加 1
print(rst)打印
# llaannggxxmm注释
为什么输出是这个 输出 llllaaaannnnggggxxxxmmmm:每个字母 4 遍。
接下来 拼接练习收尾:加法拼接 vs 乘法复制,你分得清吗?
In [ ] 复制
name = "langxm"
i = 0
rst = ""
while i < len(name):
# rst = rst + name[i] * 4
i += 1
print(rst)
# mxgnal
豆豆老师小课堂 把“加字母”的那行注释掉了,循环空转,rst 是空的。
▸
它是怎么实现的 rst = rst + name[i] * 4 被 # 注释掉,循环体里什么都不做,篮子永远是空的。注释里写的 mxgnal 是老师想要的方向(反转),但代码还没实现。
逐行讲解(带注释版代码)
name = "langxm" # 定义字符串
i = 0 # 计数器
rst = "" # 空篮子
while i < len(name): # 循环 6 次
# rst = rst + name[i] * 4
i += 1 # 只有计数在动
print(rst) # 打印篮子
# mxgnal
name = "langxm"定义字符串
i = 0计数器
rst = ""空篮子
while i < len(name):循环 6 次
# rst = rst + name[i] * 4这一行被注释掉了——没执行
i += 1只有计数在动
print(rst)打印篮子
# mxgnal注释:真正想要的是反转字符串 mxgnal
为什么输出是这个 输出空行:因为往篮子里加东西的代码被注释掉了。
接下来 while 遍历你的名字:i 是索引,从 0 数到最后一个字符。
In [21] 复制
name = "arianna"
print(name[-1])
print(name[-2])
print(name[-3])
print(name[-4])
print(name[-5])
print(name[-6])
豆豆老师小课堂 用负数索引:从右往左数。-1 是最后一个字符。
▸
它是怎么实现的 负数索引是从字符串“尾巴”往前数:-1 是最后一位,-2 是倒数第二……不过 -1 有个小陷阱:它既是“倒数第一个”,又常被用来表示“没找到”,遇到时要分清。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串(7 个字母)
print(name[-1]) # -1:最后一个,a
print(name[-2]) # -2:倒数第二,n
print(name[-3]) # -3:n
print(name[-4]) # -4:a
print(name[-5]) # -5:i
print(name[-6]) # -6:r
name = "arianna"定义字符串(7 个字母)
print(name[-1])-1:最后一个,a
print(name[-2])-2:倒数第二,n
print(name[-3])-3:n
print(name[-4])-4:a
print(name[-5])-5:i
print(name[-6])-6:r
为什么输出是这个 输出 a n n a i r:从尾巴往头数。arianna 倒着数前 6 位。
接下来 遍历名字——小心!循环体里别忘了 i += 1,否则会死循环。
In [22] 复制
i = 0
while i < len(name):
print(name[i])
i += 1
豆豆老师小课堂 用 while 遍历 name,把每个字符打印出来。
▸
它是怎么实现的 name 还是上一课的 'arianna'(变量在会话里保留着)。用 while + 索引遍历。循环体里别忘了让计数器前进:课堂上就有人写完 while 忘了写 i += 1,程序直接卡死——这就是死循环(infinite loop)。
逐行讲解(带注释版代码)
i = 0 # 计数器从 0 开始
while i < len(name): # i 小于长度 7 就循环
print(name[i]) # 打印第 i 号字符
i += 1 # i 加 1
i = 0计数器从 0 开始
while i < len(name):i 小于长度 7 就循环
print(name[i])打印第 i 号字符
i += 1i 加 1
为什么输出是这个 输出 a r i a n n a:'arianna' 的每个字母。注意 name 是之前 cell 里留下的。
接下来 更简单的遍历:for 循环直接“把每个字符拿过来”,不用管索引。
In [23] 复制
for ch in name:
print(ch)
豆豆老师小课堂 用 for 循环直接遍历:for ch in name,一个字符一个字符拿。
▸
它是怎么实现的 for ch in name 的意思是“把 name 里的字符按顺序一个一个放进 ch”。有没有更简单的方法?有——for 循环直接“把每个字符拿过来”,连下标都不用自己数。
逐行讲解(带注释版代码)
for ch in name: # 把 name 的每个字符依次放进 ch
print(ch) # 打印 ch
for ch in name:把 name 的每个字符依次放进 ch
print(ch)打印 ch
为什么输出是这个 输出 a r i a n n a:for 循环自动取完所有字符。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. 下面代码会输出什么?
for ch in 'ab':
print(ch)
A abB 'a' 'b'C a
bD a b
ab 是连在一起,但 print 每次都会换行。
'a' 'b' 带引号是列表写法,print 输出字符不带引号。
✓ 对!ch 依次是 a、b,每次 print 换行:a\nb。
print 默认不输出空格。
📖 完整思路:for 循环每次拿一个字符打印,print 默认换行:a、b 各占一行。
2. for ch in 'ab': 循环会执行几次?
A 1 次B 2 次C 3 次D 无限次
两个字符要各处理一次,1 次不够。
✓ 对!'ab' 有两个字符,循环 2 次。
3 次多算了,这里只有 2 个字符。
for 循环会自己数完,不会无限。
📖 完整思路:'ab' 有两个字符,for 循环按字符个数执行:2 次。
接下来 for 循环再试:这次把每个字符原样打印出来。
In [24] 复制
name = "arianna"
for i in range(len(name)):
print(i)
豆豆老师小课堂 用 range(len(name)) 生成 0~6 的编号,打印编号。
▸
它是怎么实现的 range(n) 会生成 0,1,2,...,n-1 这一串数。range(len(name)) 就是 0~6。课堂上演示过:先打印 i 得到 0123456,再打印 name[i] 得到的就是字符串本身。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串
for i in range(len(name)): # i 依次等于 0~6
print(i) # 打印编号
name = "arianna"定义字符串
for i in range(len(name)):i 依次等于 0~6
print(i)打印编号
为什么输出是这个 输出 0 1 2 3 4 5 6:字符串有 7 个字符,编号 0~6。
接下来 两个遍历对比:while 和 for,谁更省心?
In [25] 复制
name = "arianna"
for i in range(len(name)):
print(name[i])a
豆豆老师小课堂 用编号取字符打印:print(name[i])。注意这行末尾多了一个字母 a(打字误触)。
▸
它是怎么实现的 本意是打印每个字符。缓存里的运行记录是正常版本的结果。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串
for i in range(len(name)): # i 取 0~6
print(name[i])a # 打印第 i 号字符——小心!末尾多了个 a,重跑会语法报错
name = "arianna"定义字符串
for i in range(len(name)):i 取 0~6
print(name[i])a打印第 i 号字符——小心!末尾多了个 a,重跑会语法报错
为什么输出是这个 缓存输出 a r i a n n a(旧运行结果)。如果现在重新运行,print(...)a 会报 SyntaxError。这正是课堂想展示的“手滑陷阱”。
豆豆提醒 print(...) 括号外面不能乱加字母。
接下来 用 range(len(name)) 拿到索引,再按索引取字符——两种工具都能用。
In [27] 复制
name = "arianna"
for i in range(0, len(name)):
print(i, name[i])
0 a
1 r
2 i
3 a
4 n
5 n
6 a
豆豆老师小课堂 同时打印编号和对应字符:print(i, name[i])。
▸
它是怎么实现的 print 里用逗号隔开,一次打印两样东西(中间自动有空格)。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串
for i in range(0, len(name)): # range(0,7) = 0~6
print(i, name[i]) # 打印编号和字符
name = "arianna"定义字符串
for i in range(0, len(name)):range(0,7) = 0~6
print(i, name[i])打印编号和字符
为什么输出是这个 输出 0 a / 1 r / 2 i / 3 a / 4 n / 5 n / 6 a:每个字符都标上了座位号。
接下来 倒着遍历:从最后一个字符往前取,想想怎么改循环。
In [28] 复制
name = "arianna"
for i in range(0, len(name), 2):
print(i, name[i])
豆豆老师小课堂 range 加第三个参数 2:隔一个取一个(步长 2)。
▸
它是怎么实现的 range(0, 7, 2) 从 0 开始,每次跳 2:0、2、4、6。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串
for i in range(0, len(name), 2): # i = 0,2,4,6(步长 2)
print(i, name[i]) # 打印
name = "arianna"定义字符串
for i in range(0, len(name), 2):i = 0,2,4,6(步长 2)
print(i, name[i])打印
为什么输出是这个 输出 0 a / 2 i / 4 n / 6 a:只取了偶数座位。
接下来 步长 -1:range 从后往前数,字符串就反过来了。
In [29] 复制
name = "arianna"
for i in range(1, len(name), 2):
print(i, name[i])
豆豆老师小课堂 从 1 开始、步长 2:取奇数座位。
▸
它是怎么实现的 range(1, 7, 2) = 1、3、5。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串
for i in range(1, len(name), 2): # i = 1,3,5
print(i, name[i]) # 打印
name = "arianna"定义字符串
for i in range(1, len(name), 2):i = 1,3,5
print(i, name[i])打印
为什么输出是这个 输出 1 r / 3 a / 5 n:只取了奇数座位。
接下来 倒序完整版:name[::-1] 一步搞定,或者用循环慢慢来。
In [32] 复制
name = "arianna"
for i in range(len(name)-1, 0, -2):
print(i, name[i])
豆豆老师小课堂 倒着数:从 6 开始,每次减 2,到 1 为止(不取 0)。
▸
它是怎么实现的 range(len(name)-1, 0, -2) 从 6 开始,步长 -2(往后跳),到 0 之前停下:6、4、2。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串
for i in range(len(name)-1, 0, -2): # i = 6,4,2(倒着跳 2)
print(i, name[i]) # 打印
name = "arianna"定义字符串
for i in range(len(name)-1, 0, -2):i = 6,4,2(倒着跳 2)
print(i, name[i])打印
为什么输出是这个 输出 6 a / 4 n / 2 i:从尾巴往头,隔一个取一个,且不到 0 号。
接下来 遍历综合练习:把名字拆成一个个字母排排站。
In [33] 复制
name = "arianna"
for i in range(len(name)-1, 0, -1):
print(i, name[i])
豆豆老师小课堂 从 6 到 1 倒着走,每步减 1。
▸
它是怎么实现的 range(6, 0, -1) = 6,5,4,3,2,1。注意不包含 0。
逐行讲解(带注释版代码)
name = "arianna" # 定义字符串
for i in range(len(name)-1, 0, -1): # i = 6,5,4,3,2,1
print(i, name[i]) # 打印
name = "arianna"定义字符串
for i in range(len(name)-1, 0, -1):i = 6,5,4,3,2,1
print(i, name[i])打印
为什么输出是这个 输出 6 a / 5 n / 4 n / 3 a / 2 i / 1 r:从尾到第 2 个字符。
接下来 字符串小练习收尾:'abc' 里的索引和长度,再数一遍。
In [34] 复制
"abc"
"bcd"
豆豆老师小课堂 一个 cell 里写了两行表达式,Jupyter 只显示最后一行的结果。
▸
它是怎么实现的 'abc' 先被算出来,但没显示;紧接着 'bcd' 是最后一个表达式,被显示出来。
逐行讲解(带注释版代码)
"abc" # 表达式 1——算出来了但没显示
"bcd" # 表达式 2——最后一个,被显示
"abc"表达式 1——算出来了但没显示
"bcd"表达式 2——最后一个,被显示
为什么输出是这个 输出 'bcd':Jupyter 只显示最后一个表达式的值。
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 索引为什么从 0 开始?
计算机数数从 0 开始(就像 while 循环的计数器)。name[0] 是第一个字符,name[6] 是第 7 个。这和你的计数器习惯一致,别弄混。
📌 课堂重点
💬 空格算字符吗?
算!len('a b') 是 3,不是 2。空格是合法字符,索引也要给它留位置。课堂上专门讲过这一点。
📌 来自课堂
💬 访问 name[99] 会怎样?
会报错:IndexError: string index out of range(索引超出范围)。字符串多长,索引最大就是 长度-1。
📌 课堂真实报错
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. name = 'langxm',name[0] 是?
A 'l'B 'a'C 报错D 'n'
✓ 对!索引从 0 开始,name[0] 是第一个字符 l。
a 是第二个字符,应该是 name[1]。
索引 0 完全合法,不会报错。
n 是第三个字符,在 name[2]。
📖 完整思路:索引从 0 开始,name[0] 是第一个字符 l。
2. len('a b') 等于?
A 2B 3C 4D 报错
2 漏掉了中间的空格,空格也是字符。
✓ 对!a + 空格 + b = 3 个字符。
4 个就数多了,这里只有 3 个字符。
len 对字符串完全合法,不会报错。
📖 完整思路:空格也是合法字符,'a b' 有三个字符:a、空格、b。
3. 访问 name[99](name 只有 6 个字符)会?
A 返回空B 返回最后一个字符C 报 IndexErrorD 自动循环
不会返回空,Python 直接报错。
最后一个字符是 name[5],不是 name[99]。
✓ 对!索引超界报 IndexError。
Python 不会自动绕回开头。
📖 完整思路:索引超出范围,Python 报 IndexError: string index out of range。
08
凯撒加密 接下来 凯撒加密开场:把明文 arianna 变成密文——先认识“加密”这个词。
In [36] 复制
name = "arianna" # plain text
secret = "" # encrpyt secret
for ch in name:
print(ch)
豆豆老师小课堂 凯撒加密的准备:先把名字的每个字母打印出来。
▸
它是怎么实现的 name 是“明文”(plain text),secret 是准备好的“密文篮子”(现在为空)。先遍历打印,看看每个字母。凯撒加密就是不想让别人偷听:把信息加密,好比加了个保险箱;加密解密用同一把钥匙,叫对称加密(symmetric encryption)。还有更高级的“功德箱”:谁都能往里投钱,只有和尚能取出来——加密用 public key(公钥),解开要用 private key(私钥),这叫非对称加密(asymmetric encryption)。
逐行讲解(带注释版代码)
name = "arianna" # plain text # 明文名字;# 注释:plain text 明文
secret = "" # encrpyt secret # 密文篮子 secret 先空着;# 注释:加密密文
for ch in name: # 遍历每个字符
print(ch) # 先打印看看
name = "arianna" # plain text明文名字;# 注释:plain text 明文
secret = "" # encrpyt secret密文篮子 secret 先空着;# 注释:加密密文
for ch in name:遍历每个字符
print(ch)先打印看看
为什么输出是这个 输出 a r i a n n a:先观察每个字母,为加密做准备。
接下来 认识 ord:字符 → 编号。字母在电脑里其实都是一个数字。
In [37] 复制
# letter -> ascii code
ord('a')
豆豆老师小课堂 认识 ord():把字母翻译成电脑用的编号(ASCII 码)。
▸
它是怎么实现的 ord 是“字母→数字”的翻译官。电脑内部其实用数字记字母:'a' 是 97。每个符号都有对应编号——小写 a 是 97,大写 A 是 65,就像老师给每个同学编一个号。
逐行讲解(带注释版代码)
# letter -> ascii code
ord('a') # 把 'a' 翻译成数字
# letter -> ascii code注释:字母 → ASCII 码
ord('a')把 'a' 翻译成数字
为什么输出是这个 输出 97:字母 a 在电脑里的编号是 97。
接下来 认识 chr:编号 → 字符。ord 和 chr 是一对互逆的“翻译机”。
In [41] 复制
# ascii code -> letter
chr(97) # character
豆豆老师小课堂 认识 chr():把编号翻译回字母。
▸
它是怎么实现的 chr 是“数字→字母”的翻译官,和 ord 正好相反。chr 是 character(字符)的缩写,把数字翻译回字母;ord 和 chr 是互逆的两个翻译官。
逐行讲解(带注释版代码)
# ascii code -> letter
chr(97) # character # 把 97 翻译回字母
# ascii code -> letter注释:ASCII 码 → 字母
chr(97) # character把 97 翻译回字母
为什么输出是这个 输出 'a':97 对应的字母就是 a。
接下来 查一查:a 的编号是多少?记住这个数字,后面有大用。
In [42] 复制
asc_a = ord('a')
asc_b = asc_a + 1
chr(asc_b)
豆豆老师小课堂 组合使用:拿到 'a' 的编号,加 1,再变回字母,得到 b。
▸
它是怎么实现的 这是“移位”的雏形:asc_a = 97,asc_b = 98,chr(98) = 'b'。向后移 1 位。
逐行讲解(带注释版代码)
asc_a = ord('a') # a 的编号 97
asc_b = asc_a + 1 # 加 1:98
chr(asc_b) # 翻译回字母
asc_a = ord('a')a 的编号 97
asc_b = asc_a + 1加 1:98
chr(asc_b)翻译回字母
为什么输出是这个 输出 'b':97+1=98 → b。字母往后挪了 1 格。
接下来 再看一眼 97——这就是小写字母 a 的“身份证号”。
In [43] 复制
asc_a = ord('a')
asc_b = asc_a + 3
chr(asc_b)
豆豆老师小课堂 加 3:往后挪 3 格,a 变成 d。
▸
它是怎么实现的 和上个 cell 一样,只是 +1 改成 +3。每个字母都有对应的编号,小写 a 是 97——就像给每个同学编一个号,电脑按编号找字符。
逐行讲解(带注释版代码)
asc_a = ord('a') # 97
asc_b = asc_a + 3 # 加 3:100
chr(asc_b) # 翻译回字母
asc_a = ord('a')97
asc_b = asc_a + 3加 3:100
chr(asc_b)翻译回字母
为什么输出是这个 输出 'd':100 对应 d。向后移 3 格。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. ord('b') 的结果是?
A 97B 98C 99D 66
97 是 a 的编号。
✓ 对!a=97, b=98, c=99……
99 是 c 的编号。
66 是大写 B 的编号。
📖 完整思路:a=97,b 是下一个:98。字母编号一个个往下排。
2. ord('a') + 3 然后 chr() 变回,得到?
A 'c'B 'd'C 'a3'D 报错
c 是挪 2 格(97+2=99)。
✓ 对!97+3=100,chr(100)='d',往后 3 格。
'a3' 是把数字当字符拼,chr 是编号变字符。
ord 和 chr 用法合法,不会报错。
📖 完整思路:97 + 3 = 100,chr(100) = 'd'。往后挪 3 格。
接下来 终极任务:把 arianna 每个字母往后挪 3 格。先想清楚四步:取字母→变编号→挪→变回。
In [44] 复制
name = "arianna" # plain text
secret = "" # encrpyt secret
for ch in name:
asc = ord(ch)
encrypt = chr(asc + 3)
secret += encrypt
print(secret)
豆豆老师小课堂 完整的凯撒加密:把名字的每个字母都往后挪 3 格。
▸
先想一想(任务说明) 终极任务:把名字 arianna 加密——每个字母往后挪 3 格(a 变成 d)。先想清楚“加密”要分几步:拿到一个字母 → 变成编号 → 挪 3 格 → 变回字母。可名字有 7 个字母,难道写 7 遍?别忘了你学过 for 循环——它天生就是“对每个字符做同一件事”的。先自己写一遍,再对比下面的答案。
它是怎么实现的 遍历 name 的每个字符:ord 变数字 → 加 3 → chr 变回字母 → 加进 secret。循环结束打印 secret。加密流程记住四步:依次访问每个字符 → 取它的 ascii 码 → 加上偏移量 → 转回字母拼进 secret。往后挪没问题,但挪到 z 再往后会“跑出字母表”,怎么绕回来?下一节讲。
逐行讲解(带注释版代码)
name = "arianna" # plain text # 明文
secret = "" # encrpyt secret # 密文篮子
for ch in name: # 遍历每个字符
asc = ord(ch) # 变成编号
encrypt = chr(asc + 3) # 加 3 再变回字母(加密)
secret += encrypt # 把加密结果加进篮子
print(secret) # 打印密文
name = "arianna" # plain text明文
secret = "" # encrpyt secret密文篮子
for ch in name:遍历每个字符
asc = ord(ch)变成编号
encrypt = chr(asc + 3)加 3 再变回字母(加密)
secret += encrypt把加密结果加进篮子
print(secret)打印密文
为什么输出是这个 输出 duldqqd:a→d、r→u、i→l、a→d、n→q、n→q、a→d。每个字母都往后挪了 3 格。
接下来 难题登场:xyz 往后挪会“跑出字母表”,怎么让它绕回开头?
In [45] 复制
name = "xyz" # plain text
secret = "" # encrpyt secret
for ch in name:
asc = ord(ch)
encrypt = chr(asc + 3)
secret += encrypt
print(secret)
豆豆老师小课堂 同样的加密,但明文是 xyz——问题出现了!
▸
它是怎么实现的 x+3 会超出 z(122),变成符号,而不是绕回 a。这暴露了凯撒加密的“边界问题”。
逐行讲解(带注释版代码)
name = "xyz" # plain text # 明文 xyz
secret = "" # encrpyt secret # 密文篮子
for ch in name: # 遍历
asc = ord(ch) # 编号:x=120, y=121, z=122
encrypt = chr(asc + 3) # 加 3:123、124、125——变成 { | }
secret += encrypt # 加进篮子
print(secret) # 打印
name = "xyz" # plain text明文 xyz
secret = "" # encrpyt secret密文篮子
for ch in name:遍历
asc = ord(ch)编号:x=120, y=121, z=122
encrypt = chr(asc + 3)加 3:123、124、125——变成 { | }
secret += encrypt加进篮子
print(secret)打印
为什么输出是这个 输出 {|}:x→{、y→|、z→}。字母表走完了,变成符号,没有绕回 a。接下来要修这个 bug。
接下来 先确认边界:97 + 25 正好是 z 的编号。
In [46] 复制
chr(97 + 25)
豆豆老师小课堂 验证:97 + 25 = 122,正是 z 的编号。
▸
它是怎么实现的 字母表从 a(97) 到 z(122) 一共 26 个字母,最后一个 z 的编号是 122。
逐行讲解(带注释版代码)
chr(97 + 25) # 97+25=122,翻译回字母
chr(97 + 25)97+25=122,翻译回字母
为什么输出是这个 输出 'z':122 对应 z。说明 a~z 占编号 97~122。
接下来 取模运算:超过 122 就绕回开头——% 是“除法剩多少”的魔法符号。
In [49] 复制
(97 + 25 + 3) % (97 + 25)
豆豆老师小课堂 用取余 % 解决“绕圈”:122+3 在 122 的圈里余数是 3。
▸
它是怎么实现的 (97+25+3) % (97+25) 就是 125 % 122 = 3。取余让数字绕回起点。
逐行讲解(带注释版代码)
(97 + 25 + 3) % (97 + 25) # 125 % 122
(97 + 25 + 3) % (97 + 25)125 % 122
为什么输出是这个 输出 3:超过 122 的部分被“剪掉”,只剩 3。这就是绕圈的数学基础。
接下来 绕圈公式拆开第一步:97 + (超过的部分) 是什么?
In [50] 复制
97 + (97 + 25 + 3) % (97 + 25)
豆豆老师小课堂 在 a 的编号上加上余数:97 + 3 = 100。
▸
它是怎么实现的 97 + (125 % 122) = 97 + 3 = 100,也就是 d 的编号。
逐行讲解(带注释版代码)
97 + (97 + 25 + 3) % (97 + 25) # 97 + 3 = 100
97 + (97 + 25 + 3) % (97 + 25)97 + 3 = 100
接下来 把绕圈后的编号变回字符:chr 登场收尾。
In [51] 复制
chr(97 + (97 + 25 + 3) % (97 + 25))
豆豆老师小课堂 把 100 翻译回字母:d。
▸
它是怎么实现的 chr(100) = 'd'。整体公式:chr(97 + (122+3) % 122)。
逐行讲解(带注释版代码)
chr(97 + (97 + 25 + 3) % (97 + 25)) # chr(100)
chr(97 + (97 + 25 + 3) % (97 + 25))chr(100)
为什么输出是这个 输出 'd':绕圈公式成功——z+3 会变成 c(绕回),这里是演示 a 的常规情况。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. (97 + 25 + 3) % (97 + 25) 等于?
A 3B 125C 122D 0
✓ 对!125 除 122 剩 3,超出的部分就是 3。
125 是取模前的总数,取模后只剩余数。
122 是除数,不是结果。
125 不是 122 的整数倍,余数不是 0。
📖 完整思路:125 ÷ 122 余 3。这就是“超出部分绕回开头”的取模。
2. chr(97 + 3) 得到?
A 'c'B 'd'C 'a'D 报错
c 是 99(97+2)。
✓ 对!a→b→c→d,3 格后是 d。
a 是 97(0 格)。
chr 接收 100 合法,不会报错。
📖 完整思路:97+3=100,chr(100)='d'(a=97 往后数 3 格)。
接下来 再算一遍边界:97 + 25 = 122,这就是字母表的上限。
In [52] 复制
97 + 25
豆豆老师小课堂 再确认:97 + 25 = 122。
▸
它是怎么实现的 就是 z 的编号,为下面的完整加密做铺垫。
逐行讲解(带注释版代码)
97 + 25 # 122
接下来 通用加密:step 想移几位就移几位。先画一画绕圈的思路,再看代码。
In [54] 复制
step = 5
z = 122
ch = 'a'
rst_asc = ord(ch) + step
if rst_asc >= z:
rst_asc = ord('a') + rst_asc % z
print(rst_asc, chr(rst_asc))
豆豆老师小课堂 完整版凯撒加密:step=5,ch='a',用 if 处理越界。
▸
先想一想(任务说明) 新问题:如果挪到 z 还要往后走怎么办?比如 'x' 往后挪 5 格,就“跑出字母表”了。想一想:怎么让它绕回 a 重新数?(提示:把编号对 26 取余数,或者设定边界 z,超了就往回绕。)先画一画绕圈的思路,再看代码怎么处理。
它是怎么实现的 rst_asc = ord(ch) + step = 97+5=102。if rst_asc >= z(122) 不成立(102 < 122),所以不用绕圈。102 对应 f。
逐行讲解(带注释版代码)
step = 5 # 加密步长:往后挪 5 格
z = 122 # z 的编号,当作边界
ch = 'a' # 要加密的字母
rst_asc = ord(ch) + step # 编号 + 步长:97+5=102
if rst_asc >= z: # 如果超过了 z 的编号
rst_asc = ord('a') + rst_asc % z # 绕回 a 重新数(这里没触发)
print(rst_asc, chr(rst_asc)) # 打印编号和加密后的字母
step = 5加密步长:往后挪 5 格
z = 122z 的编号,当作边界
ch = 'a'要加密的字母
rst_asc = ord(ch) + step编号 + 步长:97+5=102
if rst_asc >= z:如果超过了 z 的编号
rst_asc = ord('a') + rst_asc % z绕回 a 重新数(这里没触发)
print(rst_asc, chr(rst_asc))打印编号和加密后的字母
为什么输出是这个 输出 102 f:a 往后挪 5 格变成 f。没有越界,if 没触发。
接下来 step = 5:把变量名起成 step(步长),代码立刻“会说话”了。
In [62] 复制
step = 5
z = 122
ch = 'x'
rst_asc = ord(ch) + step
if rst_asc >= z:
rst_asc = ord('a') + rst_asc % z - 1
print(rst_asc, chr(rst_asc))
# abcd....xyz
豆豆老师小课堂 ch='x',x+5 越界了,if 触发绕圈。
▸
它是怎么实现的 rst_asc = 120+5 = 125 ≥ 122,进入 if:rst_asc = 97 + 125%122 - 1 = 97+3-1 = 99。99 对应 c。
逐行讲解(带注释版代码)
step = 5 # 步长 5
z = 122 # 边界
ch = 'x' # x 的编号是 120
rst_asc = ord(ch) + step # 120+5=125,超过 122!
if rst_asc >= z: # 条件成立,进入绕圈
rst_asc = ord('a') + rst_asc % z - 1 # 97 + 125%122 - 1 = 97+3-1 = 99
print(rst_asc, chr(rst_asc)) # 打印
# abcd....xyz
step = 5步长 5
z = 122边界
ch = 'x'x 的编号是 120
rst_asc = ord(ch) + step120+5=125,超过 122!
if rst_asc >= z:条件成立,进入绕圈
rst_asc = ord('a') + rst_asc % z - 197 + 125%122 - 1 = 97+3-1 = 99
print(rst_asc, chr(rst_asc))打印
# abcd....xyz注释:字母表
为什么输出是这个 输出 99 c:x 往后挪 5 格,绕回字母表开头,变成 c(x→y→z→a→b→c)。
接下来 先算数字:x 的编号加 5 等于多少?
In [58] 复制
ord('x') + 5
豆豆老师小课堂 单独看:x 的编号加 5。
▸
它是怎么实现的 ord('x') = 120,+5 = 125。
逐行讲解(带注释版代码)
ord('x') + 5 # 120 + 5
接下来 对 122 取模:看看超出部分怎么绕圈。
In [59] 复制
(ord('x') + 5) % 122
豆豆老师小课堂 125 对 122 取余。
▸
它是怎么实现的 125 % 122 = 3:超出部分。
逐行讲解(带注释版代码)
(ord('x') + 5) % 122 # 125 % 122
(ord('x') + 5) % 122125 % 122
接下来 最后的修正:为什么是 97 + 3 - 1?数一数 yzabc 就明白了。
In [61] 复制
chr(97 + 3 - 1)
豆豆老师小课堂 为什么 cell 109 里是 -1:97 + 3 - 1 = 99。
▸
它是怎么实现的 这个 cell 验证 97+3-1 = 99 对应 c,帮助理解绕圈公式里那个 -1 的作用。
逐行讲解(带注释版代码)
chr(97 + 3 - 1) # chr(99)
为什么输出是这个 输出 'c':99 对应 c。绕圈公式里 -1 是为了让 z 后的字母正好从 a 重新开始。
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 ord 和 chr 老是记反,怎么办?
用英文记:ord = order(顺序/编号),字符 → 编号;chr = character(字符),编号 → 字符。课堂上学生说“没理解”“需要反应一会儿”,就用“给每个同学编号”的例子讲通了。
📌 来自课堂:学生真实困惑
💬 加密时超过 z 怎么办?
绕圈!超过 122 就对 122 取模再减 1,加上 97 回到 a。课堂上 x+5 变成 d 就是绕圈的结果。刚开始觉得绕没关系,先会用,再慢慢想数学。
📌 来自课堂:真实难点
💬 凯撒加密为什么叫“对称加密”?
因为加密和解密用同一把“钥匙”(同一个偏移量)。像保险箱,会锁的人也会开。真正的安全加密用两把钥匙(公钥加密),像快递箱:谁都能往里投,只有你有钥匙取。
📌 课堂类比:保险箱/快递箱
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. ord('a') 的结果是?
A 'a'B 97C 65D 0
'a' 是输入不是输出,ord 会返回一个数字。
✓ 对!小写 a 的编号是 97。
65 是大写 A 的编号。
0 是控制字符的编号,不是 a。
📖 完整思路:ord(order)= 字符 → 编号,小写 a 是 97。大写 A 才是 65。
2. chr(100) 的结果是?
A 100B 'd'C 'c'D 报错
chr 返回字符,不是数字本身。
✓ 对!100 往后数:a=97, b=98, c=99, d=100。
c 是 99,d 才是 100。
chr 接收 100 完全合法,不会报错。
📖 完整思路:chr(character)= 编号 → 字符。100 对应字母 d(97=a, 98=b, 99=c, 100=d)。
3. 凯撒加密 'x' 往后挪 5 格(绕圈)得到?
A 'c'B 'd'C 'y'D 'b'
c 是数到第 4 格(x→y→z→a→b→c),还差一格。
✓ 对!x 数 5 格:y z a b c,落在 d。
y 只挪了 1 格。
b 只挪了 3 格(x→y→z→a→b)。
📖 完整思路:x→y→z→a→b→c 数 5 格,得到 d。课上 x+5 → d 就是绕圈:对 122 取模再 -1 +97。
09
字符串方法 接下来 字符串方法第一课:isupper 问“你是不是大写字母?”
In [64] 复制
'c'.isupper()
豆豆老师小课堂 问:小写字母 c 是大写吗?
▸
它是怎么实现的 isupper() 是字符串的“体检方法”:检查是不是大写字母,是就返回 True,不是就 False。
逐行讲解(带注释版代码)
'c'.isupper() # 检查 'c' 是不是大写
'c'.isupper()检查 'c' 是不是大写
为什么输出是这个 输出 False:小写 c 不是大写。
接下来 大写 A 呢?isupper 的回答是 True 还是 False?
In [65] 复制
'A'.isupper()
豆豆老师小课堂 问:A 是大写吗?
▸
逐行讲解(带注释版代码)
'A'.isupper() # 检查 'A' 是不是大写
'A'.isupper()检查 'A' 是不是大写
接下来 遍历句子,把大写字母一个个挑出来——判断 + 循环的组合拳。
In [70] 复制
msg = "Very, 1 Good People 1234"
for ch in msg:
if ch.isupper():
print(ch)
豆豆老师小课堂 在一句话里找出所有大写字母。
▸
它是怎么实现的 遍历每个字符,if ch.isupper() 成立就打印。isupper 问“你是不是大写”、islower 问“你是不是小写”——字符串自带的小工具,用点号叫它出来帮忙。
逐行讲解(带注释版代码)
msg = "Very, 1 Good People 1234" # 要检查的文字
for ch in msg: # 遍历每个字符
if ch.isupper(): # 如果是大写字母
print(ch) # 打印它
msg = "Very, 1 Good People 1234"要检查的文字
for ch in msg:遍历每个字符
if ch.isupper():如果是大写字母
print(ch)打印它
为什么输出是这个 输出 V G P:Very 的 V、Good 的 G、People 的 P。数字和小写都被跳过。
接下来 换一下:这次把小写字母挑出来,用 islower。
In [71] 复制
msg = "Very, 1 Good People 1234"
for ch in msg:
if ch.islower():
print(ch)
豆豆老师小课堂 找出所有小写字母。
▸
它是怎么实现的 条件换成 islower():是小写才打印。
逐行讲解(带注释版代码)
msg = "Very, 1 Good People 1234" # 同一句话
for ch in msg: # 遍历
if ch.islower(): # 如果是小写字母
print(ch) # 打印
msg = "Very, 1 Good People 1234"同一句话
for ch in msg:遍历
if ch.islower():如果是小写字母
print(ch)打印
为什么输出是这个 输出 e r y o o d e o p l e:全是小写字母,大写、数字、标点、空格都跳过。
接下来 isascii:只认英文字符。中文和 emoji 不算,试试看。
In [79] 复制
msg = "Very, 789 Good People 1234 你好 😄"
for ch in msg:
if ch.isascii():
print(ch)
V
e
r
y
,
7
8
9
G
o
o
d
P
e
o
p
l
e
1
2
3
4
豆豆老师小课堂 用 isascii() 只保留“电脑最基础字符”,中文和 emoji 被过滤掉。
▸
它是怎么实现的 isascii() 检查字符是不是 ASCII 字符(英文、数字、标点等基础字符)。'你'、'好'、😄 不是 ASCII,所以不打印。
逐行讲解(带注释版代码)
msg = "Very, 789 Good People 1234 你好 😄" # 混合文字:英文数字+中文+表情
for ch in msg: # 遍历
if ch.isascii(): # 如果字符属于 ASCII 基础字符
print(ch) # 打印
msg = "Very, 789 Good People 1234 你好 😄"混合文字:英文数字+中文+表情
for ch in msg:遍历
if ch.isascii():如果字符属于 ASCII 基础字符
print(ch)打印
为什么输出是这个 输出 V e r y , 空格 7 8 9 空格 G o o d 空格 P e o p l e 空格 1 2 3 4:中文 '你好' 和 😄 都没被打印——它们不是 ASCII 字符。
接下来 用 dir 侦探看看:字符串到底还藏了多少方法?
In [80] 复制
dir(str)
Out ['__add__',
'__class__',
'__contains__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getnewargs__',
'__getstate__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rmod__',
'__rmul__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'capitalize',
'casefold',
'center',
'count',
'encode',
'endswith',
'expandtabs',
'find',
'format',
'format_map',
'index',
'isalnum',
'isalpha',
'isascii',
'isdecimal',
'isdigit',
'isidentifier',
'islower',
'isnumeric',
'isprintable',
'isspace',
'istitle',
'isupper',
'join',
'ljust',
'lower',
'lstrip',
'maketrans',
'partition',
'removeprefix',
'removesuffix',
'replace',
'rfind',
'rindex',
'rjust',
'rpartition',
'rsplit',
'rstrip',
'split',
'splitlines',
'startswith',
'strip',
'swapcase',
'title',
'translate',
'upper',
'zfill']
豆豆老师小课堂 让 dir(str) 把字符串的“全部本领”(方法)列出来。
▸
它是怎么实现的 dir 是“查字典”函数:dir(str) 返回字符串类型所有能用的方法名,带下划线的是内部方法,普通名字才是常用的。is 下面有一大家子:isalpha、isalnum、isascii、isdecimal、isdigit、isidentifier、isnumeric、isprintable——专门回答“你是不是某类字符”。
逐行讲解(带注释版代码)
dir(str) # 列出字符串的所有方法
为什么输出是这个 输出一长串方法名:count、find、index、isupper、join、split、upper 等等。之后几个 cell 会逐个试用。
接下来 换行符可以打印吗?isprintable 会告诉你是 True 还是 False。
In [82] 复制
'\n'.isprintable()
豆豆老师小课堂 问:换行符 \n 是可打印字符吗?
▸
它是怎么实现的 isprintable() 检查字符能不能“看得见”。\n 是换行控制符,看不见,所以返回 False。
逐行讲解(带注释版代码)
'\n'.isprintable() # 检查换行符是否可打印
'\n'.isprintable()检查换行符是否可打印
为什么输出是这个 输出 False:\n 是控制字符,看不见,不能算可打印。
接下来 abc 能不能当变量名?isidentifier 是“变量名体检机”。
In [83] 复制
'abc'.isidentifier()
豆豆老师小课堂 问:'abc' 是合法的“名字”(标识符)吗?
▸
它是怎么实现的 isidentifier() 检查能不能当变量名:字母开头、只含字母数字下划线。'abc' 可以。老师讲过:isidentifier 就是问“这个名字能不能当变量名?”——变量只能由字母、数字、下划线组成,且不能以数字开头。
逐行讲解(带注释版代码)
'abc'.isidentifier() # 检查 'abc' 能否当标识符
'abc'.isidentifier()检查 'abc' 能否当标识符
为什么输出是这个 输出 True:'abc' 是合法的变量名。
接下来 1abc 能不能当变量名?数字开头的名字不合格!
In [84] 复制
'1abc'.isidentifier()
豆豆老师小课堂 问:'1abc' 是合法标识符吗?
▸
逐行讲解(带注释版代码)
'1abc'.isidentifier() # 检查 '1abc'
'1abc'.isidentifier()检查 '1abc'
为什么输出是这个 输出 False:数字开头的名字不合法(变量名不能以数字开头)。
接下来 count 数一数:这句话里 a 出现了几次?
In [88] 复制
'abc hello abc '.count('a')
豆豆老师小课堂 数一数 'a' 在这句话里出现几次。
▸
它是怎么实现的 count() 是“点人数”方法:数指定字符出现几次。
逐行讲解(带注释版代码)
'abc hello abc '.count('a') # 数 'a' 出现的次数
'abc hello abc '.count('a')数 'a' 出现的次数
为什么输出是这个 输出 2:第一个 abc 有 1 个,第二个 abc 有 1 个,共 2 个。
接下来 数数你的名字:arianna 里 a 有几个?
In [89] 复制
'arianna'.count('a')
豆豆老师小课堂 数 'arianna' 里 'a' 出现几次。
▸
它是怎么实现的 数一数:a-r-i-a-n-n-a,a 出现 3 次。count 就是“点人数”:统计某个字符在字符串里出现多少次。
逐行讲解(带注释版代码)
'arianna'.count('a') # 数 'a'
'arianna'.count('a')数 'a'
为什么输出是这个 输出 3:arianna 里有 3 个 a。
接下来 find 找位置:a 第一次出现在第几个索引?
In [90] 复制
'arianna'.find('a')
豆豆老师小课堂 找 'a' 第一次出现在哪个位置。
▸
它是怎么实现的 find() 从 0 号开始找,返回第一次出现的编号;找不到返回 -1。但 -1 有个坑:字符串支持负索引,容易混淆,所以判断要用 == -1。
逐行讲解(带注释版代码)
'arianna'.find('a') # 找第一个 'a' 的位置
'arianna'.find('a')找第一个 'a' 的位置
为什么输出是这个 输出 0:'arianna' 的 0 号就是 a。
接下来 index 和 find 一样吗?跑跑看,注意区别。
In [91] 复制
'arianna'.index('a')
豆豆老师小课堂 用 index() 找 'a' 的位置。
▸
它是怎么实现的 index() 和 find() 差不多,区别:找不到时 index 会报错,find 返回 -1。
逐行讲解(带注释版代码)
'arianna'.index('a') # 找第一个 'a'
'arianna'.index('a')找第一个 'a'
为什么输出是这个 输出 0:和 find 一样,0 号是 a。
接下来 找 'an':返回第一次出现的位置。
In [94] 复制
'ariannaan'.index('an')
豆豆老师小课堂 找子串 'an' 第一次出现的位置。
▸
它是怎么实现的 index 可以找一串字符(子串)的位置。'ariannaan' 里 'an' 第一次出现在编号 3。就算字符串里有两个 an,index 也只告诉你第一次出现的位置。
逐行讲解(带注释版代码)
'ariannaan'.index('an') # 找 'an' 子串的位置
'ariannaan'.index('an')找 'an' 子串的位置
为什么输出是这个 输出 3:a(0)r(1)i(2)a(3)n(4)——3 号开始是 'an'。
接下来 找不到会怎样?index 直接报错——它很较真。
In [95] 复制
'abc'.index('xyz')
ValueError: substring not found
---------------------------------------------------------------------------ValueError Traceback (most recent call last)Cell In[95], line 1
----> 1 'abc'.index('xyz')
ValueError: substring not found
豆豆老师小课堂 用 index() 找不存在的 'xyz'——报错。
▸
它是怎么实现的 'abc' 里根本没有 'xyz',index() 找不到就发脾气报错。
逐行讲解(带注释版代码)
'abc'.index('xyz') # 找不存在的子串
'abc'.index('xyz')找不存在的子串
为什么输出是这个 报 ValueError: substring not found(子串没找到)。这是 index 和 find 的重要区别。
接下来 find 找不到返回 -1——它比较温柔,但 -1 有个坑(字符串支持负索引)。
In [96] 复制
'abc'.find('xyz')
豆豆老师小课堂 用 find() 找不存在的 'xyz'——不报错,返回 -1。
▸
它是怎么实现的 find() 找不到时礼貌地返回 -1,表示“没有”。但 -1 有个坑:字符串支持负数索引(-1 是最后一个字符),容易产生歧义,所以判断“没找到”要用 == -1。
逐行讲解(带注释版代码)
'abc'.find('xyz') # 找不存在的子串
为什么输出是这个 输出 -1:find 找不到就返回 -1,不报错。
接下来 终极写法:用 if 判断 find 的结果是不是 -1,程序就有了“找没找到”的判断力。
In [97] 复制
if 'abc'.find('xyz') == -1:
print('not exist')
豆豆老师小课堂 利用 find 返回 -1 的特点:找不到就打印“不存在”。
▸
它是怎么实现的 if 'abc'.find('xyz') == -1 判断返回值是不是 -1,是就说明不存在,打印提示。老师强调:判断字符串是否存在,== -1 就是 find 最常用的检查方式。
逐行讲解(带注释版代码)
if 'abc'.find('xyz') == -1: # 如果 find 返回 -1(没找到)
print('not exist') # 打印:不存在
if 'abc'.find('xyz') == -1:如果 find 返回 -1(没找到)
print('not exist')打印:不存在
为什么输出是这个 输出 not exist:'xyz' 不在 'abc' 里,find 返回 -1,条件成立。
豆豆点一点 刚学的知识点,马上练练手——点点选项看输出对不对!
1. 下面代码会输出什么?
print('abc'.find('xyz'))
A 0B -1C 报错D 3
0 表示在开头找到,但这里没找到。
✓ 对!find 找不到就返回 -1。
find 很温柔,找不到不报错(index 才会)。
3 是位置编号,这里没有匹配。
📖 完整思路:xyz 不在 abc 里,find 找不到返回 -1。
2. 下面代码会输出什么?
if 'abc'.find('xyz') == -1:
print('没找到')
A 没找到B abcC 报错D 什么都不输出
✓ 对!-1 == -1 成立,进入 if 打印。
abc 是字符串内容,这里打印的是提示文字。
find 和 if 都合法,不会报错。
条件成立,会输出内容。
📖 完整思路:find 返回 -1,条件成立,打印“没找到”。
In [ ] 复制
豆豆老师小课堂 一个空 cell,什么都没有。
▸
它是怎么实现的 空 cell 没有任何代码和输出,通常是留白的练习区。
豆豆答疑站 课堂上同学们常问的问题,先自己想,再看答案。
💬 find 和 index 有什么区别?
都找第一次出现的位置。区别:找不到时 index 报错,find 返回 -1。课堂上还发现一个坑:字符串支持负索引,所以 -1 有歧义,要写 if x.find('abc') == -1 来判断。
📌 来自课堂:真实难点
💬 isidentifier 是干什么的?
体检一个名字能不能当变量名。'abc' → True;'1abc' → False(数字开头不行)。变量名规则:只能字母、数字、下划线,不能数字开头。
📌 课堂重点
💬 count 和 find 的差别?
count 数“出现几次”,find 找“第一次在哪”。一个数次数,一个找位置。
📌 课堂概念
豆豆小测验 点一点选项,不管选哪个都会有讲解。选错了不丢人,看懂解释就赚到了!
1. 'abc'.find('xyz') 返回?
A 0B -1C 报错D 3
0 表示在开头找到了,但 xyz 根本不在 abc 里。
✓ 对!find 找不到返回 -1,表示不存在。
find 很温柔,找不到不会报错(index 才会)。
3 是位置编号,但这里根本找不到。
📖 完整思路:find 找不到返回 -1(表示不存在)。而 index 找不到会报错。
2. '1abc'.isidentifier() 返回?
A TrueB FalseC 报错D 1
True 表示合法,但数字开头的名字不合格。
✓ 对!变量名不能数字开头,返回 False。
isidentifier 不会报错,它只会给答案。
返回的是 True/False,不是数字。
📖 完整思路:变量名不能以数字开头,所以 1abc 不是合法标识符。
3. 'arianna'.count('a') 返回?
A 1B 2C 3D 4
1 只数了第一个 a,后面还有两个。
2 漏了最后一个 a。
✓ 对!a 出现在第 1、4、7 位,共 3 次。
4 次数多了,arianna 里只有 3 个 a。
📖 完整思路:arianna 里 a 出现 3 次:a-r-i-a-n-n-a。count 数次数,find 找位置。
豆豆老师的知识地图
学到这里,你已经把 Python 的“地基”一块块垒起来了。回头看看这条路——
① 表达式与语句 代码是一段段“会算出答案”的表达式;运算符 + 操作数 组成它。
② 变量 贴了名字的盒子:a = 2。命名只能用字母/数字/下划线,不能以数字开头。
③ 类型与转换 文字(str)和数字(int/float)是不同世界;int()/float() 是“翻译机”,返回值可以存进变量。
④ 条件判断 if / elif / else:让电脑按条件选一条路走(BMI、出租车计费)。
⑤ 循环 while 把“重复做的事”交给电脑:乘法表、星号图案——先找规律,再写循环。
⑥ 嵌套循环 外层管行、内层管星:重复的代码用循环压缩,这就是“增量开发”。
⑦ 字符串 索引、遍历、len()、upper()……文字也是可以逐字操作的“字符队列”。
⑧ 算法思维 凯撒加密:把问题拆成 编号→挪动→绕圈→变回,像计算机一样一步步算。
从“2 + 3”到写出自己的加密程序,你已经学会像计算机一样思考了。下一步,试着用学到的循环和判断,自己编一个小程序吧——你已经可以做到了!