Python的基本语法详解
前言「基本语法」四个字容易让人以为重点在「怎么打冒号、怎么敲缩进」。真正卡住人的其实不是这些记号而是背后的语义为什么改了一个列表另一个变量也跟着变为什么函数里给全局变量赋值会报UnboundLocalError为什么list.sort()返回None这篇详解按「对象模型 → 运算符 → 控制流 → 函数 → 作用域 → 推导式」的顺序展开每一节都尽量把「结果是什么」和「为什么是这个结果」说清楚。凡是实现细节比如小整数缓存而不属于语言保证的我会单独标出来。示例适用于 Python 3.8 及以上。注意 Python 2.7 已于 2020 年 1 月 1 日停止维护本文不含任何 Python 2 语法。一、名字、对象与可变性Python 的赋值是名字绑定name binding不是「把值放进盒子」。a [1, 2]做的是「让名字a指向那个列表对象」b a让b指向同一个对象。# 适用于 Python 3.8a [1, 2]b ab.append(3)print(a) # [1, 2, 3]a 看到的是同一个列表c a[:] # 切片生成新列表c.append(4)print(a, c) # [1, 2, 3] [1, 2, 3, 4]这就解释了可变mutable与不可变immutable的分野类型可变备注intfloatboolstrtuplefrozenset不可变「修改」都是创建新对象listdictsetbytearray可变支持原地修改不可变对象的「修改」一定产生新对象这也是为什么s.upper()必须接返回值——原字符串不会变。# 适用于 Python 3.8s abcs.upper() # 返回新字符串但没有名字指向它随即被回收print(s) # 仍然是 abcs s.upper() # 这样才改了print(s) # ABCt (1, 2)try:t[0] 9except TypeError as e:print(TypeError:, e)二、运算符与真值测试运算符的语义细节# 适用于 Python 3.8print(7 / 2) # 3.5除号永远返回 floatprint(7 // 2) # 3整除向下取整print(-7 // 2) # -4不是 -3print(7 % 3, -7 % 3) # 1 2取余结果符号跟随除数print(True True) # 2bool 是 int 的子类print(isinstance(True, int))bool是int的子类所以True True 2。写类型判断时如果先判int再判bool布尔值会被误判成普通整数# 适用于 Python 3.8def kind(v):if isinstance(v, bool):return boolif isinstance(v, int):return intreturn otherprint(kind(True), kind(1))is与是两个层面# 适用于 Python 3.8a [1, 2]b [1, 2]print(a b) # True值相等print(a is b) # False不同对象print(a is a) # Trueprint(None is None) # TrueNone 是单例is只应用于None、True、False和哨兵对象。CPython 会缓存 -5 到 256 的小整数所以256 is 256可能是True、257 is 257在脚本里通常也是True同一编译单元内的常量合并但这些都是实现细节不能依赖。短路求值与真值测试and/or不返回布尔值而是返回决定结果的那个操作数并且短路# 适用于 Python 3.8name display name or 匿名用户print(display) # 匿名用户config {retries: 0}count config.get(retries) or 3print(count) # 3注意0 被当成假值了最后一行是个经典陷阱想要「取不到才用默认值」应该用get的 default 参数而不是or否则值为0、、False时会被替换掉。假值一共这些None、False、0、0.0、0j、、[]、{}、()、set()以及定义了__bool__返回False或只定义__len__返回 0的对象。三、控制流、函数与作用域控制流与循环的elsefor/while都能带else含义是「循环没有被break打断时执行」# 适用于 Python 3.8def find_even(numbers):for n in numbers:if n % 2 0:print(找到偶数, n)breakelse:print(没有偶数)returnfind_even([1, 3, 5])find_even([1, 2, 3])这段逻辑用else比用一个标志变量干净得多。注意else里写的条件是「没break」跟if/else的else含义不同。循环变量在循环结束后仍然存在Python 没有块级作用域# 适用于 Python 3.8for i in range(3):passprint(i) # 2函数的五种参数Python 的参数形态比大多数语言多PEP 5703.8又加了仅位置参数。按出现顺序形态写法说明仅位置3.8def f(a, b, /)只能用位置传递位置或关键字def f(a, b)两种都行可变位置def f(*args)收集成tuple仅关键字def f(*, k)只能用k值传可变关键字def f(**kwargs)收集成dict# 适用于 Python 3.8def func(a, b, /, c, *args, d, **kwargs):print(a, b, c, args, d, kwargs)func(1, 2, 3, x, y, d4, extra5)func(1, 2, c3, d4)规则/之前的只能用位置传*之后的只能用关键字传*args之后、**kwargs之前的参数自动变成仅关键字。传参时*和**还能用来解包# 适用于 Python 3.8def add(x, y):return x ynums [3, 4]print(add(*nums)) # 7opts {x: 3, y: 4}print(add(**opts)) # 7默认参数只在定义时求值一次这是函数部分最重要的坑# 适用于 Python 3.8def bad(item, bucket[]):bucket.append(item)return bucketprint(bad(1)) # [1]print(bad(2)) # [1, 2]不是 [2]def good(item, bucketNone):if bucket is None:bucket []bucket.append(item)return bucketprint(good(1)) # [1]print(good(2)) # [2]作用域LEGB 与 global / nonlocal名字查找顺序是Local当前函数→Enclosing外层函数→Global模块→Built-in内置。# 适用于 Python 3.8count 0def increase():global countcount 1 # 没有 global 会抛 UnboundLocalErrorincrease()print(count) # 1关键点只要函数体内有对某个名字的赋值这个名字在整个函数内就被当作局部变量——哪怕赋值语句在读取之后。所以下面的写法会报UnboundLocalError而不是读到全局的count# 适用于 Python 3.8total 0def broken():try:total 1 # UnboundLocalErrortotal 被判定为局部变量except UnboundLocalError as e:return fUnboundLocalError: {e}print(broken())嵌套函数要修改外层函数的变量用nonlocal# 适用于 Python 3.8def counter():n 0def step():nonlocal nn 1return nreturn stepc counter()print(c(), c(), c()) # 1 2 3四、推导式与实战推导式与生成器表达式推导式comprehension是 Python 最有特色的语法之一但要区分清楚# 适用于 Python 3.8squares_list [x * x for x in range(5)] # 列表推导式立即求值squares_gen (x * x for x in range(5)) # 生成器表达式惰性squares_set {x * x for x in range(5)} # 集合推导式squares_map {x: x * x for x in range(5)} # 字典推导式print(squares_list, squares_set)print(list(squares_gen))print(sum(x for x in range(10) if x % 2 0)) # 20生成器表达式不是列表推导式。前者是惰性迭代器只能遍历一次且不占用列表的内存后者立即构造出完整列表。下面这个错误很典型# 适用于 Python 3.8gen (x for x in range(3))print(list(gen)) # [0, 1, 2]print(list(gen)) # [] —— 已被耗尽不会重来推导式在 Python 3 里有自己的作用域循环变量不会泄漏到外面# 适用于 Python 3.8x 外部的result [x for x in range(3)]print(result, x) # [0, 1, 2] 外部的实战把语法点串起来# 适用于 Python 3.8按分数分组统计并演示参数、作用域、推导式与循环 else。def group_by_grade(records, /, *, passing60):records 是 (姓名, 分数) 的可迭代对象返回 {等级: [姓名, ...]}。groups {}for name, score in records:grade 及格 if score passing else 不及格groups.setdefault(grade, []).append(name)return groupsdef find_first(records, predicate):for item in records:if predicate(item):return itemelse: # 没找到才走这里raise LookupError(没有满足条件的记录)if __name__ __main__:students [(小明, 92), (小红, 58), (小刚, 77)]groups group_by_grade(students, passing60)for grade in (及格, 不及格):names groups.get(grade, [])print(f{grade}{len(names)} 人{、.join(names) or 无})top find_first(students, lambda r: r[1] 90)print(最高分记录, top)值得注意的几点def group_by_grade(records, /, *, passing60)用了仅位置参数和仅关键字参数groups.setdefault(grade, []).append(name)是分组惯用法setdefault在键不存在时插入默认值并返回它join(names) or 无利用了空字符串是假值for ... else在没 break 时才抛LookupError。常见坑点❌ 以为b a会复制列表 ✅ 那只是让两个名字指向同一个对象要复制用a[:]、a.copy()或copy.deepcopy(a)。❌ 写def f(x, lst[])用可变对象当默认参数 ✅ 默认参数只在定义时求值一次所有调用共享同一个列表改用lstNone再在函数体里初始化。❌ 在函数里给全局变量赋值却忘了global然后被UnboundLocalError卡住 ✅ 函数体里只要有赋值该名字就是局部的要改全局必须写global 名字。❌ 用value or 默认值处理可能为0或的配置项 ✅0、、[]都是假值会被替换该用config.get(key, 默认值)。❌ 把生成器表达式当列表推导式反复遍历 ✅ 生成器只能消费一次第二次list(gen)得到空列表需要复用请构造列表。❌ 断言257 is 257这类小整数/字符串驻留行为是语言保证 ✅ 那是 CPython 实现细节is只用于None/True/False比较值一律用。❌ 认为-7 // 2是-3✅ 整除是向下取整结果是-4-7 % 3是2取余结果符号跟随除数。❌ 用list.sort()的返回值写new data.sort()✅list.sort()原地排序并返回None要新列表用sorted(data)。总结语法点结论赋值绑定名字到对象不是复制值可变性list/dict/set 可变str/tuple/int 不可变isvs身份 vs 值缓存与驻留是实现细节and/or短路并返回操作数不返回布尔值for ... elseelse在没有 break时执行参数形态/仅位置*后仅关键字*args/**kwargs收集默认参数只在定义时求值一次禁用可变对象作用域LEGB有赋值即局部global/nonlocal显式声明推导式有独立作用域生成器表达式惰性且只能消费一次sort()原地排序返回None基本语法的难点从来不在记号本身而在这些「看起来一样、行为差很远」的地方绑定与复制、可变与不可变、局部与全局。把这些语义理清剩下的语法只是查手册的问题。

相关新闻

HDF框架下OpenHarmony温湿度传感器驱动开发实战

HDF框架下OpenHarmony温湿度传感器驱动开发实战

前阵子做一套环境监测设备,设备主控跑的是OpenHarmony系统,需要接入一路温湿度传感器,把数据从物理世界送到应用层。按理说,OpenHarmony生态里现成的传感器驱动已经不少,但手头这批传感器模块用的是某个特定型号的I2C接…

2026/10/10 19:16:56 阅读更多 →
嵌入式主从自动分配:基于平均值与设备数的轻量级方案

嵌入式主从自动分配:基于平均值与设备数的轻量级方案

1. 从一次设备组网翻车说起:为什么需要主从自动分配去年帮一个做工业数据采集的朋友排查问题,现场有二十多台同型号的采集终端挂在同一条总线上,需要选出一台作为主机来协调时序、汇总数据,其余作为从机。他们最初的做法是写死配置…

2026/10/10 19:16:56 阅读更多 →
Android BaseFragment最佳实践:ViewBinding懒加载与统一状态管理

Android BaseFragment最佳实践:ViewBinding懒加载与统一状态管理

在Android项目里待得久了,你会发现Fragment是最考验“基建功底”的东西之一。同一个列表页,有人用ViewModel把状态管得清清楚楚,有人却把加载框、空页面、接口回调全堆在Activity里,一个页面两三百行,十几个页面就是两…

2026/10/10 19:16:56 阅读更多 →

最新新闻

微服务多级缓存架构设计

微服务多级缓存架构设计

1 需求背景系统读多写少场景,大量热点字典、基础业务信息,请求全部打到 Redis,Redis CPU / 带宽压力高。 引入本地内存缓存,缩短访问链路;同时解决多实例本地缓存脏数据问题。非目标不用于强一致性业务(库存…

2026/10/11 16:38:47 阅读更多 →
安全日志分析实战:从撞库、Webshell到横向移动的攻击链还原方法

安全日志分析实战:从撞库、Webshell到横向移动的攻击链还原方法

做安全运营这些年,我翻过的日志如果打印出来,大概能堆满一整面墙。网络攻击日志分析这件事,听起来很高大上,实际干起来往往是从一堆看似无关的字符里,把攻击者的行动轨迹一点点抠出来。你盯着几十万行访问记录&#xf…

2026/10/11 16:38:47 阅读更多 →
从SEO到GEO:AI时代企业为什么需要建立品牌知识资产?

从SEO到GEO:AI时代企业为什么需要建立品牌知识资产?

随着生成式AI快速进入企业营销体系,传统的搜索流量逻辑正在出现新的变化。 世界广告主联合会(WFA)最新调研显示,96%的受访大型品牌已经在使用生成式AI或智能体AI。 对于企业数字化团队而言,一个值得关注的问题是&#…

2026/10/11 16:38:47 阅读更多 →
beautify-github-readme 内容架构教程:价值→证明→机制,5 步重排 README 阅读顺序

beautify-github-readme 内容架构教程:价值→证明→机制,5 步重排 README 阅读顺序

【免费下载链接】beautify-github-readme 整理并设计仓库 README,让项目价值、真实案例、安装方式与使用边界更容易理解。 项目地址: https://gitcode.com/gh_mirrors/be/beautify-github-readme 点击查看 免费下载 很多开源仓库不缺信息,缺…

2026/10/11 16:38:46 阅读更多 →
SpringBoot+Vue宠物健康咨询系统:前后端分离项目完整部署与二次开发指南

SpringBoot+Vue宠物健康咨询系统:前后端分离项目完整部署与二次开发指南

最近好几个人问我要这种“能直接跑起来的完整项目”,点名还是要SpringBoot加Vue那一套。这里就把一个宠物健康咨询信息管理系统的完整实现思路、技术方案和部署过程拿出来聊聊。如果你是准备做毕业设计,或者是想快速上手前后端分离的项目练手&#xff0c…

2026/10/11 16:38:46 阅读更多 →
AI File Sorter Headless 无界面集成完全指南:CLI 参数、状态 JSON 与并发锁一次讲清

AI File Sorter Headless 无界面集成完全指南:CLI 参数、状态 JSON 与并发锁一次讲清

AI 应用大模型本地部署桌面应用 【免费下载链接】ai-file-sorter Cross-platform desktop application for content-aware file organization and renaming. Supports local and remote LLMs, preview-based workflows, and fully user-controlled changes. 项目地址&#xff1…

2026/10/11 16:37:46 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →