大家好,我是煜道。
今天我们一起来学习 变量与运算符。
引言
变量是程序中存储数据的基本单元,而运算符则是对数据进行运算的符号。 在任何编程语言中,理解变量和运算符的工作原理都是编程的基础。Python的变量和运算符设计简洁直观,但背后蕴含着值得深入理解的原理。
本文将详细探讨Python变量的本质、命名规则、内存模型,以及各类运算符的行为特性。特别关注值类型与引用类型的区别、运算符的优先级与结合性,以及Python特有的身份运算符等知识点。

01 变量的本质
1.1 变量是什么
在Python中,变量实际上是一个名字(标识符),它绑定到一个对象上。变量与对象的关系可以类比为标签与物品:变量是贴在物品上的标签,标签可以贴在不同的物品上,也可以被取下。
a = 10# 创建一个整数对象10# 将变量名a绑定到该对象a = 20# 创建新的整数对象20# 将变量名a重新绑定到新对象# 原对象10如果没有其他引用,将被垃圾回收

1.2 变量命名规则
Python标识符(变量名、函数名、类名等)的命名规则:
- 必须以字母(a-z, A-Z)或下划线(_)开头。
# 合法的变量名name = "Python"_age = 25version_3_12 = True__private_var = 100# 非法的变量名# 2nd_place = "silver" # 不能以数字开头# class = "test" # 不能使用关键字
1.3 Python关键字
Python保留了一组关键字,这些关键字有特殊的语法含义,不能用作变量名:
import keywordprint(keyword.kwlist)# ['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']
1.4 命名惯例
虽然Python不强制命名风格,但社区形成了一些惯例:
| | |
|---|
| | user_name |
| | UserInfo |
| | MAX_SIZE |
| | _private_method |
| | __private_var |
| | class_ |

02 值类型与引用类型
2.1 可变对象与不可变对象
Python中的对象可以分为可变对象和不可变对象:
| | |
|---|
| int, float, str, tuple, bool, frozenset | |
| list, dict, set, bytearray | |
# 不可变对象s = "hello"# s[0] = 'H' # TypeError: str object does not support item assignments = "Hello"# 创建新对象# 可变对象lst = [1, 2, 3]lst[0] = 100# 允许修改print(lst) # [100, 2, 3]
2.2 值传递与引用传递
Python采用"对象引用传递"方式。当将变量赋值给另一个变量时,两者指向同一个对象:
# 不可变对象a = 10b = aa = 20print(b) # 10(b不受影响)# 可变对象lst1 = [1, 2, 3]lst2 = lst1lst1[0] = 100print(lst2) # [100, 2, 3](lst2也改变)

2.3 浅拷贝与深拷贝
处理可变对象时,经常需要创建副本:
original = [1, [2, 3], 4]# 浅拷贝:只复制第一层shallow = original.copy()shallow[0] = 100# 修改不影响原列表shallow[1].append(5) # 影响原列表(嵌套对象相同)print(original) # [1, [2, 3, 5], 4]# 深拷贝:递归复制所有层级import copydeep = copy.deepcopy(original)deep[1].append(6) # 不影响原列表print(original) # [1, [2, 3, 5], 4]# 切片拷贝(浅拷贝)shallow2 = original[:]
2.4 元组的特殊性
元组虽然不可变,但如果包含可变元素,则元素本身可以被修改:
t = (1, [2, 3], 4)# t[0] = 100 # 错误:元组不可变t[1].append(100) # 允许:修改元组内的列表print(t) # (1, [2, 3, 100], 4)

03 运算符分类
3.1 运算符一览
Python的运算符可以分为以下几类:

3.2 算术运算符
a = 10b = 3# 基本算术print(a + b) # 13print(a - b) # 7print(a * b) # 30print(a / b) # 3.333...(浮点数)print(a // b) # 3(整除)print(a % b) # 1(取余)print(a ** b) # 1000(幂)# 字符串算术s = "Python"print(s + " 3.12") # 拼接print(s * 3) # 重复:"PythonPythonPython"# 列表算术lst = [1, 2]print(lst + [3, 4]) # [1, 2, 3, 4]print(lst * 2) # [1, 2, 1, 2]
3.3 比较运算符
比较运算符可以链式使用:
# 基本比较print(10 > 5) # Trueprint(10 == 10) # Trueprint(10 != 5) # True# 链式比较(Python特性)print(1 < 2 < 3) # True(等价于1<2 and 2<3)print(10 < 20 > 15) # Trueprint(1 == 2 < 3) # True(2<3为True,再与1==比较)# 不同类型比较print(10 < "20") # TypeError(Python 3不允许)print(10 == 10.0) # True(不同数值类型可比较)print([1, 2] < [1, 3]) # True(列表逐元素比较)
3.4 逻辑运算符
逻辑运算符遵循短路求值规则:
# and:全真为真print(TrueandTrue) # Trueprint(TrueandFalse) # Falseprint(3and5) # 5(返回最后一个真值)print(0and5) # 0(短路:遇到0即返回)# or:一真为真print(TrueorFalse) # Trueprint(FalseorFalse) # Falseprint(3or5) # 3(返回第一个真值)print(0or5) # 5# not:取反print(notTrue) # Falseprint(not0) # Trueprint(not []) # True(空列表为假)# 实际应用defdivide(a, b):return b != 0and a / b # 短路避免除零错误print(divide(10, 2)) # 5.0print(divide(10, 0)) # False

3.5 位运算符
位运算符直接操作整数的二进制位:
x = 0b1100# 12y = 0b1010# 10# 按位与print(x & y) # 0b1000 = 8# 按位或print(x | y) # 0b1110 = 14# 按位异或print(x ^ y) # 0b0110 = 6# 按位取反print(~x) # -13(补码表示)# 左移print(x << 2) # 0b110000 = 48# 右移print(x >> 2) # 0b11 = 3# 实用技巧# 判断奇偶n = 10print(n & 1) # 0(偶数)print(9 & 1) # 1(奇数)# 快速乘除2print(10 << 1) # 20(乘2)print(10 >> 1) # 5(除2)# 交换数值a = 5b = 10a ^= bb ^= aa ^= bprint(a, b) # 10, 5
3.6 成员运算符
成员运算符测试值是否在序列中:
# in运算符s = "Python"print('P'in s) # Trueprint('p'in s) # False(大小写敏感)print('th'in s) # Truelst = [1, 2, 3, 4, 5]print(3in lst) # Trueprint(6in lst) # Falsed = {'a': 1, 'b': 2}print('a'in d) # True(测试键)print(1in d) # False# not inprint('z'notin s) # True
3.7 身份运算符
身份运算符is和is not用于比较对象的身份(内存地址):
# == 比较值# is 比较身份(内存地址)a = [1, 2, 3]b = [1, 2, 3]c = aprint(a == b) # True(值相等)print(a is b) # False(不同对象)print(a is c) # True(同一个对象)# 小整数缓存x = 257y = 257print(x is y) # False(超出缓存范围)x = 256y = 256print(x is y) # True(在缓存范围内)# None判断val = Noneprint(val isNone) # Trueprint(val isnotNone) # False

3.8 三元表达式
Python的三元表达式语法独特:
# 语法:value_if_true if condition else value_if_falsex = 10y = 20max_val = x if x > y else y # 20min_val = x if x < y else y # 10# 嵌套使用status = "正数"if x > 0else"零"if x == 0else"负数"

04 运算符优先级
4.1 优先级表
从高到低的运算符优先级:
| |
|---|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| ==, !=, >, <, >=, <=, is, is not, in, not in(比较) |
| |
| |
| |
4.2 使用建议
当不确定优先级时,使用括号明确意图:
# 清晰写法result = (a + b) * cresult = (x > 0) and (y > 0)# 依赖优先级(可能引起困惑)result = a + b * cresult = a and b or c


05 赋值语句详解
5.1 简单赋值
a = 10# 基本赋值a = b = 10# 链式赋值(都指向同一对象)a, b = 10, 20# 元组解包a, b = b, a # 交换值
5.2 增强赋值
a = 10a += 5# 等价于 a = a + 5a -= 3a *= 2a /= 2a //= 2a %= 3a **= 2# 注意:对于不可变对象,增强赋值会创建新对象x = 10print(id(x)) # 140...x += 5print(id(x)) # 不同的地址
5.3 解包赋值
# 基本解包a, b, c = 1, 2, 3# 使用*号收集多余元素first, *rest = [1, 2, 3, 4, 5]print(first, rest) # 1 [2, 3, 4, 5]*beginning, last = [1, 2, 3, 4, 5]print(beginning, last) # [1, 2, 3, 4] 5first, middle, last = [1, 2, 3]print(first, middle, last) # 1 2 3# 扩展解包(Python 3)a, *b, c = [1, 2, 3, 4, 5]print(a, b, c) # 1 [2, 3, 4] 5

06 小结
本文深入探讨了Python的变量和运算符:
- 值类型与引用类型:不可变对象与可变对象在赋值时的行为差异
- 运算符分类:算术、比较、逻辑、位、赋值、成员、身份运算符
理解这些基础知识对于编写正确的Python代码至关重要,也为后续学习函数式编程、面向对象等高级主题打下基础。
