第三篇:变量——让程序拥有“记忆”
字数:约38,000字 | 阅读时间:35-50分钟 | 适合刚学会print的你
---
写在前面:从“复读机”到“智能体”
恭喜你完成了第二篇。现在你已经能让Python“说话”了——用print输出各种内容。
但你可能已经感觉到了一个问题:目前的程序像一只复读机。你让它说什么,它就说什么。它没有自己的“记忆”,也不能灵活地处理信息。
比如,你想写一个程序来管理你的零花钱:
```python
print("我有100元")
print("花了30元")
print("还剩70元")
```
如果下次零花钱变成了200元,或者花掉了45元,你必须手动修改代码里的数字。这很不方便。
变量就是来解决这个问题的。它让程序能够记住信息,存储数据,并且重复使用这些数据。
你可以把变量想象成:
· 一个带标签的盒子,你可以往里面放东西
· 一个抽屉,你可以随时打开查看里面的内容
· 一个小纸条,上面记着一个数字或一句话
💡 一个小提示:这个“盒子”比喻能帮助你理解80%的场景,特别适合初学者入门。但等你学到列表、字典等“可变对象”时,我们会把比喻升级为“标签”,那时你会理解更深的原理。现在,你完全可以放心地用“盒子”来思考。
这一篇,我们会花很长时间来理解变量。它非常简单(就是一个名字对应一个值),但又极其重要(没有变量就没有编程)。我会用大量的例子、比喻和练习,确保你真正理解,而不是死记硬背。
---
第一章:变量的本质——名字与盒子的比喻
1.1 生活中的变量
在我们接触代码之前,先想想日常生活中是怎么使用“变量”的。
场景一:给朋友起外号
你的朋友叫“陈小明”,这个名字就是一个“变量名”,指向一个真实的人。当你喊“小明”时,大家都知道你在叫谁。
你甚至可以有多个名字指向同一个人:“小明”、“阿明”、“老大”、“陈总”——这些都是“变量名”,指向同一个“值”(那个人)。
场景二:手机通讯录
你在通讯录里存了“妈妈”这个联系人。这个“妈妈”就是一个变量名,背后是一个具体的电话号码。当你对手机说“打电话给妈妈”,手机会自动找到那个号码。
如果妈妈换了手机号,你只需要修改通讯录里的号码,而不需要改变你说的话——“打电话给妈妈”这句话永远不变,变的是“妈妈”背后对应的号码。
这就是变量的核心价值:把变化的部分和固定的名字分离开。
场景三:冰箱里的抽屉
你家冰箱有冷藏室、冷冻室。每个抽屉可以贴上标签:“肉类”、“蔬菜”、“饮料”。你往“蔬菜”抽屉里放什么,打开它就能拿到什么。今天放的是白菜,明天可能换成菠菜。
变量也是同样的道理:给一块内存空间贴上一个名字,往里面放数据,之后通过名字就能取出数据。
1.2 Python中的变量长什么样?
在Python中,给变量赋值(也就是“创建变量并放东西进去”)的语法非常简单:
```python
变量名 = 值
```
注意:等号 = 在这里不是“等于”的意思,而是“赋值”——把右边的值“赋给”左边的变量。
第一个例子:
```python
age = 25
```
这句代码的含义:
· age 是变量名(就像标签“年龄”)
· = 是赋值运算符
· 25 是值(放进去的数据)
· 整体意思:把数字25这个值,存储到名为age的变量中
之后,你就可以使用age这个变量名来代表25:
```python
print(age) # 输出 25
```
第二个例子:
```python
name = "小明"
print(name) # 输出:小明
```
第三个例子: 变量的值可以被改变
```python
score = 100 # 第一次赋值
print(score) # 输出 100
score = 95 # 重新赋值
print(score) # 输出 95——变量还是叫score,但里面的值变了
```
这就是“变量”这个名字的由来:它的值是可变的。
1.3 一个最容易混淆的概念:= 不是“等于”
数学课上,等号表示“左边等于右边”。比如:x + 3 = 5
但在编程中,等号表示“把右边的值,复制一份,放进左边的盒子里”。
所以下面这个在数学里看起来很奇怪的东西,在编程里是完全正确的:
```python
count = 10
count = count + 1 # 把count原来的值加1,再放回count
print(count) # 输出 11
```
读法:count = count + 1 读作“把count加1后的值,赋值给count”。
让我们拆解:
1. 先计算右边:count + 1 → 当前count是10,所以结果是11
2. 再把11赋给左边的count → count变成了11
这和数学完全不同! 数学里x = x + 1是无解的方程,编程里这是“让x增加1”的标准写法。
1.4 多个变量之间的关系
变量之间可以互相赋值:
```python
a = 5
b = a # 把a的值(5)复制一份,赋给b
a = 10 # 修改a,不影响b
print(b) # 输出 5(b还是原来的5)
```
关键理解:b = a 的意思是“把a的值赋给b”,而不是“让b和a绑定在一起”。赋值完成后,b和a是独立的两个盒子。
用生活中的例子理解:
你在两张纸条上分别写“张三的存款”和“李四的存款”。
· 一开始,张三有100元,李四有0元。
· 你执行“李四的存款 = 张三的存款”——意思是把100这个数字抄到李四的纸条上。
· 然后张三花掉50元(张三的存款改成50)。
· 李四的纸条上还是100,不会自动变成50。
这就是“值复制”的含义。
1.5 变量的命名规则(非常重要!)
不是任何名字都可以做变量名。Python有一套命名规则,违反规则会导致SyntaxError。
硬性规则(违反就报错):
1. 只能包含字母、数字、下划线 _。不能包含空格、点号(.)、标点符号或其他特殊字符(如 @, #, $, % 等)
2. 不能以数字开头(可以以字母或下划线开头)
3. 不能是Python的关键字(Python自己使用的保留词,共35个)
合法变量名示例:
```python
name # 纯字母
name1 # 字母加数字(数字在末尾)
_name # 下划线开头(通常表示“私有”变量,现在不必深究)
user_name # 下划线分隔单词
firstName # 驼峰命名(也可以,但Python社区更常用下划线)
```
非法变量名示例:
```python
123name # 以数字开头 → SyntaxError
my-name # 包含连字符(减号) → 会被解析为减法
my name # 包含空格 → SyntaxError
class # class是关键字(用于定义类)→ SyntaxError
@name # 特殊字符 → SyntaxError
user.name # 包含点号 → SyntaxError(点号有特殊用途)
```
Python关键字(你不需要背诵,但要知道它们存在):
```
False, True, None, and, or, not, if, else, elif, for, while, break, continue,
def, return, class, import, from, as, try, except, finally, raise, with,
assert, async, await, yield, lambda, nonlocal, global, pass, del, is, in
```
如果你不确定一个词是不是关键字,可以用Python自己检查:
```python
import keyword
print(keyword.iskeyword("class")) # True
print(keyword.iskeyword("name")) # False
```
软规则(强烈建议,不遵守不会报错但会被同行吐槽):
1. 使用有意义的名称
```python
# 不好的命名
a = 25
b = "张三"
c = 100
# 好的命名
age = 25
name = "张三"
score = 100
```
2. 变量名用小写字母,多个单词用下划线分隔(PEP 8风格指南,Python官方推荐)
```python
# 推荐
user_name = "小明"
first_order_amount = 999
# 不推荐(但合法)
UserName = "小明" # 大写通常用于类名
userName = "小明" # 驼峰命名在Java/C#中常见,Python中不普遍
```
3. 避免使用单字母变量名(除了非常短的代码或数学公式中的i, j, k作为循环计数器)
4. 不要覆盖内置函数名(比如不要用print、input、len作为变量名)
```python
# 千万不要这样做!
print = 5 # print本来是输出函数,现在被覆盖成了数字5
print("hello") # 报错!因为print不再是函数了
```
如果不小心覆盖了,重启Python解释器可以恢复。
---
第二章:数据类型——变量能装什么“东西”?
变量的“盒子”虽然可以装不同的东西,但Python是有类型的——每个值都有确定的类型。不同的类型支持不同的操作。
就像你家里的抽屉:衣服抽屉可以叠放衣服,但你不能把水倒进去;厨房抽屉可以放调料,但你不能把活鱼放进去(除非你想找死)。
Python中最常用的四种基本数据类型:
类型 中文名 例子 说明
int 整数 42, -5, 0, 1000 没有小数点的数字
float 浮点数 3.14, -0.5, 2.0 有小数点的数字(“浮点”指小数点可以浮动)
str 字符串 "hello", '你好', "123" 一串字符,必须有引号
bool 布尔值 True, False 只有两个值:真/假(注意首字母大写)
2.1 整数(int)
整数就是你小学学的整数:正数、负数、零。
```python
age = 18
temperature = -5
count = 0
year = 2024
print(age + 5) # 23
print(temperature * 10) # -50
print(year - 2000) # 24
```
整数可以做所有数学运算:+(加)、-(减)、*(乘)、/(除)、//(整除)、%(取余/模)、**(幂/乘方)。
我们会在下一章详细讲这些运算符。
2.2 浮点数(float)
浮点数就是带小数点的数字。名字“浮点”来源于小数点可以“浮动”(比如 0.0012 也可以写成 1.2e-3,科学计数法)。
```python
pi = 3.14159
price = 19.99
ratio = 0.75
negative = -2.5
print(pi * 2) # 6.28318
print(price + 0.01) # 20.0
```
重要警示:浮点数精度问题
计算机用二进制表示小数时,有些十进制小数无法精确表示(就像1/3无法用有限位小数精确表示一样,只能用0.33333...近似)。
试试这个:
```python
print(0.1 + 0.2)
```
你可能期望输出 0.3,但实际输出可能是 0.30000000000000004!
这不是Python的bug,而是所有编程语言(JavaScript、Java、C++等)使用浮点数时的共同特性。因为计算机内部用二进制,0.1的二进制表示是一个无限循环小数,只能取近似值。
解决方法:
· 对于需要精确计算的情况(比如金额),使用整数(以“分”为单位存储,而不是“元”)
· 或者使用Python的decimal模块(以后会学到)
· 大多数情况下,浮点数的微小误差是可以接受的,只需要控制输出格式
控制输出小数位数(用round函数或格式化字符串):
```python
result = 0.1 + 0.2
print(round(result, 2)) # 保留2位小数 → 0.3
# 注意:round() 返回的仍然是浮点数,只是显示上更接近我们期望的值
```
2.3 字符串(str)
字符串就是文本。需要放在引号里——单引号、双引号、三引号都可以,但必须成对。
```python
greeting = "Hello"
name = 'Alice'
sentence = """这是一个
多行字符串"""
print(greeting) # Hello
print(name) # Alice
print(sentence) # 这是一个\n多行字符串(\n是换行符)
```
引号的选择:
· 如果字符串内部没有引号,单引号和双引号都可以
· 如果字符串内部有单引号,外部用双引号(避免转义)
· 如果字符串内部有双引号,外部用单引号
```python
speech1 = '她说:"你好"' # 外部单引号,内部双引号,没问题
speech2 = "她说:'你好'" # 外部双引号,内部单引号,也没问题
speech3 = "她说:\"你好\"" # 使用转义字符\"来表示双引号
```
字符串拼接(连接):
用 + 可以将两个字符串连接起来:
```python
first = "Hello"
second = "World"
result = first + " " + second # "Hello World"
print(result)
```
字符串重复:
用 * 可以将字符串重复多次:
```python
print("=" * 20) # 输出 20个等号
print("哈哈" * 3) # 输出 "哈哈哈哈哈哈"
```
字符串长度:
用len()函数获取字符串中字符的个数:
```python
message = "Hello"
print(len(message)) # 5(H,e,l,l,o 共5个字符)
```
字符串索引和切片(更进阶的内容,下一篇或下下篇会系统讲解):
```python
text = "Python"
print(text[0]) # 第一个字符:P(索引从0开始)
print(text[1]) # y
print(text[-1]) # 最后一个字符:n
print(text[0:3]) # 从索引0到2(不包括3):Pyt
```
2.4 布尔值(bool)
布尔值只有两个:True 和 False。
重要:首字母必须大写!true、false、True、False 中只有后两个是正确的。
```python
is_raining = True
is_sunny = False
is_adult = (age >= 18) # 括号里是一个比较表达式,结果是True或False
```
布尔值主要用在条件判断(if语句)中,我们会在第四篇详细学习。
布尔值的真谛:计算机世界归根结底是二进制的——0和1,开和关,是和否。布尔值就是这个基本逻辑在Python中的体现。
```python
# 一些返回布尔值的操作
print(10 > 5) # True
print(10 == 5) # False(注意是两个等号表示“等于比较”)
print(10 != 5) # True(!= 表示“不等于”)
```
2.5 type()函数——查看数据类型
有时候你不确定一个变量是什么类型,可以用type()函数查看:
```python
print(type(42)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type(True)) # <class 'bool'>
print(type(type(42))) # <class 'type'>(type本身的类型是type,有点绕,不必纠结)
```
2.6 类型转换(非常重要的技能)
有时候你需要把一种类型转换成另一种类型。比如:用户输入的数字默认是字符串,你需要把它转成整数才能做数学运算。
Python提供了几个内置转换函数:
函数 作用 示例
int(x) 转换为整数 int("123") → 123,int(3.9) → 3(截断小数)
float(x) 转换为浮点数 float("3.14") → 3.14,float(5) → 5.0
str(x) 转换为字符串 str(123) → "123",str(3.14) → "3.14"
bool(x) 转换为布尔值 bool(1) → True,bool(0) → False,bool("") → False
实际应用场景:
```python
# 数字转字符串(用于拼接)
age = 18
message = "我今年" + str(age) + "岁"
print(message) # 我今年18岁
# 如果不加str(),会报错:字符串和整数不能直接用+拼接
# 字符串转整数(用于计算)
user_input = "100" # 假设这是从input()获取的
bonus = int(user_input) + 50
print(bonus) # 150
# 浮点数转整数(取整)
price = 19.99
integer_price = int(price) # 19(注意是截断,不是四舍五入)
rounded = round(price) # 20(四舍五入)
```
布尔值转换的特殊规则:
```python
print(bool(0)) # False(零是False)
print(bool(1)) # True(非零是True)
print(bool(-5)) # True(负数也是True)
print(bool("")) # False(空字符串是False)
print(bool("Hi")) # True(非空字符串是True)
print(bool(None)) # False(None表示“空”,是False)
# 特别注意:只有空字符串 "" 是 False,任何非空字符串都是 True
print(bool("False")) # True(字符串"False"不是空字符串)
```
这条规则在实际编程中非常有用:你可以直接用if my_list:来判断列表是否为空,而不需要写if len(my_list) > 0:。
---
第三章:运算符——让变量动起来
变量不只是静态存储数据,更重要的是对它们进行操作。运算符就是操作的工具。
3.1 算术运算符(对数字操作)
运算符 名称 示例 结果
+ 加法 5 + 3 8
- 减法 5 - 3 2
* 乘法 5 * 3 15
/ 除法(浮点数) 5 / 2 2.5
// 整除(向下取整) 5 // 2 2
% 取余(模运算) 5 % 2 1
** 幂(乘方) 2 ** 3 8
详细说明每个运算符:
除法 /:总是返回浮点数,即使两个整数能整除:
```python
print(10 / 2) # 5.0(不是5,是浮点数5.0)
```
整除 //:返回商的整数部分(向下取整,即往负无穷方向取整):
```python
print(10 // 3) # 3
print(10 // 4) # 2
print(-10 // 3) # -4(因为-3.33向下取整是-4,这点和某些语言不同)
```
取余 %:返回除法后的余数,公式:a = (a // b) * b + (a % b)
```python
print(10 % 3) # 1(因为10 = 3*3 + 1)
print(17 % 5) # 2(17 = 5*3 + 2)
print(100 % 10) # 0(整除)
```
取余的实际用途:
· 判断奇偶:num % 2 == 0 表示偶数
· 循环周期:index % 10 得到0-9的循环
· 时间换算:total_seconds % 60 得到秒数(取余60)
幂 **:
```python
print(2 ** 10) # 1024(2的10次方)
print(9 ** 0.5) # 3.0(平方根)
print(8 ** (1/3)) # 2.0(立方根)
```
3.2 赋值运算符(给变量赋值)
你已经见过最基本的赋值运算符 =。
Python还提供了一系列复合赋值运算符,把运算和赋值合并在一起:
运算符 示例 等价于
+= x += 3 x = x + 3
-= x -= 3 x = x - 3
*= x *= 3 x = x * 3
/= x /= 3 x = x / 3
//= x //= 3 x = x // 3
%= x %= 3 x = x % 3
**= x **= 3 x = x ** 3
实际用法:
```python
count = 0
count += 1 # count现在是1(比写count = count + 1更简洁)
count += 5 # count现在是6
count *= 2 # count现在是12
money = 100
money -= 30 # 70
money /= 2 # 35.0(注意变成了浮点数)
```
复合赋值运算符让代码更简洁,尤其是做累加、累乘时。
3.3 比较运算符(返回布尔值)
比较运算符用于比较两个值,结果总是 True 或 False。
运算符 名称 示例 结果
== 等于 5 == 5 True
!= 不等于 5 != 3 True
> 大于 5 > 3 True
< 小于 5 < 3 False
>= 大于等于 5 >= 5 True
<= 小于等于 3 <= 5 True
重要提醒:==(两个等号)是比较,=(一个等号)是赋值。新手最常犯的错误就是把==写成=:
```python
# 错误示范(虽然不会报错,但逻辑错了)
if x = 5: # 这是赋值,不是比较!而且if语句里不能这样写,会报SyntaxError
```
正确的:
```python
if x == 5: # 判断x是否等于5
```
字符串也可以比较:比较的是字符的Unicode编码顺序(字典序):
```python
print("apple" == "apple") # True
print("apple" != "orange") # True
print("a" < "b") # True(a排在b前面)
print("abc" < "abd") # True(前两个字母相同,比较第三个,c < d)
print("Apple" < "apple") # True(大写字母的Unicode码小于小写字母)
```
3.4 逻辑运算符(组合布尔值)
逻辑运算符用来组合多个布尔条件。
运算符 名称 示例 结果
and 且(两个都为真才为真) True and True True
or 或(至少一个为真即为真) True or False True
not 非(取反) not True False
真值表(记住这些,以后不用查):
A B A and B A or B not A
True True True True False
True False False True False
False True False True True
False False False False True
实际例子:
```python
age = 20
has_license = True
# 可以开车的条件:年龄>=18 并且 有驾照
can_drive = age >= 18 and has_license
print(can_drive) # True
# 学生优惠条件:年龄<=12 或者 年龄>=65
is_child = age <= 12
is_elder = age >= 65
has_discount = is_child or is_elder
print(has_discount) # False
# 不是未成年人(年龄<18的反面)
is_adult = not (age < 18)
print(is_adult) # True
```
短路求值(Python的一个特性):
· and:如果左边已经是False,右边就不计算了(因为无论右边是什么,结果都是False)
· or:如果左边已经是True,右边就不计算了(因为结果已经是True)
这个特性在某些情况下很有用:
```python
# 安全地访问变量(避免错误)
name = None
# 如果name是None,name.upper()会报错,但用and可以短路
result = name and name.upper() # name是None(相当于False),所以直接返回None,不计算后面
print(result) # None
```
3.5 运算符优先级(谁先算?)
当你写一个复杂的表达式时,比如 2 + 3 * 4 ** 2,Python按照一定的顺序计算。这个顺序叫做运算符优先级。
从高到低(排名越靠前,越先计算):
1. 括号 ():最高优先级,强制先计算括号内的内容
2. 幂运算 **
3. 正负号 +x, -x(一元运算符)
4. 乘除 *, /, //, %
5. 加减 +, -
6. 比较 ==, !=, >, <, >=, <=
7. 逻辑非 not
8. 逻辑与 and
9. 逻辑或 or(最低)
示例:
```python
# 没有括号时的计算顺序
result = 2 + 3 * 4 ** 2
# 步骤:
# 1. 4 ** 2 = 16
# 2. 3 * 16 = 48
# 3. 2 + 48 = 50
print(result) # 50
# 加括号改变顺序
result = (2 + 3) * 4 ** 2
# 步骤:
# 1. (2+3) = 5
# 2. 4 ** 2 = 16
# 3. 5 * 16 = 80
print(result) # 80
```
最佳实践:当你对优先级不确定时,加括号。括号让代码更清晰,也避免出错。不要依赖记忆优先级。
```python
# 不清晰的写法
if age > 18 and has_license or is_supervisor:
# 实际逻辑是 (age>18 and has_license) or is_supervisor
# 但可能不是你想要的
# 清晰的写法
if (age > 18 and has_license) or is_supervisor:
# 意图一目了然
```
---
第四章:变量的高级玩法(但仍然很基础)
4.1 同时给多个变量赋值
Python支持一行代码给多个变量赋值:
```python
# 方式1:同时赋不同的值
a, b, c = 1, 2, 3
print(a, b, c) # 1 2 3
# 方式2:多个变量赋同一个值
x = y = z = 0
print(x, y, z) # 0 0 0
```
实用场景:交换两个变量的值
在其他语言中,交换两个变量需要第三个临时变量:
```c
// C语言写法
int temp = a;
a = b;
b = temp;
```
在Python中,一行搞定:
```python
a = 5
b = 10
a, b = b, a
print(a, b) # 10 5
```
这叫做元组解包(后面会学元组,现在先记住这个好用的小技巧)。
4.2 变量名的“标签”本质(理解这个很重要)
前面的“盒子”比喻有一定帮助,但严格来说不够准确。更准确的理解是:变量是贴在值上的标签。
当你写:
```python
a = [1, 2, 3]
b = a
```
并不是把列表复制了一份放到 b 的盒子里。而是:a 和 b 两个标签,贴在同一个列表对象上。
```python
a = [1, 2, 3] # 创建一个列表,贴上标签a
b = a # 把标签b也贴到同一个列表上
a.append(4) # 通过标签a修改列表
print(b) # [1, 2, 3, 4] —— b也看到了变化!
```
这跟数字、字符串的表现不一样:
```python
x = 10
y = x
x = 20
print(y) # 10(y没有变成20)
```
为什么?因为数字是不可变对象。x = 20 不是修改原本的10,而是把标签x撕下来,贴到了一个新的20对象上。y还贴在10上。
区分可变对象和不可变对象(这是Python新手常见的坑):
· 不可变类型:int, float, str, bool, tuple——赋值就是重新贴标签
· 可变类型:list, dict, set, 自定义对象——多个变量可以指向同一个对象
我们学到列表时会再次强调这个问题。
4.3 常量(用大写字母表示,但Python没有真正的常量)
“常量”是值不会改变的变量。Python没有语法层面的常量(不能强制禁止修改),但约定俗成:用全大写字母命名的变量视为常量,不应该修改。
```python
# 这些是常量(按约定)
PI = 3.14159
MAX_SIZE = 100
DATABASE_URL = "localhost:5432"
# 技术上你可以修改它,但不要这样做
# PI = 3.14 # 虽然不会报错,但破坏了约定
```
4.4 动态类型 vs 静态类型
Python是动态类型语言:一个变量可以在不同时间存储不同类型的值。
```python
something = 42 # 整数
print(type(something)) # int
something = "hello" # 现在是字符串(完全合法)
print(type(something)) # str
something = True # 现在是布尔值
```
而像Java、C++是静态类型语言:变量类型一旦声明就不能改变。
动态类型的优点:灵活、代码简洁
动态类型的缺点:大型项目中可能难以追踪类型,容易产生运行时错误(Python 3.5+引入了“类型注解”来解决这个问题,但不强制)
---
第五章:输入函数 input()——让程序跟用户对话
有了变量和输入,程序才能真正“活起来”——不再只是输出固定内容,而是根据用户的输入做出不同反应。
5.1 input() 的基本用法
input() 函数让程序暂停,等待用户输入一行文字,用户按回车后,输入的内容被作为字符串返回。
```python
name = input("请输入你的名字:")
print("你好," + name)
```
运行效果:
```
请输入你的名字:小明
你好,小明
```
注意:input() 括号里的字符串是提示文字,会显示在屏幕上。不写也可以,但最好写,让用户知道要输入什么。
5.2 input() 返回的一定是字符串
这是新手最容易犯的错误之一:
```python
age = input("请输入你的年龄:") # 用户输入 18
print(age + 10) # 报错!TypeError: can only concatenate str to str
```
因为 age 是字符串 "18",不能直接和整数10相加。
解决方法:用类型转换函数
```python
age = input("请输入你的年龄:")
age_int = int(age) # 转换为整数
print(age_int + 10) # 28
# 或者一步到位
age = int(input("请输入你的年龄:"))
print(age + 10)
```
注意:如果用户输入的不是数字,int() 会报错(ValueError)。如何优雅地处理这种情况?我们会学到异常处理(try/except),或者在第四篇学到条件判断后可以验证用户输入。
5.3 一个完整的交互式程序示例
让我们把目前学到的所有知识组合起来,写一个真正“有用”的程序:
```python
# 简单计算器(BMI体重指数计算器)
print("=" * 30)
print(" 欢迎使用BMI计算器")
print("=" * 30)
# 获取用户输入
name = input("请输入你的名字:")
height = float(input("请输入你的身高(米):")) # 例如 1.75
weight = float(input("请输入你的体重(公斤):")) # 例如 70
# 计算BMI
bmi = weight / (height ** 2)
# 输出结果
print("-" * 30)
print(f"{name},你的BMI指数是:{bmi:.2f}") # :.2f 表示保留2位小数
# 简单判断(BMI标准,中国参考)
if bmi < 18.5:
print("体重过轻")
elif bmi < 24:
print("正常范围")
elif bmi < 28:
print("超重")
else:
print("肥胖")
print("-" * 30)
```
这个程序使用了:
· 变量(name, height, weight, bmi)
· 类型转换(float())
· 算术运算(/, **)
· 格式化输出(f-string + :.2f)
· 条件判断(if-elif-else,虽然还没正式讲,但你应该能猜出意思)
💡 不用担心上面的 if 语句看不懂。现在你只需要感受一下“程序可以根据条件做出不同反应”这个能力。下一整篇我们都会详细拆解它。如果你实在好奇,可以试着把 bmi 改成不同的值(比如 15 或 30),看看输出会怎么变化。
运行示例:
```
==============================
欢迎使用BMI计算器
==============================
请输入你的名字:张三
请输入你的身高(米):1.75
请输入你的体重(公斤):70
------------------------------
张三,你的BMI指数是:22.86
正常范围
------------------------------
```
5.4 输入多个值(一次输入,用split拆分)
有时候你想让用户一次输入多个值,比如“姓名 年龄 城市”。可以用 .split() 方法拆分:
```python
# 用户输入:张三 25 北京(推荐使用空格分隔)
data = input("请输入姓名、年龄、城市(用空格分隔):")
parts = data.split() # 默认按空白字符(空格、制表符等)拆分
name = parts[0]
age = int(parts[1])
city = parts[2]
print(f"{name},{age}岁,来自{city}")
```
.split() 返回一个列表(后面会专门讲),[0] 表示第一个元素。
---
第六章:f-string——最优雅的格式化输出
你已经见过 print("你好," + name) 这种用 + 拼接字符串的方式。这种方式在变量多的时候会很麻烦:
```python
name = "张三"
age = 18
city = "北京"
print("我叫" + name + ",今年" + str(age) + "岁,来自" + city)
```
需要小心处理类型转换(age要转成字符串)和加号的位置。
f-string(格式化字符串字面量) 是Python 3.6引入的特性,让这一切变得简单优雅。
6.1 基本用法
在字符串前面加上 f 或 F,然后在字符串内部用 {变量名} 嵌入变量:
```python
name = "张三"
age = 18
city = "北京"
print(f"我叫{name},今年{age}岁,来自{city}")
```
输出:我叫张三,今年18岁,来自北京
不需要 +,不需要 str(age),f-string会自动处理。
6.2 在 {} 里写表达式
{} 里不只是可以放变量名,还可以放任何Python表达式:
```python
price = 49
quantity = 3
print(f"总价:{price * quantity}元") # 总价:147元
score = 85
print(f"及格了吗:{score >= 60}") # 及格了吗:True
print(f"明年我就{age + 1}岁了") # 明年我就19岁了
```
6.3 格式化数字(控制小数位数、千位分隔符等)
```python
pi = 3.1415926535
print(f"π ≈ {pi:.2f}") # π ≈ 3.14(保留2位小数)
print(f"π ≈ {pi:.4f}") # π ≈ 3.1416(保留4位,会四舍五入)
percentage = 0.856
print(f"成绩:{percentage:.1%}") # 成绩:85.6%(百分比格式)
big_number = 12345678
print(f"数字:{big_number:,}") # 数字:12,345,678(千位分隔符)
# 对齐
name = "小明"
score = 98
print(f"{name:>10}:{score}") # 右对齐,总宽度10:' 小明:98'
print(f"{name:<10}:{score}") # 左对齐:'小明 :98'
print(f"{name:^10}:{score}") # 居中对齐:' 小明 :98'
```
6.4 f-string vs 其他格式化方式
Python有多种字符串格式化方式,你可能会在旧代码中看到:
```python
# 方式1:%格式化(老式,来自C语言)
print("我叫%s,今年%d岁" % (name, age))
# 方式2:.format()方法(Python 2.6+)
print("我叫{},今年{}岁".format(name, age))
# 方式3:f-string(Python 3.6+,推荐)
print(f"我叫{name},今年{age}岁")
```
建议:新代码一律使用f-string,除非你需要兼容Python 3.5或更早版本(现在已经很少见了)。f-string最简洁、最直观、性能也最好。
---
第七章:变量的作用域(简单了解)
作用域(scope)是一个变量“能见度”的范围——在哪里可以访问这个变量,在哪里不行。
目前我们只写简单的单行或几行代码,还没有定义函数或类,所以所有变量都是全局作用域(在整个文件中都可以访问)。
但为了给将来打基础,简单了解一下:
```python
# 全局变量(在函数外部定义的)
global_var = 100
def my_function():
# 局部变量(在函数内部定义的)
local_var = 50
print(global_var) # 可以访问全局变量
print(local_var) # 可以访问局部变量
my_function()
# print(local_var) # 报错!NameError,外部无法访问函数内部的局部变量
```
变量查找规则(LEGB规则):
1. Local:函数内部
2. Enclosing:外层嵌套函数
3. Global:模块全局
4. Built-in:内置名称(如print、len)
现在你不需要死记这些,只需要知道:函数内部定义的变量,函数外部不能用。这个规则以后学了函数再深入。
---
第八章:动手做项目——用变量写几个实用小程序
光看不练假把式。这一章我们来写几个真正有用的小程序,把前面学的变量、输入、输出、运算全部用上。
项目1:秒数转换器
功能:输入一个秒数(比如3665秒),转换成“X小时Y分钟Z秒”的格式。
代码:
```python
# 秒数转换器
total_seconds = int(input("请输入秒数:"))
hours = total_seconds // 3600 # 1小时 = 3600秒
remaining = total_seconds % 3600
minutes = remaining // 60
seconds = remaining % 60
print(f"{total_seconds}秒 = {hours}小时{minutes}分钟{seconds}秒")
```
运行示例:
```
请输入秒数:3665
3665秒 = 1小时1分钟5秒
```
知识点:整除//、取余%、类型转换int()、f-string。
项目2:简单的对话机器人
功能:问用户几个问题,然后根据回答生成一段个性化的回复。
代码:
```python
# 对话机器人
print("你好!我是小P机器人。让我们聊几句吧。")
name = input("你叫什么名字?")
age = int(input("你今年多大了?"))
hobby = input("你平时喜欢做什么?")
city = input("你现在住在哪个城市?")
print("\n" + "=" * 40)
print(f"很高兴认识你,{name}!")
print(f"你今年{age}岁,{'是个年轻人' if age < 30 else '是个成熟的人'}。")
print(f"喜欢{hobby}是个不错的爱好。")
print(f"希望以后有机会去{city}看看。")
print("=" * 40)
```
运行示例:
```
你好!我是小P机器人。让我们聊几句吧。
你叫什么名字?李华
你今年多大了?25
你平时喜欢做什么?打篮球
你现在住在哪个城市?上海
========================================
很高兴认识你,李华!
你今年25岁,是个年轻人。
喜欢打篮球是个不错的爱好。
希望以后有机会去上海看看。
========================================
```
知识点:input()、类型转换、f-string、条件表达式(x if condition else y,这是简化的if-else)。
项目3:简单的购物车计算器
功能:输入商品的价格和数量,计算总价,并添加一定比例的税费。
代码:
```python
# 购物车计算器
print("简易购物车")
print("-" * 30)
item1_name = input("商品1名称:")
item1_price = float(input("商品1单价:"))
item1_qty = int(input("商品1数量:"))
item2_name = input("商品2名称:")
item2_price = float(input("商品2单价:"))
item2_qty = int(input("商品2数量:"))
item3_name = input("商品3名称:")
item3_price = float(input("商品3单价:"))
item3_qty = int(input("商品3数量:"))
# 计算小计
subtotal1 = item1_price * item1_qty
subtotal2 = item2_price * item2_qty
subtotal3 = item3_price * item3_qty
subtotal = subtotal1 + subtotal2 + subtotal3
# 计算税费(假设10%)
tax_rate = 0.10
tax = subtotal * tax_rate
# 总计
total = subtotal + tax
# 输出购物清单
print("\n" + "=" * 40)
print("购物清单")
print("=" * 40)
print(f"{item1_name} x{item1_qty}:{subtotal1:.2f}元")
print(f"{item2_name} x{item2_qty}:{subtotal2:.2f}元")
print(f"{item3_name} x{item3_qty}:{subtotal3:.2f}元")
print("-" * 40)
print(f"小计:{subtotal:.2f}元")
print(f"税费({tax_rate*100:.0f}%):{tax:.2f}元")
print(f"总计:{total:.2f}元")
print("=" * 40)
```
运行示例:
```
简易购物车
------------------------------
商品1名称:苹果
商品1单价:5.5
商品1数量:3
商品2名称:香蕉
商品2单价:4.0
商品2数量:2
商品3名称:牛奶
商品3单价:12.0
商品3数量:1
========================================
购物清单
========================================
苹果 x3:16.50元
香蕉 x2:8.00元
牛奶 x1:12.00元
----------------------------------------
小计:36.50元
税费(10%):3.65元
总计:40.15元
========================================
```
知识点:浮点数运算、格式化输出(.2f)、税率计算。
---
第九章:常见陷阱与调试(进阶版)
陷阱1:忘记转换input()的类型
```python
# 错误
age = input("年龄:")
next_year = age + 1 # TypeError
# 正确
age = int(input("年龄:"))
```
陷阱2:混淆 = 和 ==
```python
# 错误(在if语句中)
if x = 5: # SyntaxError,应该用 ==
# 正确
if x == 5:
```
陷阱3:浮点数精度问题导致的逻辑错误
```python
# 你可能以为下面会输出True
print(0.1 + 0.2 == 0.3) # False!
# 解决方法:使用一个误差范围
epsilon = 1e-10
print(abs((0.1 + 0.2) - 0.3) < epsilon) # True
```
陷阱4:变量名覆盖内置函数
```python
# 错误
list = [1, 2, 3] # 覆盖了list()函数
new_list = list("abc") # 报错!因为list不再是类型构造函数了
# 正确
my_list = [1, 2, 3]
new_list = list("abc") # 正常工作
```
陷阱5:可变对象的“意外修改”
```python
# 错误(以为list2是list1的副本)
list1 = [1, 2, 3]
list2 = list1
list2.append(4)
print(list1) # [1, 2, 3, 4] —— list1也被改了!
# 正确:创建副本
list1 = [1, 2, 3]
list2 = list1.copy() # 或 list(list1) 或 list1[:]
list2.append(4)
print(list1) # [1, 2, 3]
```
陷阱6:字符串和数字用+拼接
```python
# 错误
print("答案:" + 42) # TypeError
# 正确
print("答案:" + str(42))
print(f"答案:{42}") # 最佳
```
---
第十章:巩固练习(强化篇)
练习1:基础变量操作
1. 创建变量 age 赋值为你的年龄,height 赋值为你的身高(米),weight 赋值为你的体重(公斤)。
2. 计算你的BMI指数(weight / height**2),并用print输出。
3. 修改 age 的值,增加1岁,输出新的年龄。
练习2:变量交换
给定 a = 10, b = 20,交换两个变量的值,使 a = 20, b = 10。用一行代码实现。
练习3:类型转换练习
```python
s1 = "123"
s2 = "456.78"
s3 = "True"
```
将s1转换为整数,s2转换为浮点数,s3转换为布尔值。输出每个转换后的结果和类型。
练习4:温度转换器
编写程序,接收用户输入的摄氏温度(Celsius),转换成华氏温度(Fahrenheit)并输出。
公式:F = C * 9/5 + 32
示例:输入 25,输出 77.0华氏度
练习5:找零计算器
你购买了一件商品,价格是 price 元,你支付了 paid 元(paid >= price)。计算找零金额,并输出需要找回多少张10元、5元、1元纸币(假设只有这三种面额)。
提示:用整除 // 和取余 %。
示例:price=37, paid=100,找零63元 → 6张10元、0张5元、3张1元。
练习6:圆的面积和周长
接收用户输入的半径 r(浮点数),计算并输出圆的面积和周长。
公式:面积 π * r²,周长 2 * π * r。π 取 3.14159。
输出格式(保留2位小数):
```
半径:5.00
面积:78.54
周长:31.42
```
练习7:平均分计算
接收用户输入的三个科目的成绩(整数或浮点数),计算平均分并输出。
额外挑战:输出时保留1位小数。
练习8:个人简介生成器
接收用户输入:姓名、出生年份、城市、职业。输出一段个人简介,格式如下:
```
大家好,我是[姓名],[计算年龄]岁,来自[城市],是一名[职业]。很高兴认识大家!
```
提示:当前年份可以用固定值(比如2026),也可以导入datetime模块获取当前年份(但这是后面章节的内容)。
练习9:数值交换(不用第三个变量)
a和b是两个整数,在不使用第三个变量的前提下交换它们的值。
💡 提示:用加减法需要处理溢出问题(但Python整数无溢出);用异或需要理解位运算,对新手较难。这个练习的目的是让你体会Python的简洁之美——a, b = b, a 就是最好的实践。如果做不出来也没关系,知道有别的办法存在即可。
练习10:综合挑战——简单计算器
编写一个简单的计算器程序:
1. 接收用户输入的第一个数字
2. 接收用户输入的运算符(+, -, *, /)
3. 接收用户输入的第二个数字
4. 根据运算符进行计算并输出结果
5. 如果是除法,除数为0时输出“错误:除数不能为0”
示例运行:
```
请输入第一个数字:10
请输入运算符(+ - * /):*
请输入第二个数字:5
10 * 5 = 50
```
(这个练习需要用if语句判断运算符,可以提前尝试,或等第四篇后再做)
---
第十一章:总结与下一站
你在这38,000字中学到的核心内容
1. 变量:
· 什么是变量(名字=值)
· 赋值运算符 =
· 变量命名规则(字母、数字、下划线,不能数字开头,不能是关键字,不能含点号)
· 同时赋多个值
2. 数据类型:
· int:整数
· float:浮点数(注意精度问题)
· str:字符串(引号,拼接+,重复*,长度len())
· bool:布尔值(True/False)
· type() 查看类型
· 类型转换(int(), float(), str(), bool())
3. 运算符:
· 算术:+ - * / // % **
· 复合赋值:+= -= *= /= //= %= **=
· 比较:== != > < >= <=
· 逻辑:and or not
· 优先级(用括号最保险)
4. 输入输出:
· input() 获取用户输入(返回字符串)
· print() 输出
· f-string 格式化输出(f"{var}"、{var:.2f})
5. 动手项目:
· 秒数转换器
· 对话机器人
· 购物车计算器
一个重要的思维转变
学完这一篇,你应该开始意识到:
编程不是在写“固定的话”,而是在描述“规则”和“关系”。
之前你写 print("我有100元"),输出永远是“我有100元”。
现在你可以写:
```python
money = 100
print(f"我有{money}元")
```
然后改变 money 的值,输出也会自动改变。你的程序从“硬编码”变成了“参数化”。
这是从“复读机”到“智能体”的关键一步。
下一篇预告:条件判断——让程序自己“做决定”
到目前为止,我们的程序都是线性的——从上到下执行每一行,没有分支。
但现实世界不是线性的:
· 如果今天下雨,我就带伞;否则不带
· 如果成绩 >= 60,就及格;否则不及格
· 如果用户输入的是数字,就计算;否则提示错误
在第四篇,你将学到:
· if、elif、else 语句
· 条件表达式
· 嵌套判断
· 让程序根据不同情况执行不同的代码
到时候,你的程序就能真正“思考”了——虽然只是最简单的“是/否”判断,但这是人工智能的起点。
最后的鼓励
变量是编程世界的基本粒子。你现在就像学会了化学元素周期表里的前20个元素——虽然还不能合成复杂的分子,但你已经有了构建一切的基础。
给新手的三个建议:
1. 每天写代码,哪怕只有10分钟。编程是技能,不是知识。看100遍不如写1遍。
2. 不要复制粘贴。手动敲每一个字符,肌肉记忆很重要。
3. 遇到错误是好事。每一次报错都在告诉你“Python的思考方式是这样的”,你在学习一门新语言,犯错是必经之路。
如果你读到这里并且动手敲了每一个代码示例,你已经超过了99%的人。
下一篇见。如果你读到了这里,给自己一个肯定——你已经超过了90%的人,因为大多数人连第二篇都没读完。
休息一下,然后继续前进。
---