目录
2.1 变量:给数据起个名字
变量不是「装数据的盒子」,更准确的说法是贴在数据上的标签。
age = 18
name = "小明"
= 在这里不是数学的「等于」,而是赋值:把右边的值算出来,让左边的名字指向它。
>>> age = 18
>>> age
18
>>> age = age + 1 # 先算右边得 19,再让 age 指向 19
>>> age
19
因为变量只是标签,所以同一个名字可以先后指向不同类型的值:
x = 10
print(x) # 10
x = "十"
print(x) # 十
Python 是动态类型语言:不需要提前声明类型。灵活,但也意味着类型错误要到运行时才暴露。
用 id() 看见「标签」这件事
a = [1, 2, 3]
b = a # b 和 a 指向同一个列表,不是复制
b.append(4)
print(a) # [1, 2, 3, 4] a 也变了
a = [1, 2, 3]
b = a.copy() # 复制出一份新的
b.append(4)
print(a) # [1, 2, 3]
这个区别在第 4 课还会重点讲,现在记住一句:= 不复制数据,只复制标签。
2.2 怎么给变量起名字
硬性规则(违反就报错):
- 只能包含字母、数字、下划线,且不能以数字开头
- 不能是关键字(
if、for、class、def、True、None等) - 区分大小写:
age、Age、AGE是三个不同的名字 - 不能用中文标点、空格
软性规范(违反不报错,但会被同事嫌弃):
| 场景 | 推荐 | 不推荐 |
|---|---|---|
| 普通变量、函数 | user_name、total_price(蛇形命名) |
userName、a、x1 |
| 常量 | MAX_SIZE、PI |
max_size |
| 类名 | StudentInfo(大驼峰) |
student_info |
好名字的标准:读代码时不需要看注释就知道它是什么。
# 差
d = 30
t = 8.5
# 好
days = 30
daily_hours = 8.5
2.3 五种基本类型
age = 18 # int 整数
price = 9.9 # float 浮点数(小数)
name = "小明" # str 字符串
is_student = True # bool 布尔值(True / False)
result = None # NoneType 空值,表示「还没有结果」
用 type() 查看类型:
>>> type(18)
<class 'int'>
>>> type(9.9)
<class 'float'>
>>> type("18")
<class 'str'>
>>> type(True)
<class 'bool'>
isinstance() 判断是否属于某个类型,比 type() == 更常用:
>>> isinstance(18, int)
True
>>> isinstance(True, int) # 注意:bool 是 int 的子类
True
⚠️ 常见坑:
"18"和18看起来像,但一个是文本一个是数字。"18" + 1会直接报TypeError。
2.4 数字与运算
四种数字类型相关运算
>>> 7 + 3 # 加
10
>>> 7 - 3 # 减
4
>>> 7 * 3 # 乘
21
>>> 7 / 3 # 除,结果永远是 float
2.3333333333333335
>>> 7 // 3 # 整除,向下取整,丢掉小数部分
2
>>> 7 % 3 # 取余,余数
1
>>> 7 ** 3 # 幂,7 的 3 次方
343
两个容易踩的点:
>>> -7 // 2 # 向下取整,不是向零取整
-4
>>> -7 % 3 # 余数的符号跟除数一致
2
// 和 % 组合起来可以拆数字,比如「137 分钟是几小时几分钟」:
total = 137
print(total // 60, "小时", total % 60, "分钟") # 2 小时 17 分钟
优先级
** > 正负号 > * / // % > + -,同级从左往右。记不住就加括号,括号永远不嫌多。
>>> 2 + 3 * 4
14
>>> (2 + 3) * 4
20
浮点数精度
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
False
这不是 Python 的 bug,而是二进制无法精确表示 0.1(就像十进制写不出 1/3)。解决办法:
>>> round(0.1 + 0.2, 2) == 0.3
True
>>> abs((0.1 + 0.2) - 0.3) < 1e-9 # 更专业的写法:判断误差足够小
True
涉及金额计算时,用 decimal 模块而不是 float:
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2")) # 0.3
大数字和下划线
Python 的 int 没有溢出问题,可以算很大的数:
>>> 2 ** 100
1267650600228229401496703205376
>>> 10_000_000 # 下划线只是给人看的分隔,不影响数值
10000000
2.5 字符串
三种写法
s1 = '单引号'
s2 = "双引号" # 和单引号完全等价,选一种风格坚持用
s3 = """三个引号可以
跨多行书写"""
索引与切片
字符串是「字符的序列」,可以用下标取单个字符,从 0 开始:
s = "Python"
# 012345
print(s[0]) # P
print(s[5]) # n
print(s[-1]) # n 负数从末尾数,-1 是最后一个
print(s[0:3]) # Pyt 左闭右开:含 0 不含 3
print(s[2:]) # thon
print(s[:3]) # Pyt
print(s[::2]) # Pto 每两个取一个
print(s[::-1]) # nohtyP 反转
常用方法
字符串方法都返回新字符串,原字符串不变(字符串不可变):
s = " Hello, Python "
s.strip() # 'Hello, Python' 去掉两端空白
s.lower() # ' hello, python ' 转小写
s.upper() # ' HELLO, PYTHON ' 转大写
s.replace("Python", "世界") # ' Hello, 世界 '
"a,b,c".split(",") # ['a', 'b', 'c'] 切成列表
"-".join(["2026", "11"]) # '2026-11' 拼接
"Python".find("t") # 2 找不到返回 -1
"Python".startswith("Py") # True
len("Python") # 6 长度,注意 len 是函数不是方法
链式调用很常见,因为每一步都返回新字符串:
raw = " XiaoMing@Example.COM "
email = raw.strip().lower()
print(email) # xiaoming@example.com
转义字符
print("第一行\n第二行") # \n 换行
print("姓名\t年龄") # \t 制表符(对齐用)
print("C:\\Users\\me") # \\ 表示一个反斜杠
print("他说:\"你好\"") # \" 在双引号字符串里表示引号
路径多的时候用原始字符串,r 前缀让反斜杠不再转义:
path = r"C:\Users\me\Documents"
print(path) # C:\Users\me\Documents
2.6 f-string:拼字符串的最佳方式
Python 3.6 之后,格式化字符串首选 f-string:在引号前加 f,用 {} 嵌入变量或表达式。
name = "小明"
age = 18
print(f"{name} 今年 {age} 岁") # 小明 今年 18 岁
print(f"明年他 {age + 1} 岁") # 括号里可以写表达式
print(f"{name} 的名字有 {len(name)} 个字")
格式控制写在冒号后面:
pi = 3.14159
print(f"{pi:.2f}") # 3.14 保留 2 位小数
print(f"{pi:10.3f}") # 3.142 总宽 10,右对齐
print(f"{pi:<10.3f}|") # 3.142 | 左对齐
print(f"{0.257:.1%}") # 25.7% 百分比
print(f"{1234567:,}") # 1,234,567 千分位
print(f"{42:05d}") # 00042 补零到 5 位
调试时有个偷懒写法(3.8+),= 会同时打印变量名和值:
>>> x = 42
>>> print(f"{x=}")
x=42
2.7 类型转换
int("18") # 18 字符串 → 整数
int(3.9) # 3 浮点 → 整数,直接截断,不四舍五入
float("3.14") # 3.14
str(18) # '18'
bool(0) # False
三个必知的陷阱
陷阱一:int("3.5") 会报错
>>> int("3.5")
ValueError: invalid literal for int() with base 10: '3.5'
因为 "3.5" 不是合法的整数字面量。要两步走:
int(float("3.5")) # 3
陷阱二:bool 转换的规则和直觉不同
bool("0") # True 非空字符串都是 True,哪怕内容是 "0" 或 "False"
bool("") # False 空字符串才是 False
bool(0) # False
bool([]) # False 空列表
bool(None) # False
记法:0、""、[]、{}、None、False 为假,其它一切为真。
陷阱三:round() 是「银行家舍入」
>>> round(2.5)
2
>>> round(3.5)
4
遇到 .5 时舍入到最近的偶数。做「四舍五入」的业务逻辑时要留意,必要时用 decimal 的 ROUND_HALF_UP。
2.8 input():让程序接收输入
name = input("请输入你的名字:")
print(f"你好,{name}")
运行效果:
请输入你的名字:小明
你好,小明
关键点:input() 的返回值永远是字符串,哪怕用户输入的是 18。
age = input("年龄:")
print(type(age)) # <class 'str'>
print(age + 1) # TypeError!
必须先转换:
age = int(input("年龄:"))
print(f"明年 {age + 1} 岁")
如果用户输入了非数字,int() 会抛 ValueError,程序崩溃。第 6 课会讲怎么优雅处理;现在先知道这件事会发生。
2.9 综合示例:BMI 计算器
height = float(input("请输入身高(米):"))
weight = float(input("请输入体重(公斤):"))
bmi = weight / height ** 2
print(f"你的 BMI 是 {bmi:.1f}")
if bmi < 18.5:
print("偏瘦")
elif bmi < 24:
print("正常")
else:
print("偏胖")
这段代码已经用到了本课几乎所有知识点:input、类型转换、算术运算、f-string 格式化。if 分支下一课就讲。
2.10 小结
- 变量是标签,
=是绑定不是复制 - 五种基本类型:
int、float、str、bool、None /永远得 float,//向下取整,%取余,**是幂- 浮点数有精度误差,比较时用
round或误差范围 - 字符串不可变,切片左闭右开,方法都返回新字符串
- 格式化优先用 f-string
input()返回 str,用前必须转换- 假值集合:
0、""、[]、{}、None、False
2.11 课后练习
练习 1 下面哪些变量名合法?
user_name 2name _temp my-age class userName MAX_SIZE 名字
练习 2 预测输出,再运行验证:
print(7 / 2)
print(7 // 2)
print(7 % 2)
print(2 ** 3 ** 2)
练习 3 写程序:输入一个三位整数,分别输出百位、十位、个位。例如输入 365,输出 3 6 5。
练习 4 写程序:输入圆的半径,输出面积,保留两位小数(面积 = πr²,π 取 3.14159)。
练习 5 下面代码为什么报错?给出两种修改方式。
age = input("年龄:")
print("明年你 " + age + 1 + " 岁")
参考答案
练习 1
合法:user_name、_temp、userName、MAX_SIZE、名字(Python 3 支持中文变量名,但不推荐实际使用)。
非法:2name(数字开头)、my-age(含减号)、class(关键字)。
练习 2
3.5
3
1
512
2 ** 3 ** 2 是右结合的,等价于 2 ** (3 ** 2) = 2 ** 9 = 512。这是幂运算的特殊规则,和 + - * / 的左结合不同。
练习 3
num = int(input("输入三位整数:"))
hundreds = num // 100
tens = num // 10 % 10
ones = num % 10
print(hundreds, tens, ones)
用除法和取余「拆位」是最基础的数字处理技巧,后面处理时间、进制转换都靠它。
练习 4
r = float(input("半径:"))
area = 3.14159 * r ** 2
print(f"面积是 {area:.2f}")
练习 5
原因:age 是字符串,"明年你 " + age 得到字符串,再接 + 1(整数)时类型不匹配,抛 TypeError。
改法一,先转成数字再算:
age = int(input("年龄:"))
print(f"明年你 {age + 1} 岁")
改法二,保持字符串,先算再转:
age = input("年龄:")
next_age = int(age) + 1
print("明年你 " + str(next_age) + " 岁")
推荐第一种:尽早把数据转成正确的类型,而不是一路用字符串拼。
评论
评论区即 对应 issue 的讨论串,登录 GitHub 即可留言。