变量、表达式与流程控制
上一章环境已经跑通,从这一章开始正式写代码。我们要解决三件事:数据怎么存(变量)、数据怎么算(运算符与表达式)、程序怎么根据不同情况走不同的路、怎么重复干活(流程控制)。这三样是所有 Python 代码的地基,务必敲熟
上一章环境已经跑通,从这一章开始正式写代码。我们要解决三件事:数据怎么存(变量)、数据怎么算(运算符与表达式)、程序怎么根据不同情况走不同的路、怎么重复干活(流程控制)。这三样是所有 Python 代码的地基,务必敲熟。
一、先摸清 Python 的脾气
动手之前,先用四个标签认识一下这门语言:
- 解释型:代码不用事先编译成机器码,解释器读一句执行一句,改完立刻见效
- 动态类型:变量本身不锁定类型,同一个名字这一秒装数字、下一秒装字符串都没问题
- 强类型:类型不合时 Python 绝不偷偷帮你乱转,
"3" + 5会直接报错——宁可报错,也不瞎猜 - 面向对象:万物皆对象,连数字、字符串、函数身上都挂着属性和方法
二、注释:写给读代码的人
# 井号开头,从这里到行尾都归注释管
"""
三个双引号包起来的整块内容
想写几行就写几行
"""
'''
三个单引号也行
效果完全一样
'''
注释是给人看的,解释器会直接无视它。养成"写代码顺手写注释"的习惯,三个月后的你会感谢现在的你。
三、变量:给数据贴标签
创建变量
Python 里造一个变量不需要提前声明类型,起个名字、直接赋值,它就诞生了:
shop = "山野茶铺" # 字符串
tables = 12 # 整数
rating = 4.8 # 浮点数
is_open = True # 布尔值
可以把变量理解成贴在数据上的标签:标签本身没有类型,贴到什么数据上,它就代表什么。
起名的硬性规则
| 规则 | 具体要求 | 示例 |
|---|---|---|
| 开头有限制 | 只能以字母或下划线打头 | tea_name、_count |
| 内容有限制 | 只能由字母、数字、下划线组成 | order2、cup_500 |
| 大小写敏感 | Name 和 name 是两个不同的变量 |
Name = 1、name = 2 |
| 避开关键字 | Python 保留的字不能占用 | if、for、class |
关键字清单(这些名字归 Python 所有):
False, None, True, and, as, assert, async, await, break, class, continue, def, del, elif, else, except, finally, for, from, global, if, import, in, is, lambda, nonlocal, not, or, pass, raise, return, try, while, with, yield
# 合法的命名
tea_name = "鸭屎香柠檬茶"
_total = 0
MAX_CUPS = 500
order2 = 88.5
# 不合法的命名(写了就报错)
# 2order = 10 # 数字打头,不行
# tea-name = "绿茶" # 中间那根横线会被当成减号
# for = 5 # for 是关键字,被 Python 占了
起名的软性约定
规则是底线,约定是品味。Python 社区有一套默认的命名习惯:
| 场景 | 惯例 | 示例 |
|---|---|---|
| 普通变量 | 小写加下划线(snake_case) | order_count、total_price |
| 常量 | 全大写加下划线 | MAX_STOCK、PI |
| 类名 | 大驼峰(PascalCase) | OrderDetail、ShopModel |
| 私有/内部变量 | 下划线开头 | _helper、__secret |
一行搞定多个赋值
# 一行创建多个变量
lemon, oolong, jasmine = 12, 30, 8
# 交换两个变量的值(不需要第三个变量打辅助)
cup_a, cup_b = "奶茶", "果茶"
cup_a, cup_b = cup_b, cup_a # cup_a="果茶",cup_b="奶茶"
# 一串变量共用同一个值
sugar = spice = ice = "标准"
四、数据类型:认一认都有什么
六大类基本类型
| 分类 | 类型 | 长什么样 | 要点 |
|---|---|---|---|
| 数字 | ==int== | 7, -20, 0 | 没有大小上限,多大都装得下 |
| 数字 | ==float== | 3.5, -0.2, 6e8 | 双精度浮点数 |
| 数字 | complex | 2+3j, 1-1j | 虚数单位用 j 表示 $\sqrt{-1}$ |
| 数字/布尔 | ==bool== | True, False | 本质是 int:True 就是 1,False 就是 0 |
| 文本 | ==str== | '奶茶', "tea" | 引号包起来的都是字符串 |
| 空值 | ==NoneType== | None | 表示"什么都没有" |
| 容器 | list 等 | [1, 2]、(3, 4) | 第 03 章专门展开 |
原子与容器两大阵营
- 原子类型(也叫基本内置类型、标量类型):一个值就是一个不可拆的整体——int、float、complex、bool、str、NoneType
- 容器类型:一个值里面装着一堆别的值——list、tuple 等,第 03 章细说
字面量的各种写法
# 整数:支持不同进制
print(2026) # 十进制
print(0b1100) # 二进制,等于 12
print(0o17) # 八进制,等于 15
print(0xFF) # 十六进制,等于 255
# 浮点数:小数形式与科学计数法
print(9.8) # 常规小数
print(-2.5) # 负的小数
print(3.0e8) # 科学计数法 = 300000000.0
print(6.1e-2) # 负指数 = 0.061
# 布尔值只有两个
print(True) # 真
print(False) # 假
# 字符串:单引号双引号等价,三引号能跨行
print("双引号可以")
print('单引号也行')
print('''跨越
两行''')
print("""同样
两行""")
# 空值
print(None)
五、type():随时验明正身
拿不准一个值是什么类型,扔给 type() 看一眼:
# 整数
print(type(2026)) # <class 'int'>
print(type(0b1100)) # <class 'int'>
print(type(0o17)) # <class 'int'>
print(type(0xFF)) # <class 'int'>
# 浮点数
print(type(9.8)) # <class 'float'>
print(type(-2.5)) # <class 'float'>
print(type(3.0e8)) # <class 'float'>
print(type(6.1e-2)) # <class 'float'>
# 布尔值
print(type(True)) # <class 'bool'>
print(type(False)) # <class 'bool'>
# 字符串
print(type("茶")) # <class 'str'>
print(type('Tea')) # <class 'str'>
# 空值
print(type(None)) # <class 'NoneType'>
注意一个细节:type() 返回的不是一串文字,而是类型对象本身,所以可以直接拿去和类型比较:
print(type(2026) == int) # True
六、类型转换:让数据换个身份
# 字符串 → 整数
count_str = "36"
count = int(count_str) # 36
# 整数 → 字符串
price = 22
price_str = str(price) # "22"
# 整数 → 浮点数
seats = 40
seats_float = float(seats) # 40.0
# 浮点数 → 整数(直接砍掉小数部分,不做四舍五入)
discount = 0.75
print(int(discount)) # 0
# 任何值 → 布尔值
print(bool(0)) # False
print(bool(3)) # True
print(bool("")) # False
print(bool("茶")) # True
七、f-string:把变量嵌进字符串
从 Python 3.6 起,字符串前面挂一个 f(或 F),它就变成了"模板"——花括号 {} 里的内容会被现场计算、再填回字符串。这是目前最简洁也最主流的格式化方式,先掌握它就够了。
drink = "生椰拿铁"
price = 18
print(f"饮品:{drink},价格:{price} 元") # 饮品:生椰拿铁,价格:18 元
# 花括号里可以直接写表达式
cups = 3
print(f"{cups} 杯共 {cups * price} 元") # 3 杯共 54 元
八、输入与输出
print:向屏幕说话
# 输出一句话
print("欢迎光临")
# 一次输出多项,默认用空格隔开
print("库存:", 36)
# 用 sep 自定义分隔符
print("2026", "08", "27", sep="-") # 2026-08-27
# 用 end 自定义结尾(默认是换行)
print("正在备餐", end="...")
print("完成") # 正在备餐...完成
input:听用户说
# input 拿到的东西永远是字符串
city = input("请输入你所在的城市:")
print("收到,", city)
# 想当数字用,必须先手动转换
height_str = input("请输入身高(厘米):")
height = int(height_str)
print("换个说法是", height / 100, "米")
九、运算符全家福
算术运算符
| 运算符 | 作用 | int | float | str | bool | None |
|---|---|---|---|---|---|---|
+ |
加 | 数值相加 | 数值相加 | 拼接 | 按数字算 | ✗ |
- |
减 | 数值相减 | 数值相减 | ✗ | 按数字算 | ✗ |
* |
乘 | 数值相乘 | 数值相乘 | 重复若干遍 | 按数字算 | ✗ |
/ |
除 | 结果是 float | 结果是 float | ✗ | 按数字算 | ✗ |
// |
整除 | 向下取整 | 向下取整 | ✗ | 按数字算 | ✗ |
% |
取余 | 求余数 | 求余数 | ✗ | 按数字算 | ✗ |
** |
乘方 | 幂运算 | 幂运算 | ✗ | 按数字算 | ✗ |
# 整数运算
print(16 + 5) # 21
print(16 - 5) # 11
print(16 * 5) # 80
print(16 / 5) # 3.2(注意:/ 的结果一定是 float)
print(16 // 5) # 3(只留整数部分)
print(16 % 5) # 1(余数)
print(16 ** 5) # 1048576
# 浮点数运算
print(4.0 + 1.5) # 5.5
print(4.0 - 1.5) # 2.5
print(4.0 * 1.5) # 6.0
print(4.0 / 1.5) # 2.666...
print(4.0 // 1.5) # 2.0
print(4.0 % 1.5) # 1.0
print(4.0 ** 1.5) # 8.0
# 字符串只吃两个运算符
print("芋泥" + "波波") # 芋泥波波(拼接)
print("好喝!" * 3) # 好喝!好喝!好喝!(重复)
# 布尔值本质是 0 和 1
print(True + True) # 2
print(False * 9) # 0
# None 参与任何算术运算都会报错
# print(None - 1) # TypeError
比较运算符
| 运算符 | 含义 | int / float | str | bool | None |
|---|---|---|---|---|---|
== |
等于 | 比数值 | 比内容 | True==1、False==0 | 只与 None 相等 |
!= |
不等于 | 比数值 | 比内容 | 同上 | 与非 None 都不等 |
< > <= >= |
比大小 | 比数值 | 按字典序 | 按 0/1 比 | ✗ 会报错 |
# 数字比较
print(8 == 8) # True
print(8 != 5) # True
print(8 > 5) # True
# 浮点数同理
print(7.5 >= 7.5) # True
print(7.5 < 7.0) # False
# 字符串按字典序逐个字符比编码
print("tea" == "tea") # True
print("tea" != "coffee") # True
print("apple" < "banana") # True
print("B" < "b") # True(大写 B=66,小写 b=98)
# 布尔值当数字比
print(True == 1) # True
print(False == 0) # True
print(True > False) # True
# None 只能判断"是不是它"
print(None == None) # True
print(None != 0) # True
print(None != False) # True
# print(None > 0) # TypeError
链式比较
Python 支持把比较运算符像数学不等式一样连着写:
temperature = 26
# 其他语言的常规写法
print(temperature > 0 and temperature < 35) # True
# Python 的链式写法,更顺眼
print(0 < temperature < 35) # True
print(20 <= temperature < 30) # True
print(0 < temperature < 10) # False
# 想连更多个也没问题
print(0 < temperature < 35 < 100) # True
等价规则: a < b < c 相当于 a < b and b < c,区别在于 b 只计算一次。
赋值运算符
| 写法 | 相当于 | 常用于 |
|---|---|---|
n = 5 |
- | 所有类型 |
n += 2 |
n = n + 2 |
数字、字符串 |
n -= 2 |
n = n - 2 |
数字 |
n *= 2 |
n = n * 2 |
数字、字符串 |
n /= 2 |
n = n / 2 |
数字 |
n //= 2 |
n = n // 2 |
数字 |
n %= 2 |
n = n % 2 |
数字 |
n **= 2 |
n = n ** 2 |
数字 |
# 数值的累计
total = 20
total += 8 # 28
total -= 3 # 25
total *= 2 # 50
total /= 5 # 10.0(注意:一用 /,结果就变 float)
# 字符串同样支持 += 和 *=
order = "一份炸鸡"
order += ",加辣" # 一份炸鸡,加辣
order *= 2 # 一份炸鸡,加辣一份炸鸡,加辣
海象运算符(:=)
Python 3.8 引入的赋值表达式,能把"赋值"和"求值"塞进同一行。
# 老写法:先赋值,再进循环判断
reply = input("输入点什么(exit 退出):")
while reply != "exit":
print(f"你说的是:{reply}")
reply = input("输入点什么(exit 退出):")
# 海象写法:赋值和判断合二为一
while (reply := input("输入点什么(exit 退出):")) != "exit":
print(f"你说的是:{reply}")
注意: 这是 3.8 才有的特性,更老的版本跑不了。
逻辑运算符
| 运算符 | 名字 | 结果怎么定 |
|---|---|---|
and |
与 | 前面是假 → 返回前面;否则返回后面 |
or |
或 | 前面是真 → 返回前面;否则返回后面 |
not |
非 | 永远返回 True / False |
各类型的真假值( falsy 判定):
- int:0 为假,其余为真
- float:0.0 为假,其余为真
- str:"" 为假,其余为真
- bool:False 为假
- NoneType:None 为假
# 数字
print(0 and 6) # 0(0 是假,直接返回 0)
print(4 and 6) # 6(4 是真,返回后面)
print(0 or 6) # 6
print(4 or 6) # 4
print(not 0) # True
print(not 6) # False
# 浮点数
print(0.0 and 6.0) # 0.0
print(4.0 and 6.0) # 6.0
print(not 0.0) # True
# 字符串
print("" and "abc") # ""(空字符串算假)
print("hi" and "abc") # "abc"
print(not "") # True
print(not "abc") # False
# 布尔值
print(True and False) # False
print(True or False) # True
print(not True) # False
# None
print(None and True) # None
print(None or True) # True
print(not None) # True
三元表达式(条件表达式)
if-else 的单行浓缩版,适合在两种值之间快速二选一:
# 语法
结果 = 值A if 条件 else 值B
stock = 42
# 常规写法
if stock >= 30:
status = "库存充足"
else:
status = "需要补货"
# 三元写法(一行搞定)
status = "库存充足" if stock >= 30 else "需要补货"
print(status) # 库存充足
# 也能嵌套,但别贪多
points = 4200
level = "金卡" if points >= 5000 else ("银卡" if points >= 3000 else "普通")
提醒: 三元只适合简单的二选一,逻辑一复杂就老老实实写回 if-else,可读性要紧。
十、流程控制
if 条件分支
| 写法 | 什么时候执行它 |
|---|---|
if 条件: |
条件成立时 |
elif 条件: |
上面全不成立、而这个成立时 |
else: |
所有条件全部落空时 |
# 两分支
age = 16
if age >= 18:
print("可以独立办理会员")
else:
print("需要监护人陪同")
# 多分支:按消费金额给折扣
spending = 1680
if spending >= 2000:
rate = 0.8
elif spending >= 1000:
rate = 0.85
elif spending >= 500:
rate = 0.9
else:
rate = 1.0
print(f"本次消费享受 {rate} 折")
# 单行版(就是三元表达式)
ship = "免运费" if spending >= 99 else "需付运费"
注意: Python 靠缩进(惯例 4 个空格)划分代码块,没有大括号这回事,缩进就是语法本身。
pass:先占个位
pass 什么都不做,纯粹是个占位符——语法要求这里必须有条语句,但逻辑上暂时还没想好写什么时,就让它顶着。
# 循环体先留空
count = 0
while count < 3:
pass # 逻辑以后再补
count += 1
# 分支先留空
if True:
pass # TODO:还没想好怎么写
while 循环
# 基本款:数到 5
num = 1
while num <= 5:
print(f"第 {num} 杯完成")
num += 1
# 直到用户喊停
answer = ""
while answer != "stop":
answer = input("输入 stop 结束:")
print(f"你输入了:{answer}")
break 与 continue
| 关键字 | 效果 |
|---|---|
break |
当场终止整个循环 |
continue |
跳过本轮剩余代码,直接进入下一轮 |
# break:温度一超标就收工
temp = 20
while temp <= 40:
if temp > 30:
print(f"警报:温度达到 {temp} 度")
break
temp += 1
# continue:跳过 3 的倍数
num = 0
while num < 12:
if num % 3 == 0:
num += 1
continue
print(num) # 1, 2, 4, 5, 7, 8, 10, 11
num += 1
循环的 else 子句
循环后面可以挂一个 else,当循环自然跑完(中途没被 break 打断)时执行:
# 正常结束,else 就会执行
num = 1
while num <= 3:
print(num)
num += 1
else:
print("循环安然结束")
# 经典场景:找东西
# 在偶数序列 2, 4, 6, ... 里找 7
num = 2
while num <= 10:
if num == 7:
print("找到了 7")
break
num += 2
else:
print("没找到 7") # 会执行这句,因为偶数里没有 7
重要区别:
- 循环被 break 打断 → else 不执行
- 循环自然跑完(continue 不算打断)→ else 执行
课后练习
参考答案存放在 ./answers 目录中。
练习一:基础语法输出预测
先不动手运行,逐行读下面的代码,把每个 print 的结果写在注释里,再上机验证。
# 几个变量
stock = 12
price = 45.5
word = "Code"
flag = True
nothing = None
# 1. type 函数
print(type(stock))
print(type(price))
print(type(word))
print(type(flag))
print(type(nothing))
print(type(stock) == int)
# 2. 类型转换
print(int(price))
print(float(stock))
print(str(stock) + word)
print(bool(0))
print(bool(""))
print(bool("ok"))
# 3. 算术运算符
print(stock + 7)
print(stock / 5)
print(stock // 5)
print(stock % 5)
print(stock ** 2)
print(word * 2)
# 4. 字符串格式化(f-string)
book = "数据分析入门"
pages = 320
print(f"书名: {book}, 页数: {pages}")
print(f"第二版增加到{pages + 80}页")
print(f"{stock} + {7} = {stock + 7}")
# 5. 比较运算符与链式比较
print(stock > 8)
print(stock == 12)
print(6 < stock < 20)
print(word == "code")
print("Z" < "a")
# 6. 逻辑运算符
print(True and False)
print(True or False)
print(not flag)
print(0 and 8)
print(7 or 8)
print("" and "ok")
print("ok" or "yes")
print(not None)
# 7. 三元运算符
balance = 650
state = "充足" if balance >= 500 else "不足"
print(state)
grade = "金卡" if balance >= 1000 else ("银卡" if balance >= 600 else "普卡")
print(grade)
# 8. 赋值运算符
y = 8
y += 4
print(y)
y -= 2
print(y)
y *= 3
print(y)
y /= 5
print(y)
t = "第二杯"
t += "半价"
print(t)
t *= 2
print(t)
练习二:循环与分支输出预测
同样先在纸上推演,写出每个 print 的结果,再运行验证。
# 1. while 循环 + if-else
k = 1
total = 0
while k <= 5:
if k % 2 == 0:
total -= k
else:
total += k
k += 1
print(total)
# 2. continue 和 break
num = 1
while num <= 10:
if num == 4:
num += 1
continue
if num == 8:
break
print(num)
num += 1
# 3. 循环 else 子句
j = 0
while j < 3:
print(j)
j += 1
else:
print("over")
# 4. 嵌套条件
y = 25
if y < 20:
print("A")
elif y < 30:
if y % 3 == 0:
print("B")
else:
print("C")
else:
print("D")
# 5. 综合练习
n = 1
acc = 0
while n <= 5:
if n == 4:
acc += 12
elif n % 2 == 0:
acc += n * 3
else:
acc += n
n += 1
print(acc)
练习三:咖啡因摄入评估器
编写一个评估每日咖啡因摄入的小工具,要求如下:
-
用户输入:通过
input()获取用户的体重(单位:千克)和今天喝的咖啡杯数。 -
计算摄入指数:按每杯咖啡约含 80 毫克咖啡因估算,使用公式
摄入指数 = 杯数 × 80 / 体重。 -
判断档位: - 指数 < 1.5:较低 - 1.5 ≤ 指数 < 3:适中 - 3 ≤ 指数 < 5:偏高 - 指数 ≥ 5:过量
-
输出结果:使用 f-string 格式化输出摄入指数(保留两位小数)和档位结果。
-
给出建议:根据档位输出对应建议,例如: - 较低:摄入量不大,正常喝水节奏即可 - 适中:在舒适范围内,注意别太晚喝 - 偏高/过量:建议换成白开水或无因饮品,明显超量时关注身体反应
示例输出:
请输入您的体重(千克):70
请输入您今天喝了几杯咖啡:3
您的咖啡因摄入指数为:3.43
当前档位:偏高
建议:今天的量已经不小,接下来可以换成白开水或无因饮品。
练习四:回文数筛选器
回文数 是指正着读、倒着读都一样的数,例如 11、121、3883;个位数(1~9)天然都是回文数。
编写一个程序,要求如下:
-
用户输入:通过
input()函数获取起始数字和结束数字。 -
输入合法性检查: - 输入必须是正整数(大于 0 的整数) - 结束数字必须大于起始数字 - 输入不合法时,给出相应提示并要求重新输入
-
回文判断:使用循环逐个判断该范围内的每个数字是否为回文数。
-
输出结果:打印该范围内的所有回文数,并统计个数。
示例输出:
请输入起始数字:10
请输入结束数字:60
10 到 60 之间的回文数有:
11 22 33 44 55
共计 5 个回文数
下一章:03 · 序列、字典与集合