8 个概念建立 Python 思维
AI 能替你写代码,但替不了你拆解问题、表达逻辑、检查结果。编程思维才是驾驭 AI 的底层能力。
学 Python 最怕什么?不是语法记不住,而是脑子里没有"程序怎么想"的框架。这篇文章用 8 个概念帮你建立这个框架。零基础也能看懂,每个概念都拆到最细。
1. 变量与赋值 —— 程序怎么"记住"东西
等号不是"相等",是"存入"
数学里的等号表示左边等于右边。程序里不是。程序里的 = 叫赋值号,意思是:把右边的结果,放进左边的盒子里。
- x = 10 → 创建一个叫 x 的盒子,把 10 放进去
- x = x + 1 → 把 x 盒子里的值(10)拿出来,加上 1,再放回去。现在 x 里是 11
数学上 x = x + 1 不可能成立,程序里这再正常不过。
三个关键规则
规则一:变量可以反复更新。同一行下面的代码,看到的永远是最新的值。程序从上到下一行行执行,不是同时执行。
规则二:先定义,后使用。不能用一个还没创建过的变量名——Python 不认识它。
规则三:取名要表意。a = 3.14 不如 pi = 3.14。代码是写给人看的,顺便给机器跑。
一把手的交换
Python 里可以同时给多个变量赋值,这是它独特的便利。
2. 条件与布尔逻辑 —— 程序怎么"做选择"
两种答案:True 或 False
程序做决策的方式极其简单:任何判断,最终只出两个结果——是(True)或否(False)。这种"非黑即白"的值叫布尔值。
5 > 3# True10 == 20# False(注意:双等号是比较,单等号是赋值)”猫” == ”狗”# False
if 让程序分岔
score = 85if score >= 90: print(”优秀”)elif score >= 80: print(”良好”)else: print(”继续加油”)
执行逻辑:从上到下检查,哪个条件先为 True 就执行哪块,后面全跳过。如果都不满足且有 else,就走 else。
组合条件
- and:两边都 True 才 True("而且")
- or:任意一边 True 就 True("或者")
if age >= 18 and has_ticket: print(”可以入场”)
缩进决定"谁属于谁"
Python 用缩进(行首空白)表示代码块的归属关系。同一个缩进层级的代码属于同一块。这不是为了好看——缩进错了,逻辑就错了。
3. 列表 —— 一组数据怎么"打包"
为什么需要列表
假设你要存一个班 50 个人的成绩。不用列表你得写 score1, score2, ... score50,用列表只要一个名字:
scores = [85, 92, 78, 90, 88]
列表就是一个有顺序的容器,里面可以放任意数量、任意类型的值。
核心操作
索引为什么从 0 开始?
把索引理解为"距离第一个元素的偏移量":第一个元素偏移为 0,第二个偏移为 1……这样底层的地址计算正好是 起始地址 + 偏移量。
实战思路:处理一段文本
”罗密欧与朱丽叶”全文 → 清洗标点 → split() 切分成单词列表 → 统计词频
"hello world".split() → ["hello", "world"],字符串瞬间变成列表,每个单词是一个元素。
4. for 循环与 range —— 重复的事情交给程序
循环解决什么问题
代码里如果出现同一模式反复写,就该用循环。循环的本质是:写出一次规则,让程序自动重复 N 次。
# 不用循环:手写 100 行print(”第1遍”)print(”第2遍”)...print(”第100遍”)# 用循环:3 行for i in range(1, 101): print(f”第{i}遍”)
直接遍历 vs 用索引遍历
fruits = [”苹果”, ”香蕉”, ”橘子”]# 方式一:直接拿元素(只读,不关心位置)for fruit in fruits: print(fruit)# 方式二:拿索引(需要位置信息或要修改原列表时)for i in range(len(fruits)): fruits[i] = fruits[i] + ”很好吃”
什么时候用哪种?只读元素 → 直接遍历。要修改原列表 → range(len(列表))。
range 怎么理解
range(5) → 0, 1, 2, 3, 4(从 0 开始,不包含 5,共 5 个)range(2, 6) → 2, 3, 4, 5(从 2 开始,不包含 6)range(1, 10, 2) → 1, 3, 5, 7, 9(步长为 2)
始终记住:包前不包后。
嵌套循环
# 生成一副扑克牌suits = [”♠”, ”♥”, ”♦”, ”♣”]ranks = [”A”, ”2”, ..., ”K”]for suit in suits: for rank in ranks: print(suit + rank)
外层循环每走一步,内层循环走完一整圈。两层循环 → 所有组合全覆盖。
5. 函数 —— 把逻辑"打包"成一块积木
输入 → 处理 → 输出
函数就是三件事:接收输入(参数)→ 内部处理 → 返回输出(返回值)。
def add(a, b):# def 定义,a, b 是参数 result = a + b# 内部运算 return result# 把结果交出去sum = add(3, 5)# 调用函数,3 传给了 a,5 传给了 bprint(sum)# 8
两个极易混淆的点
print 不是 return。print 只是在屏幕上显示给你看,值并没有被"交出来"给调用者用。return 才是把结果真正交给调用方,后续代码可以接着用这个结果。
return 会立即终止函数。return 后面的代码不会执行——函数"下班了"。
def demo(): return ”这行之后的所有代码都不会执行” print(”这句话永远不会被打印”)
定义 ≠ 执行
这三行代码没有输出任何东西——它只是定义了一个函数,存起来备用。只有当你写 greet() 时,函数才会真正运行。
局部变量与全局变量
函数内部定义的变量,函数外面拿不到——这叫局部变量,每个函数有自己的"小世界"。函数外面定义的变量,函数里面可以读,但如果要在函数里修改它,需要用 global 关键字声明。
函数的真正价值
不是省几行代码,而是把大问题拆成小问题。一个 100 行的函数很难读;十个 10 行的函数,每个只做一件事,组合起来就清晰得多。
6. 值与引用 —— 两个变量会不会"互相牵连"
关键区别
# 数字、字符串——赋值后各自独立a = 10b = a# b 得到的是 a 当时的值:10a = 20# 改 a 不影响 bprint(b)# 还是 10# 列表——赋值后共享同一个对象x = [1, 2, 3]y = x# y 和 x 指向同一个列表x[0] = 999# 通过 x 修改print(y)# [999, 2, 3] ← y 也变了!
为什么这样设计
数字、字符串这类简单数据,赋值时直接复制值——因为数据量小,复制不贵。
列表可能存海量数据,如果每次赋值都完整复制,内存和时间都受不了。所以 Python 选择共享同一个对象——这叫"引用"。y = x 实际上说的是"y 也指向 x 指向的那个列表"。
函数传参也同理
把列表传给函数,函数内部修改列表,外面的原列表也会变。因为传进来的不是副本,是指向原列表的引用。
def add_item(lst, item): lst.append(item)my_list = [1, 2]add_item(my_list, 3)print(my_list)# [1, 2, 3] ← 被改了
真要复制怎么办
new_list = old_list.copy()# 浅拷贝,两者从此互不影响
7. 字典 —— 用"名字"找东西,而不是"编号"
列表的局限
person = [”张三”, 25, ”北京”, ”程序员”]# 拿到年龄:person[1] ← 你怎么记住 1 是年龄?
列表用数字索引,读代码的人得记住第几个是啥——不人性。
字典用"键"代替编号
person = { ”姓名”: ”张三”, ”年龄”: 25, ”城市”: ”北京”, ”职业”: ”程序员”}print(person[”年龄”])# 25 —— 一目了然
字典是键值对的集合:每个值都配一把钥匙(键),用钥匙来找值,而不是用位置编号。这更贴近人的思维方式——"把名字和对应的事物关联起来"。
核心操作
d = {}# 创建空字典d[”name”] = ”Alice”# 添加 / 修改print(d[”name”])# 访问(键不存在会报错)print(d.get(”name”, ”未找到”))# 安全访问(键不存在返回默认值)del d[”name”]# 删除# 遍历for key in d.keys():# 遍历所有键for value in d.values():# 遍历所有值for key, value in d.items():# 同时遍历键和值
实战:统计《哈利·波特》角色出场次数
text = ”哈利波特和赫敏一起...哈利波特遇到...”words = text.split()count = {}for word in words: if word in count: count[word] += 1# 出现过,次数 +1 else: count[word] = 1# 第一次出现,记 1# count = {”哈利波特”: 127, ”赫敏”: 89, ...}
用字典来做"统计"是最高频的实战模式之一。
8. 递归 —— 函数自己调用自己
一句话理解
递归就是把一个大问题,不断缩小成同类的小问题,缩到不能再缩时直接给出答案。
两个必要零件
递归必须同时具备:
少了基本情况 → 无限调用 → 程序崩溃。少了递归情况 → 根本不会递归。
阶乘是最经典的例子
阶乘定义:n! = n × (n-1) × (n-2) × ... × 1,且 1! = 1。
这个定义已经自带递归结构:
def factorial(n): if n == 1:# 基本情况:缩到头了 return 1 return n * factorial(n - 1)# 递归情况:n! = n × (n-1)!
执行过程可视化(调用栈)
以 factorial(3) 为例:
factorial(3)→ 3 * factorial(2)# 暂停,等 factorial(2) 的结果 → 2 * factorial(1)# 暂停,等 factorial(1) 的结果 → return 1# 触底,开始返回 → 2 * 1 = 2# 一层层算回去→ 3 * 2 = 6# 最终答案
像叠盘子——先一个个压下去(调用),到底后再一个个取出来(返回)。
什么时候用递归
问题的结构天然是自相似的——每一层做的事一样,只是规模更小。比如:遍历文件夹(文件夹里套文件夹)、树形菜单展开、反转字符串、汉诺塔、快速排序。
总结:编程思维的内核
这 8 个概念教你的不是"Python 语法速查表",而是一套让脑子用程序的方式工作的框架:
好代码的标准不是炫技,而是:简单、清楚、像人话一样可读。有了这套思维,你不仅能用 Python 写程序,更能理解 AI 生成的代码有没有逻辑问题——这才是编程思维真正的价值。