Python-基础语法大全


本文所有代码均基于 Python 3.10 + 版本运行,兼容 Python3.6 +

参考资料:比特就业课 Python 基础语法体系、Python 官网文档等

前言

Python凭借其简洁的语法、极强的可读性和丰富的生态库,常年霸占 TIOBE 编程语言排行榜榜首位置。截至 2026 年 3 月,Python 在 TIOBE 榜单中以超过23%市场份额持续领跑,广泛应用于人工智能、数据分析、Web 开发、自动化运维、网络爬虫等诸多领域,成为零基础入门编程的首选语言。

基础语法是 Python 学习的基石,无论是后续进阶框架使用,还是复杂项目开发,都离不开扎实的语法功底。本文将基于 Python3 标准,系统梳理 Python 核心基础语法,从最基础的常量表达式,到流程控制、函数、复合数据类型,再到文件操作,全覆盖讲解核心知识点,同时配套可运行代码示例、原理图表和行业最佳实践,帮读者一文吃透 Python 基础语法。

一、常量、变量与数据类型

1.1 常量与表达式

在 Python 中,我们可以直接将解释器作为计算器使用,通过常量运算符 组成表达式完成算术运算。

  • 字面值常量 :代码中直接写出的固定值,如 12.5'hello',分为数值常量、字符串常量、布尔常量等

  • 表达式:由常量、变量和运算符组成的算式,每个表达式都会有一个明确的返回值

  • 运算符优先级 :遵循数学规则,先算乘除,后算加减 ,可通过括号()改变运算顺序

代码示例:基础算术运算

python 复制代码
# 基础算术运算
print(1 + 2 - 3)    # 加减运算,输出:0
print(1 + 2 * 3)    # 先乘后加,输出:7
print(1 + 2 / 3)    # 除法运算,输出:1.6666666666666665
print((67.5 + 89.0 + 12.9 + 32.2) / 4)  # 求平均数,输出:50.4

注意:

  • print 是一个 Python 内置的函数,这个稍后详细介绍。

  • 可以使用 +、-、*、/ 以及括号 ( ) 等运算符进行算术运算。计算时先算乘除,后算加减。

  • 运算符和数字之间可以没有空格,也可以有多个空格,但是一般习惯上写一个空格,这样比较美观。

形如 1 + 2 - 3 这样的算式,在编程语言中称为表达式 。算式的运算结果,称为表达式的返回值 。其中 1、2、3 这种称为字面值常量 ,+++-*/++ 这种称为运算符操作符

注意 :和 C/Java 等语言不同,Python 中/除法不会截断小数部分,会直接返回浮点数,更符合日常使用直觉。

示例:

给定四个分数 67.5、89.0、12.9、32.2,编写代码,求这四个分数的平均数。

python 复制代码
print( (67.5 + 89.0 + 12.9 + 32.2) / 4 )

1.2 变量与命名规范

变量是程序中用于存储数据的容器,对应计算机内存中的一块存储空间,我们可以通过变量名读取 或修改其中的数据,是实现复杂计算的核心载体。

1.2.1 变量的定义与使用

Python 中变量 无需提前声明类型,赋值时自动确定类型,核心语法为**变量名 = 数值**

创建变量的语句非常简单,其中

  • a 为变量名。当我们创建很多个变量的时候,就可以用名字来进行区分。

  • = 为赋值运算符,表示把 = 右侧的数据放到 = 左侧的空间中。

示例:

给定四个分数 67.5、89.0、12.9、32.2,编写代码,求这四个分数的方差。

PS:方差的计算过程:取每一项,减去平均值,计算平方,再求和,最后除以(项数 - 1)。

在以下代码中,就需要先计算这四个数字的平均值,然后再计算方差。这就需要把计算的平均值使用变量保存起来。

python 复制代码
# 定义变量,计算4个数字的方差
avg = (67.5 + 89.0 + 12.9 + 32.2) / 4  # 存储平均值
total = (67.5 - avg) ** 2 + (89.0 - avg) ** 2 + (12.9 - avg) ** 2 + (32.2 - avg) ** 2
result = total / 3
print(result)  # 输出方差结果:1278.0499999999997

# 变量的读取与修改
a = 10
print(a)  # 读取变量,输出:10
a = 20    # 修改变量值
print(a)  # 输出:20

注意:

  • avg、total、result 均为变量。

  • ** 在 Python 中表示乘方运算,** 2 即为求平方。

就像计算器中的 M 键功能类似,通过变量就可以保存计算过程中的中间结果。

只不过,计算器一般只能保存一个数据,而在 Python 代码中,可以创建任意多的变量,来随心所欲地保存很多很多的数据。

变量可以视为是一块能够容纳数据的空间,这个空间往往对应到"内存"这样的硬件设备上。

PS:我们可以把内存想像成是一个宿舍楼,这个宿舍楼上有很多的房间。每个房间都可以存放数据。衡量内存的一个重要指标就是内存空间的大小,比如我的电脑内存是 16GB。这个数字越大,意味着内存的存储空间就越大,能够存放的数据(变量)就越多。

1.2.2 变量命名规则

变量名不是随意定义的,需要遵守 Python 的语法规则,分为 硬性规则(务必遵守)和 软性规则(建议遵守) 两类:

规则类型 具体要求 反例 正确示例
硬性规则 只能由数字、字母、下划线组成 a*b123num num123user_name
硬性规则 数字不能作为开头 123abc abc123
硬性规则 不能与 Python 关键字重名 iffordef if_flagfor_num
硬性规则 大小写敏感 Numnum是两个完全不同的变量 -
软性规范 使用有描述性的单词,见名知意 xya1 user_agetotal_count
软性规范 多单词推荐使用蛇形命名法(PEP8 规范) userName(驼峰) user_name
软性规范 不使用拼音 / 拼音英文混合 yong_hu_ming user_name

补充:Python3 支持中文作为变量名(如姓名 = "张三"),但工业级开发中强烈不建议使用,会存在兼容性和可读性问题。

1.3 变量的类型

Python 中变量的类型在赋值时自动确定,无需显式声明,通过内置函数**type()** 可以查看变量的类型。核心基础数据类型分为 4 类,同时支持++列表、元组、字典++等复合类型,核心基础类型如下:

1.3.1 四类基础数据类型
数据类型 关键字 特点说明 代码示例
整数 int 无大小上限,只要内存足够,可存储无限大的整数,支持正负数、0 a = 10b = -9999999999999
浮点数 float 双精度浮点数(等价于 C/Java 的 double),占用 8 字节内存,精度约小数点后 15 位 a = 0.5b = 3.1415926
字符串 str 单引号' '或双引号" "包裹的文本内容,两者完全等价,支持拼接、长度获取等操作 a = 'hello'b = "Python"
布尔值 bool 仅两个取值:True(真)和False(假),用于逻辑判断 a = Trueb = 10 > 20

除了上述类型之外,Python 中还有 list、tuple、dict、自定义类型等等。

(1) 整数

代码示例:数据类型操作

python 复制代码
a = 10
print(type(a))

PS:type 和 print 类似,也是 Python 内置的函数。可以使用 type 来查看一个变量的类型。

注意:和 C++ / Java 等语言不同,Python 的 int 类型变量表示的数据范围是没有上限的。只要内存足够大,理论上就可以表示无限大小的数据。

(2) 浮点数
python 复制代码
a = 0.5
print(type(a))

注意:和 C++ / Java 等语言不同,Python 的小数只有 float 一种类型,没有 double 类型。但实际上 Python 的 float 就相当于 C++ / Java 的 double,表示双精度浮点数。

PS:关于单精度浮点数和双精度浮点数的问题,此处不做过多讨论。大家只要知道,相比于单精度浮点数,双精度浮点数占用的内存空间更多,同时表示的数据精度更高即可(大概精确到小数点后 15 位)。

(3) 字符串
python 复制代码
a = 'hello'
print(type(a))

使用 ' ' 或者 " " 引起来的,称为字符串,可以用来表示文本。

注意:在 Python 中,单引号构成的字符串和双引号构成的字符串没有区别,'hello'"hello" 是完全等价的。

可以使用 len 函数来获取字符串的长度。

python 复制代码
a = 'hello'
print(len(a))

可以使用 + 针对两个字符串进行拼接

python 复制代码
a = 'hello'
b = 'world'
print(a + b)

PS:此处是两个字符串相加,不能拿字符串和整数/浮点数相加。

字符串作为开发中最常用到的数据类型,支持的操作方式也是非常丰富的。

(4) 布尔

布尔类型是一个特殊的类型,取值只有两种:True(真)和 False(假)

PS:布尔类型也是数学上的一个概念。我们初中就学过一个概念叫做"命题",进一步的就可以判定命题的真假。

布尔类型在咱们后续进行逻辑判断的时候,是非常有用的。

1.3.2 为什么要有这么多类型?
(1) 类型决定了数据在内存中占据多大空间。

例如 float 类型在内存中占据 8 个字节。

PS:计算机里面使用二进制来表示数据,也就是每个位只能表示 0 或者 1。

1 个二进制位就称为是一个"比特",8 个二进制位就称为一个"字节"(Byte)。

一个 float 变量在内存中占据 8 个字节空间,也就是 64 个二进制位。

我的电脑有 16GB 的内存空间,也就是一共有 1024 × 1024 × 1024 × 8 这么多的二进制位。

示例代码:

python 复制代码
a = 'hello'
b = 'world'
print(a + b)

a = True
print(type(a))
b = False
print(type(b))
(2) 类型约定了能对这个变量做什么样的操作。

例如 int / float 类型的变量,可以进行 +、-、、/ 等操作。而 str 类型的变量,只能进行 +(并且行为是字符串拼接),不能进行 -、、/,但是还能使用 len 等其他操作。

总结: 类型系统其实是在对变量进行"归类"。相同类型的变量(数据)往往具有类似的特性和使用规则。

1.3.3 动态类型特性

Python 是典型的动态类型语言,变量的类型可以在程序运行过程中发生改变;而 C++/Java 等静态类型语言,变量定义后类型就固定不可修改。

python 复制代码
# 动态类型演示
a = 10
print(type(a))  # 初始为int类型,输出:<class 'int'>
a = 'hello'
print(type(a))  # 运行中变为str类型,输出:<class 'str'>

优缺点对比

优势 劣势
代码更简洁,开发效率高,一段代码可支持多种类型 大型项目中,提高了模块间的交互成本,不利于类型校验
无需提前声明类型,学习门槛低 容易出现类型相关的隐藏 bug,需依赖类型注解和单元测试规避

动态类型特性是把双刃剑!!!!

二、注释

2.1注释是什么

注释是不会被程序执行的特殊代码,核心作用是解释代码逻辑,提升代码可读性,是团队协作和后期维护的核心保障。Python 中主要分为行注释文档字符串两类。

PS: 写代码是一件比较烧脑的事情,读代码同样也非常烧脑。相比于一板一眼的代码,一些口语化的描述能更好地帮助程序员理解程序。

python 复制代码
# 计算 4 个数字 67.5, 89.0, 12.9, 32.2 的方差
avg = (67.5 + 89.0 + 12.9 + 32.2) / 4
total = (67.5 - avg) ** 2 + (89.0 - avg) ** 2 + (12.9 - avg) ** 2 + (32.2 - avg)
** 2
result = total / 3
print(result)

形如上述代码,如果没有注释,直接阅读,是不容易 get 到代码的含义是计算方差的。但是通过加了一行注释解释一下,就让人一目了然了。

PS: 代码的第一目标是容易理解,第二目标才是执行正确。写注释不光是为了方便别人来理解,也是方便三个月之后的自己理解。

一个反例:早些年医生的手写处方:

2.2 注释的两种语法

2.2.1 行注释

以**# 开头,#** 后的所有内容都会被解释器忽略,通常用于对++单行代码++做解释。

python 复制代码
# 计算4个数字的方差(行注释:说明代码整体功能)
avg = (67.5 + 89.0 + 12.9 + 32.2) / 4  # 计算平均值(行注释:单行代码说明)
total = (67.5 - avg) ** 2 + (89.0 - avg) ** 2 + (12.9 - avg) ** 2 + (32.2 - avg) ** 2
result = total / 3  # 方差公式:平方和/(项数-1)
print(result)
2.2.2 文档字符串

使用三引号 """ """''' '''包裹,支持++多行内容++,通常放在文件、函数、类的开头,用于说明整体功能,是 Python 官方推荐的文档注释方式。

python 复制代码
"""
这是文档字符串示例
功能:计算一组数据的方差
作者:Python教程
日期:2026-04
"""
def calc_variance(data_list):
    """
    计算列表数据的方差
    :param data_list: 输入的数值列表
    :return: 方差计算结果
    """
    avg = sum(data_list) / len(data_list)
    total = sum((x - avg) ** 2 for x in data_list)
    return total / (len(data_list) - 1)

2.3 注释的规范

  1. 内容准确:注释必须和代码逻辑一致,代码修改时同步更新注释,禁止出现 "注释和代码不符" 的情况

  2. 篇幅合理 :注释应简洁明了,核心代码必须加注释,无需对显而易见的代码做冗余注释(如a = 10 # 给a赋值10

  3. 语言规范:国内企业统一使用中文写注释,外企可根据要求使用英文,禁止中英文混合、拼音注释

  4. 格式规范 :行注释#后必须加一个空格;文档字符串需遵循 Google 风格或 NumPy 风格,统一团队标准

  5. 积极正向:注释中禁止包含负能量、吐槽、人身攻击等无关内容

三、控制台输入与输出

程序与用户的交互核心分为两步:

  • 用户把信息传递给程序的过程,称为"输入"。

  • 程序把结果展示给用户的过程,称为"输出"。

输入输出的最基本方法就是控制台。用户通过控制台输入一些字符串,程序再通过控制台打印出一些字符串。

PyCharm 运行程序,下方弹出的窗口就可以视为是控制台。

**输入输出的最常见方法是图形化界面。**如我们平时用到的 QQ, 浏览器, steam 等, 都不需要用户输入命令,而只是通过鼠标点击窗口点击按钮的方式来操作.

PS: Python 当然也可以用来开发图形化界面的程序,但是图形化程序开发本身是一个大话题,咱们暂时不做介绍。

3.1 控制台输出

**print()**是 Python 内置的输出函数,用于将内容打印到控制台,支持多种数据类型和格式化输出。

3.1.1 基础用法

不仅能输出一个字符串,还可以输出一个其他类型的变量。更多的时候,我们希望能够输出的内容是混合了字符串和变量的。

python 复制代码
# 打印单个常量/变量
print('hello Python')  # 输出字符串:hello Python
a = 10
print(a)  # 输出变量:10
print(True)  # 输出布尔值:True

# 打印多个内容,用逗号分隔,默认用空格拼接
name = '张三'
age = 20
print('姓名:', name, '年龄:', age)  # 输出:姓名: 张三 年龄: 20
3.1.2 格式化输出:f-string

Python3.6 + 支持的 f-string 格式化语法,是目前工业级开发的首选,

语法为f'内容{变量/表达式}',直接在字符串中内嵌变量或表达式,可读性极强。

python 复制代码
# f-string基础用法
num = 10
print(f'num = {num}')  # 输出:num = 10

# 内嵌表达式
a = 20
b = 30
print(f'a + b = {a + b}')  # 输出:a + b = 50

# 格式化浮点数精度
pi = 3.1415926
print(f'圆周率保留2位小数:{pi:.2f}')  # 输出:圆周率保留2位小数:3.14

扩展:Python 还支持**%格式化、format()**格式化,三者对比如下:

格式化方式 优点 缺点 适用场景
f-string 语法简洁、可读性强、性能最高 仅支持 Python3.6+ 绝大多数开发场景,首选
format() 兼容性好,支持复杂格式化 语法繁琐,长字符串可读性差 需要兼容 Python3.5 及以下版本
% 格式化 最传统,兼容所有版本 类型限制严格,容易出现类型错误 老项目维护

3.2 控制台输入

**input()**是 Python 内置的输入函数,用于接收用户在控制台输入的内容,核心特点:

  1. **input()**的参数是提示信息,可省略

  2. 无论用户输入什么内容,返回值永远是字符串类型

  3. 程序执行到 **input()**时会阻塞,等待用户输入完成后继续执行

代码示例:

python 复制代码
# 基础输入
num = input('请输入一个整数:')
print(f'你输入的内容是:{num}')
print(f'输入内容的类型是:{type(num)}')  # 永远是<class 'str'>

# 重点:输入数值时,必须进行类型转换
a = input('请输入第一个整数:')
b = input('请输入第二个整数:')
# 错误用法:直接相加,会变成字符串拼接
print(f'错误的相加结果:{a + b}')  # 输入10和20,输出:1020

# 正确用法:先转换为int/float类型,再进行算术运算
a = int(a)
b = int(b)
print(f'正确的相加结果:{a + b}')  # 输入10和20,输出:30

**实战案例:**输入 4 个小数,计算平均值

python 复制代码
# 接收用户输入的4个小数,计算平均值
a = float(input('请输入第一个数字:'))
b = float(input('请输入第二个数字:'))
c = float(input('请输入第三个数字:'))
d = float(input('请输入第四个数字:'))

avg = (a + b + c + d) / 4
print(f'4个数字的平均值是:{avg:.2f}')

四、运算符

运算符是用于执行各种运算的符号,Python 中核心运算符分为 5 大类,下面逐一讲解核心用法和注意事项。

4.1 算术运算符

用于执行基础的数学运算,核心运算符如下表:

运算符 功能 示例 结果 注意事项
+ 加法 10 + 20 30 字符串之间可用于拼接
- 减法 20 - 10 10 可用于负数表示
* 乘法 2 * 3 6 字符串与整数可用于重复('a'*3得到'aaa'
/ 除法 10 / 2 5.0 永远返回浮点数,除数不能为 0,否则抛出异常
// 地板除(取整除法) 7 // 2-7 // 2 3-4 舍弃小数部分,向下取整,而非四舍五入
% 取余(取模) 7 % 2 1 返回除法运算的余数
** 乘方 4 ** 24 ** 0.5 162.0 支持整数次方、小数次方,可用于开方

坑点:

  1. 除零异常:///% 运算符中,除数不能为 0,否则会抛出 ZeroDivisionError

  2. 地板除的向下取整:负数场景需注意,-7//2 结果是 - 4,而非 - 3

  3. 浮点数精度问题:算术运算中浮点数可能出现微小误差,如 0.1 + 0.2 = 0.30000000000000004

4.2 关系运算符

用于比较两个值的大小 或 相等关系,运算结果永远是布尔值True或False,核心运算符如下:

运算符 含义 示例 结果
< 小于 10 < 20 True
<= 小于等于 10 <= 10 True
> 大于 10 > 20 False
>= 大于等于 10 >= 20 False
== 等于 10 == 10 True
!= 不等于 10 != 20 True
注意事项
  • 字符串比较 :支持关系运算符,按照字典序比较

    python 复制代码
    a = 'hello'
    b = 'world'
    print(a < b)  # 输出:True,因为'h'的Unicode编码小于'w'
    print(a == 'hello')  # 输出:True,直接对比字符串内容
  • 浮点数相等判断的巨坑 :禁止直接用==判断两个浮点数相等,因为浮点数的存储存在精度误差

    python 复制代码
    # 错误用法
    print(0.1 + 0.2 == 0.3)  # 输出:False,因为0.1+0.2=0.30000000000000004
    
    # 正确用法:判断差值在允许的误差范围内
    a = 0.1 + 0.2
    b = 0.3
    print(-1e-6 < (a - b) < 1e-6)  # 输出:True,误差小于百万分之一即认为相等
  • Python 特有语法 :支持连续比较,++a < b < c等价于a < b and b < c++,更符合数学书写习惯

PS: 关于字典序:想象一个英文词典,上面的单词都是按照字母顺序排列。如果首个字母相同,就比较第二个字母(比如著名单词 abandon)咱们可别放弃。我们认为一个单词在词典上越靠前,就越小;越靠后,就越大。

4.3 逻辑运算符

用于多个布尔值之间的逻辑运算,核心运算符为 andornot,运算结果为布尔值,核则如下表:

运算符 含义 运算规则 示例 结果
and 逻辑与(并且) 两侧都为 True,结果才为 True;一假则假 True and False False
or 逻辑或(或者) 两侧有一个为 True,结果就为 True;一真则真 True or False True
not 逻辑非(取反) 操作数为 True,结果为 False;反之亦然 not True False

此处说的"并且"和"或者",就是我们日常生活中使用的"并且"和"或者"。想象一下未来丈母娘问你要彩礼,什么叫做"有房并且有车",什么叫做"有房或者有车"。

python 复制代码
a = 10
b = 20
c = 30
print(a < b and b < c)
print(a < b and b > c)
print(a > b or b > c)
print(a < b or b > c)
print(not a < b)
print(not a > b)
(1) 扩展:短路求值

逻辑运算符支持短路求值,即当表达式的结果可以提前确定时,不再执行后续的代码,是 Python 中重要的性能优化机制,也是面试高频考点。

  • 对于and:左侧表达式为 False 时,整体结果一定为 False,右侧表达式不再执行

  • 对于or:左侧表达式为 True 时,整体结果一定为 True,右侧表达式不再执行

python 复制代码
# 短路求值演示
# 1. and短路:左侧为False,右侧的除零运算不会执行,无异常
print(10 > 20 and 10 / 0 == 1)  # 输出:False

# 2. or短路:左侧为True,右侧的除零运算不会执行,无异常
print(10 < 20 or 10 / 0 == 1)  # 输出:True

上述代码没有抛出异常,说明右侧的除以 0 操作没有真正执行。

4.4 赋值运算符

用于给变量赋值,核心分为基础赋值、复合赋值、多元赋值三类。

4.4.1 基础赋值与复合赋值
(1) = 的使用

= 表示赋值。注意和 **==**区分。

**=**除了基本的用法之外,还可以同时针对多个变量进行赋值:

  • 链式赋值

    python 复制代码
    a = b = 10
  • 多元赋值

    python 复制代码
    a, b = 10, 20

代码实例:交换两个变量

基础写法

python 复制代码
a = 10
b = 20
tmp = a
a = b
b = tmp

基于多元赋值

python 复制代码
a = 10
b = 20
a, b = b, a
(2) 复合赋值运算符

Python 还有一些复合赋值运算符,例如 +=、-=、*=、/=、%=。

其中 a += 1 等价于 a = a + 1,其他复合赋值运算符也是同理。

python 复制代码
a = 10
a = a + 1
print(a)
b = 10
b += 1
print(b)
运算符 含义 等价写法
= 基础赋值 a = 10,将 10 赋值给变量 a
+= 加法赋值 a += 1 等价于 a = a + 1
-= 减法赋值 a -= 1 等价于 a = a - 1
*= 乘法赋值 a *= 2 等价于 a = a * 2
/= 除法赋值 a /= 2 等价于 a = a / 2
//= 地板除赋值 a //= 2 等价于 a = a // 2
%= 取余赋值 a %= 2 等价于 a = a % 2
**= 乘方赋值 a **= 2 等价于 a = a ** 2

注意:Python 不支持 C/Java 中的 ++--自增自减运算符,统一使用 += 1-= 1实现,避免了前置 / 后置的混淆问题。

4.5 其他运算符

除了上述核心运算符,Python 还有两类常用运算符,这里做基础讲解:

  1. 成员运算符innot in,用于判断元素是否存在于序列 / 字典中,返回布尔值

    python 复制代码
    print(2 in [1,2,3])  # 输出:True
    print('hello' in 'hello world')  # 输出:True
  2. 身份运算符isis not,用于判断两个变量是否指向同一个内存对象(即内存地址是否相同),和 == 有本质区别:== 判断值是否相等,is 判断内存地址是否相同

    python 复制代码
    a = [1,2,3]
    b = [1,2,3]
    print(a == b)  # 输出:True,值相等
    print(a is b)  # 输出:False,内存地址不同,是两个独立的列表

五、顺序、条件分支与循环语句

流程控制是程序的核心骨架,Python 中程序的执行流程分为 3 类:顺序结构分支结构循环结构,通过这三类结构可以实现所有复杂的业务逻辑。

5.1 顺序结构

顺序结构是 Python 默认的执行流程,代码按照从上到下的顺序依次执行,不会跳过任何一行代码,是最基础的流程结构。

python 复制代码
print("1")
print("2")
print("3")

执行结果一定为 "123",而不会出现 "321" 或者 "132" 等。这种按照顺序执行的代码,我们称为顺序语句。

这个顺序是很关键的。编程是一件明确无歧义的事情。安排好任务的顺序,计算机才能够正确地执行。就好像人生的顺序,是上学、工作、结婚、生子。一旦这里的顺序乱了,就很麻烦。

5.2 分支结构:if-elif-else 条件语句

什么是条件语句

条件语句能够表达"如果......否则......"这样的语义,这构成了计算机中基础的逻辑判定条件语句也叫做分支语句,表示了接下来的逻辑可能有几种走向。

一个典型的例子:如果丘处机没有路过牛家村,那么:

  1. 金兵不会死在郭、杨两家手上

  2. 郭、杨两家就不会流亡北方

  3. 郭夫人就不会去到大漠,完颜洪烈就不会遇到包惜弱

  4. 郭靖就不会和江南七怪救了铁木真

  5. 蒙古就不会统一

  6. 蒙古铁骑就不会西征

  7. 欧洲就不会出现火药,也就不会出现文艺复兴、大航海

  8. 大炮就不会从欧洲传到日本,日本得不到统一

  9. 完颜洪烈就不会全力战,金国内乱

  10. 宋朝不会灭亡,并诞生出资本主义,中国成为最发达的国家

python 复制代码
如果 我认真敲代码
    我就很容易找到工作
否则
    我就容易毕业就失业

其中"我认真敲代码"称为条件。如果条件成立(条件为真),则会出现"我就很容易找到工作"这个情况;如果条件不成立(条件为假),则会出现"我就容易毕业就失业"。

当然,同样的逻辑还可以反着表达。

python 复制代码
如果 我选择躺平摆烂
    我就容易毕业就失业
否则
    我就很容易找到工作

虽然结构变了,但是整体表达的语义是等价的。

PS:亲爱的读者们,你们是选择认真敲代码,还是躺平摆烂呢?

5.2.1 三种语法格式
1. 单分支:if

仅当条件为True 时,执行 if内的代码块,否则跳过。

python 复制代码
# 单分支:输入一个数字,如果大于0,打印正数
num = int(input('请输入一个整数:'))
if num > 0:
    print('这是一个正数')  # 仅num>0时执行
print('程序执行结束')  # 无论条件是否成立,都会执行
2. 双分支:if-else

条件为True 执行 if 代码块,条件为False 执行 else 代码块,两个分支二选一。

python 复制代码
# 双分支:判断奇数偶数
num = int(input('请输入一个整数:'))
if num % 2 == 0:
    print('这是一个偶数')
else:
    print('这是一个奇数')
3. 多分支:if-elif-else

用于多个条件的判断,从上到下依次匹配条件,匹配到第一个为 True 的条件后,执行对应的代码块,后续分支不再执行;所有条件都不成立,执行 else 代码块。

python 复制代码
# 多分支:判断成绩等级
score = float(input('请输入你的考试成绩:'))
if score >= 90:
    print('成绩等级:A')
elif score >= 80:
    print('成绩等级:B')
elif score >= 60:
    print('成绩等级:C')
else:
    print('成绩等级:D,考试不及格')
5.2.2 注意事项

注意: Python 中的条件语句写法,和很多编程语言不太一样。

  • if 后面的条件表达式,没有 ( ),使用 : 作为结尾。

  • if / else 命中条件后要执行的"语句块",使用缩进(通常是 4 个空格或者 1 个 tab)来表示,而不是 { }

  • 对于多条件分支,不是写作 else if,而是 elif(合体了)。

示例: 输入 1 表示愿意认真学习,输入 2 表示躺平摆烂。

python 复制代码
choice = input("输入 1 表示认真学习, 输入 2 表示躺平摆烂: ")
if choice == "1":
print("你会找到好工作!")
elif choice == "2":
print("你可能毕业就失业了!")
else:
print("你的输入有误!")
  • 缩进规则:Python 通过缩进表示代码块,PEP8 规范推荐使用4 个空格作为一级缩进,禁止使用 Tab 和空格混合缩进,否则会报语法错误。

  • 代码块嵌套:if 语句内部可以嵌套 if 语句,实现更复杂的逻辑判断,通过缩进区分层级。

  • pass 空语句:Python 语法要求代码块不能为空,如果暂时不需要执行任何逻辑,使用pass关键字占位,保证语法合法。

python 复制代码
# pass空语句用法
num = int(input('请输入一个整数:'))
if num != 1:
    pass  # 占位,无任何执行效果,保证语法不报错
else:
    print('num等于1')

基于缩进的方式表示代码块,带来的好处就是强制要求程序员要写明确的缩进,来明确代码之间的相对关系。如果缩进书写的不对,则直接报错。

像 C++ / Java 这些语言,即使完全不写缩进,语法也不会报错,代码可读性就比较差。

同时,带来的坏处就是,如果缩进层次比较多,就容易分不清楚某个语句属于哪个层级。

python 复制代码
if a == 1:
if b == 2:
if c == 3:
if d == 4:
if e == 5:
if f == 6:
if g == 7:
print("hello")
print("1")
print("2")

上述代码中的 print("1") 和 print("2") 属于 **if 语句内部** 的缩进层级(通常缩进 4 个空格或 1 个 tab)。

因此,就有了"写 Python 需要自备游标卡尺"这个梗。

例题:闰年判断

闰年的判断规则:

  1. 世纪闰年:能被 400 整除的年份

  2. 普通闰年:能被 4 整除,但不能被 100 整除的年份

python 复制代码
# 闰年判断
year = int(input('请输入要判断的年份:'))
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
    print(f'{year}年是闰年')
else:
    print(f'{year}年是平年')

5.3 循环结构:while 与 for 循环

循环语句用于重复执行某一段代码,避免重复的 CV 操作,提升代码复用率,Python 中循环分为**while循环** 和 for循环 两类

5.3.1 while 循环
(1)基础语法
python 复制代码
while 循环条件:
    循环体代码
  • 条件为真,则执行循环体代码

  • 条件为假,则结束循环

(2)代码示例
python 复制代码
# 示例1:打印1-10的整数
num = 1
while num <= 10:
    print(num)
    num += 1  # 循环变量更新,必须有,否则会死循环

# 示例2:计算1-100的和
sum_result = 0
num = 1
while num <= 100:
    sum_result += num
    num += 1
print(f'1-100的和是:{sum_result}')  # 输出:5050

代码示例:求 1! + 2! + 3! + 4! + 5!

python 复制代码
num = 1
sum = 0
while num <= 5:
    factorResult = 1
    i = 1
    while i <= num:
        factorResult *= i
        i += 1
    sum += factorResult
    num += 1
print(sum)

这个程序用到了两重循环,也就是在循环语句中也可以套循环。

5.3.2 for 循环

for 循环是 Python 中更常用的循环方式,主要用于遍历可迭代对象(如列表、字符串、range 序列等),语法更简洁,可读性更强。

(1)基本语法
python 复制代码
for 循环变量 in 可迭代对象:
    循环体

注意:

  • Python 的 for 和其他语言不同,没有"初始化语句"、"循环条件判定语句"、"循环变量更新语句",而是更加简单。

  • 所谓的"可迭代对象",指的是"内部包含多个元素,能一个一个把元素取出来的特殊变量"。

(2) range 函数

range(start, end, step) 函数用于生成一个整数序列,是 for 循环的最佳搭档:

  • start:起始值(包含),默认为 0

  • end:结束值(不包含),必填

  • step:步长,默认为 1,可设为负数实现倒序

python 复制代码
# 示例1:打印1-10的整数
for i in range(1, 11):
    print(i)

# 示例2:打印2、4、6、8、10(步长为2)
for i in range(2, 12, 2):
    print(i)

# 示例3:倒序打印10-1
for i in range(10, 0, -1):
    print(i)

# 示例4:计算1-100的和
sum_result = 0
for i in range(1, 101):
    sum_result += i
print(f'1-100的和是:{sum_result}')
5.3.3 循环控制:break 与 continue

**break **和 continue 用于在循环内部控制执行流程,两者的核心区别:

  • continue:结束本次循环,直接进入下一次循环

  • break :结束整个循环,直接跳出循环体

python 复制代码
# continue示例:吃包子,第3个包子吃出虫子,跳过第3个,继续吃后面的
for i in range(1, 6):
    if i == 3:
        continue  # 跳过本次循环,不执行后续的print
    print(f'吃完第{i}个包子')

# break示例:吃包子,第3个包子吃出半只虫,直接不吃了,结束整个循环
for i in range(1, 6):
    if i == 3:
        break  # 直接结束整个循环
    print(f'吃完第{i}个包子')
5.3.4 循环嵌套

循环内部可以嵌套循环,外层循环执行一次,内层循环执行完整的一轮,经典场景如九九乘法表。

python 复制代码
# 九九乘法表
for i in range(1, 10):
    for j in range(1, i+1):
        print(f'{j}*{i}={i*j}', end='\t')
    print()  # 换行
5.3.5 综合案例

实现"人生重开模拟器"

这是一款之前很火的文字类小游戏。玩家输入角色的初始属性之后,就可以开启不同的人生经历。大家可以在网上搜索"人生重开模拟器",就可以玩到这个游戏的各种版本。完整的程序代码较多,此处我们只实现其中的一部分逻辑。

python 复制代码
import random
import sys
import time

print("+---------------------------------------------------------------------+")
print("|                                                                     |")
print("| 花有重开日, 人无再少年                                               |")
print("|                                                                     |")
print("| 欢迎来到, 人生重开模拟器                                             |")
print("|                                                                     |")
print("+---------------------------------------------------------------------+")

# 设置初始属性
while True:
    print("请设定初始属性(可用总点数 20)")
    face = int(input("设定 颜值(1-10):"))
    strong = int(input("设定 体质(1-10):"))
    iq = int(input("设定 智力(1-10):"))
    home = int(input("设定 家境(1-10):"))
    if face < 1 or face > 10:
        print("颜值设置有误!")
        continue
    if strong < 1 or strong > 10:
        print("体质设置有误!")
        continue
    if iq < 1 or iq > 10:
        print("智力设置有误!")
        continue
    if home < 1 or home > 10:
        print("家境设置有误!")
        continue
    if face + strong + iq + home > 20:
        print("总点数超过了 20!")
        continue
    print("初始属性设定完成!")
    break

point = random.randint(1, 6)  # 掷色子
if point % 2 == 1:
    gender = 'boy'
    print("你是个男孩")
else:
    gender = 'girl'
    print("你是个女孩")

# 出生地点和家庭背景
if 1 <= point <= 2:
    print('你出生在村里, 你的父母是辛苦劳作的农民')
    strong += 1
    face -= 2
elif 3 <= point <= 4:
    print('你出生在穷乡僻壤, 你的父母是无业游民')
    home -= 1
else:
    print('你出生在镇上, 你的父母是医生')
    strong += 1

# 年龄循环
for age in range(1, 11):
    info = f'你今年 {age} 岁, '
    point = random.randint(1, 3)

    # 性别触发事件
    if gender == 'girl' and home <= 3 and point == 1:
        info += '你家里人重男轻女思想非常严重, 你被遗弃了!'
        print(info)
        print("游戏结束!")
        sys.exit(0)

    # 体质触发的事件
    elif strong < 6 and point != 3:
        info += '你生了一场病, '
        if home >= 5:
            info += '在父母的精心照料下恢复了健康'
            strong += 1
            home -= 1
        else:
            info += '你的父母没精力管你, 你的身体状况更糟糕了'
            strong -= 1

    # 颜值触发的事件
    elif face < 4 and age >= 7:
        info += '你因为长的太丑, 别的小朋友不喜欢你, '
        if iq > 5:
            info += '你决定用学习填充自己'
            iq += 1
        else:
            if gender == 'boy':
                info += '你和别的小朋友经常打架'
                iq -= 1
                strong += 1
            else:
                info += '你经常被别的小朋友欺负'
                strong -= 1

    # 智商触发的事件
    elif iq < 5:
        info += '你看起来傻傻的, '
        if home >= 8 and age >= 6:
            info += '你的父母给你送到更好的学校学习'
        elif 4 <= home <= 7:
            if gender == 'boy':
                info += '你的父母鼓励你多运动, 加强身体素质'
                strong += 1
            else:
                info += '你的父母鼓励你多打扮自己'
                face += 1
        else:
            info += '你的父母为此经常吵架'
            if point == 1:
                strong -= 1
            elif point == 2:
                iq -= 1

    # 健康成长
    else:
        info += '你健康成长, '
        if point == 1:
            info += '看起来更聪明了'
            iq += 1
        elif point == 2:
            info += '看起来更好看了'
            face += 1
        else:
            info += '看起来更结实了'
            strong += 1

    print('-------------------------------------------')
    print(info)
    print(f'strong={strong}, face={face}, iq={iq}, home={home}')
    time.sleep(1)

更多的逻辑,此处就不再实现了。大家可以按照类似的方式,设计更多的事件,完成青年、壮年、老年的相关逻辑。

六、函数

6.1函数是什么

编程中的函数和数学中的函数有一定的相似之处。

数学上的函数,比如 y = sin x,x 取不同的值,y 就会得到不同的结果。

编程中的函数,是一段可以被重复使用的代码片段。

代码示例:求束流的和,不使用函数

python 复制代码
# 1. 求 1 - 100 的和
sum = 0
for i in range(1, 101):
    sum += i
print(sum)

# 2. 求 300 - 400 的和
sum = 0
for i in range(300, 401):
    sum += i
print(sum)

# 3. 求 1 - 1000 的和
sum = 0
for i in range(1, 1001):
    sum += i
print(sum)

可以发现,这几组代码基本是相似的,只有一点点差异。可以把重复代码提取出来,做成一个函数。

实际开发中,复制粘贴是一种不太好的策略。实际开发的重复代码可能存在几十份甚至上百份。一旦这个重复代码需要被修改,那就得改几十次,非常不便于维护。

代码示例:求数列的和,使用函数

python 复制代码
# 定义函数
def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)

# 调用函数
calcSum(1, 100)
calcSum(300, 400)
calcSum(1, 1000)

可以明显看到,重复的代码已经被消除了。

6.2 函数的定义

(1)基础语法
python 复制代码
# 函数定义
def 函数名(形参列表):
    函数体代码
    return 返回值

# 函数调用
函数名(实参列表)
  • def:定义函数的关键字,固定写法

  • 函数名:和变量名遵循相同的命名规则,见名知意,推荐动词 + 名词格式(如calc_sumget_user_info

  • 形参列表:函数的输入参数,可无,可多个

  • return:函数的返回值,执行到 return 时,函数立即结束,将结果返回给调用者;无 return 时,默认返回None

  • 函数必须先定义,后调用,仅定义不调用,函数体代码不会执行

python 复制代码
# 还没有执行到定义,就先执行调用了,此时就会报错
test3()

def test3():
    print('hello')

动漫里释放技能之前,需要大喊招式的名字,就是"先定义,再使用"!!!!

(2)代码示例

数列求和函数

python 复制代码
# 定义函数:计算[beg, end]区间内所有整数的和
def calc_sum(beg, end):
    """
    计算区间内整数的和
    :param beg: 起始值(包含)
    :param end: 结束值(包含)
    :return: 区间内整数的和
    """
    sum_result = 0
    for i in range(beg, end + 1):
        sum_result += i
    return sum_result

# 调用函数,重复使用逻辑
print(calc_sum(1, 100))    # 计算1-100的和,输出:5050
print(calc_sum(300, 400))  # 计算300-400的和,输出:35350
print(calc_sum(1, 1000))   # 计算1-1000的和,输出:500500

6.2 函数的特性

6.2.1 函数参数
  • 形参与实参:形参是函数定义时括号内的参数,相当于 "占位符";实参是函数调用时传递的具体值,会赋值给对应的形参,两者数量必须匹配。

  • 动态类型参数:Python 函数的形参无需指定类型,一个函数可支持多种类型的实参,符合动态类型特性。

  • 参数默认值:可以给形参指定默认值,调用时如果不传该参数,自动使用默认值;带有默认值的参数必须放在无默认值参数的后面。

    python 复制代码
    # 参数默认值示例
    def add(x, y, debug=False):
        if debug:
            print(f'调试信息:x={x}, y={y}')
        return x + y
    
    print(add(10, 20))  # 不传递debug参数,使用默认值False,输出:30
    print(add(10, 20, True))  # 传递debug=True,打印调试信息,输出:30
  • 关键字参数:调用函数时,可通过形参名=实参的方式显式指定参数传递给哪个形参,无需严格按照形参顺序传参,提升代码可读性。

    python 复制代码
    # 关键字参数示例
    def test(x, y):
        print(f'x={x}, y={y}')
    
    test(10, 20)  # 位置传参,输出:x=10, y=20
    test(y=100, x=200)  # 关键字传参,调整顺序,输出:x=200, y=100

在函数定义的时候,可以在 ( ) 中指定"形式参数"(简称 形参),然后在调用的时候,由调用者把"实际参数"(简称 实参)传递进去。

注意:

  • 一个函数可以有一个形参,也可以有多个形参,也可以没有形参。

  • 一个函数的形参有几个,那么传递实参的时候也得传几个。保证个数要匹配。

python 复制代码
def test(a, b, c):
    print(a, b, c)

test(10)  # 这里会报错,因为只传了1个实参,但函数需要3个
  • 和 C++ / Java 不同,Python 是动态类型的编程语言,函数的形参不必指定参数类型。换句话说,一个函数可以支持多种不同类型的参数。
python 复制代码
def test(a):
    print(a)

test(10)
test('hello')
test(True)
6.2.2 函数返回值

函数的参数可以视为是函数的**"输入**",则函数的返回值,就可以视为是函数的"输出"。

此处的"输入"、"输出"是更广义的输入输出,不是单纯指通过控制台输入输出。

我们可以把函数想象成一个"工厂"。工厂需要买入原材料,进行加工,并生产出产品。函数的参数就是原材料,函数的返回值就是生产出的产品。

下列代码

python 复制代码
def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)

calcSum(1, 100)

可以转换成

python 复制代码
def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    return sum

result = calcSum(1, 100)
print(result)

这两个代码的区别就在于,前者直接在函数内部进行了打印,后者则使用 return 语句把结果返回给函数调用者,再由调用者负责打印。

我们一般倾向于第二种写法。

实际开发中我们的一个通常的编程原则,是"逻辑和用户交互分离"。而第一种写法的函数中,既包含了计算逻辑,又包含了和用户交互(打印到控制台上)。这种写法是不太好的,如果后续我们需要的是把计算结果保存到文件中,或者通过网络发送,或者展示到图形化界面里,那么第一种写法的函数,就难以胜任了。

而第二种写法则专注于做计算逻辑,不负责和用户交互。那么就很容易把这个逻辑搭配不同的用户交互代码,来实现不同的效果。

  1. 一个函数可以有多个 return 语句,执行到任意一个 return 都会立即结束函数

  2. 一个函数可以一次返回多个值,用逗号分隔,调用时用对应数量的变量接收

  3. 不需要返回值时,可省略 return,函数默认返回 None

python 复制代码
# 多个返回值示例
def get_point():
    x = 10
    y = 20
    return x, y  # 返回两个值

# 接收多个返回值
a, b = get_point()
print(a, b)  # 输出:10 20

# 用_忽略不需要的返回值
_, c = get_point()
print(c)  # 输出:20

6.3 变量作用域

变量作用域指的是变量的生效范围,Python 中分为局部变量全局变量两类:

  1. 局部变量:在函数内部定义的变量,仅在函数内部生效,函数执行结束后,变量就会被销毁,外部无法访问

  2. 全局变量:在函数外部定义的变量,在整个 py 文件中都生效,函数内部可以读取全局变量

变量只能在所在的函数内部生效。

在函数 getPoint() 内部定义的 x, y 只是在函数内部生效。一旦出了函数的范围,这两个变量就不再生效了。

python 复制代码
def getPoint():
    x = 10
    y = 20
    return x, y

getPoint()
print(x, y)  # 此处会报错,因为 x 和 y 在函数外部不存在

在不同的作用域中,允许存在同名的变量。

虽然名字相同,实际上是不同的变量。

python 复制代码
# 局部变量与全局变量
x = 20  # 全局变量

def test():
    x = 10  # 局部变量,和全局变量x只是同名,是两个不同的变量
    print(f'函数内部x={x}')  # 优先使用局部变量,输出:函数内部x=10

test()
print(f'函数外部x={x}')  # 全局变量不受影响,输出:函数外部x=20

注意:

  • 在函数内部的变量,也称为"局部变量"

  • 不在任何函数内部的变量,也称为"全局变量"

(1)扩展:global 关键字

如果需要在函数内部修改全局变量的值 ,必须使用 global关键字声明,否则会被视为创建一个新的局部变量,而非修改全局变量。

如果函数内部尝试访问的变量在局部不存在,就会尝试去全局作用域中查找。

python 复制代码
x = 20

def test():
    print(f'x = {x}')

test()  # 可以访问到全局变量 x

如果是想在函数内部修改全局变量的值,需要使用 global 关键字声明。

python 复制代码
x = 20

def test():
    global x
    x = 30

test()
print(x)  # 输出 30

如果此处没有 global,则函数内部的 x = 10 就会被视为是创建一个局部变量 x,这样就和全局变量 x 不相关了。

if / while / for 等语句块不会影响到变量作用域。

换而言之,在 if / while / for 中定义的变量,在语句外面也可以正常使用。

python 复制代码
if True:
    a = 10

print(a)  # 输出 10,可以正常访问

for i in range(5):
    b = i

print(b)  # 输出 4,可以正常访问

6.4 函数执行过程

  • 调用函数才会执行函数体代码,不调用则不会执行。

  • 函数体执行结束(或者遇到 return 语句),则回到函数调用位置,继续往下执行。

python 复制代码
def test():
    print("执行函数内部代码")
    print("执行函数内部代码")
    print("执行函数内部代码")

print("1111")
test()
print("2222")
test()
print("3333")

这个过程还可以使用 PyCharm 自带的调试器来观察。

  • 点击行号右侧的空白,可以在代码中插入断点

  • 右键,Debug,可以按照调试模式执行代码。每次执行到断点,程序都会暂停下来

  • 使用 Step Into (F7) 功能可以逐行执行代码

6.5 函数的调用

6.5.1 链式调用

前面的代码很多都是写作:

python 复制代码
# 判定是否是奇数
def isOdd(num):
    if num % 2 == 0:
        return False
    else:
        return True

result = isOdd(10)
print(result)

实际上也可以简化写作:

python 复制代码
print(isOdd(10))

把一个函数的返回值,作为另一个函数的参数,这种操作称为链式调用

这是一种比较常见的写法。

6.5.2 嵌套调用

函数内部还可以调用其他的函数,这个动作称为"嵌套调用"。

python 复制代码
def test():
    print("执行函数内部代码")
    print("执行函数内部代码")
    print("执行函数内部代码")

test 函数内部调用了 print 函数,这里就属于嵌套调用。

一个函数里面可以嵌套调用任意多个函数。

函数嵌套的过程是非常灵活的。

python 复制代码
def a():
    print("函数 a")

def b():
    print("函数 b")
    a()

def c():
    print("函数 c")
    b()

def d():
    print("函数 d")
    c()

d()

如果把代码稍微调整,打印结果则可能发生很大变化。

python 复制代码
def a():
    print("函数 a")

def b():
    a()
    print("函数 b")

def c():
    b()
    print("函数 c")

def d():
    c()
    print("函数 d")

d()

注意体会上述代码的执行顺序,可以通过画图的方式来理解。

函数之间的调用关系,在 Python 中会使用一个特定的数据结构来表示,称为函数调用栈。每次函数调用,都会在调用栈里新增一个元素,称为栈帧

可以通过 PyCharm 调试器看到函数调用栈和栈帧。

在调试状态下,PyCharm 左下角一般就会显示出函数调用栈。

每个函数的局部变量,都包含在自己的栈帧中。

python 复制代码
def a():
    num1 = 10
    print("函数 a")

def b():
    num2 = 20
    a()
    print("函数 b")

def c():
    num3 = 30
    b()
    print("函数 c")

def d():
    num4 = 40
    c()
    print("函数 d")

d()

选择不同的栈帧,就可以看到各自栈帧中的局部变量。

思考:上述代码,a、b、c、d 函数中的局部变量名各不相同。如果变量名是相同的,比如都是 num,那么这四个函数中的 num 是属于同一个变量,还是不同变量呢?

6.5.3 递归调用

递归是嵌套调用的特殊情况,即函数内部调用自身,递归代码必须满足两个核心条件:

  1. 存在明确的递归结束条件,否则会出现无限递归,导致栈溢出

  2. 每次递归调用,实参必须逐渐逼近结束条件

python 复制代码
# 递归实现:计算n的阶乘
def factor(n):
    # 递归结束条件:1的阶乘是1
    if n == 1:
        return 1
    # 递推公式:n! = n * (n-1)!
    return n * factor(n - 1)

print(factor(5))  # 计算5!,输出:120

上述代码中,就属于典型的递归操作。在 factor 函数内部,又调用了 factor 自身。

**注意:**递归代码务必要保证

  • 存在递归结束条件。比如 if n == 1 就是结束条件。当 n 为 1 的时候,递归就结束了。

  • 每次递归的时候,要保证函数的实参是逐渐逼近结束条件的。

如果上述条件不能满足,就会出现"++无限递归++"。这是一种典型的代码错误。

python 复制代码
def factor(n):
    return n * factor(n - 1)

result = factor(5)
print(result)

如前面所描述,函数调用时会在函数调用栈中记录每一层函数调用的信息。但是函数调用栈的空间不是无限大的。如果调用层数太多,就会超出栈的最大范围,导致出现问题。

递归的优缺点:

  • 优点:代码简洁,符合数学归纳法逻辑,能轻松解决树、分治等复杂问题

  • 缺点:理解门槛高,容易出现栈溢出,执行效率低于等价的循环代码,大型项目需谨慎使用

七、列表、元组与字典

基础数据类型只能存储单个值,当我们需要批量存储、处理大量数据时,就需要用到复合数据类型,Python 中最常用的就是++列表(list)元组(tuple)字典(dict)++三类。

7.1 列表是什么,元组是什么

编程中,经常需要使用变量来保存或表示数据。

如果代码中需要表示的数据个数比较少,可以直接创建多个变量:

python 复制代码
num1 = 10
num2 = 20
num3 = 30
......

但是,当代码中需要表示的数据特别多,甚至也不知道要表示多少个数据时,就需要用到列表。

列表是一种让程序员在代码中批量表示或保存数据的方式。

就像我们去超市买辣条,如果只买一两根,直接拿着就行;但如果一次买十根八根,用手拿不方便,超市老板就会给一个袋子。这个袋子,就相当于列表

元组和列表非常相似,区别在于:列表中的元素可以修改调整,而元组中的元素在创建时就设定好了,不能修改调整。

"列表"就像买散装辣条,装好袋子后,随时可以打开往里加辣条或拿出去一些。

"元组"就像买包装辣条,厂家生产好后一包就是固定的量,不能变动。

7.2 列表(list)

7.2.1 列表的创建与访问下标
(1) 创建列表
  • 创建列表主要有两种方式。[ ] 表示一个空的列表。

  • 如果需要往里面设置初始值,可以直接写在 [ ] 当中。

可以直接使用 print 来打印 list 中的元素内容。

  • 列表中存放的元素允许是不同的类型(这一点和 C++/Java 差别较大)。

因为 list 本身是 Python 中的内建函数,不宜再使用 list 作为变量名,因此命名为 alist。

python 复制代码
# 创建列表
# 创建空列表
alist = []
alist = list()
# 创建带初始值的列表,支持任意类型元素
alist = [1, 2, 3, 4]
alist = [1, 'hello', True, 3.14]
print(alist)  # 输出:[1, 'hello', True, 3.14]
(2) 访问下标
  • 可以通过下标访问操作符 [ ] 来获取到列表中的任意元素。

我们把 [ ] 中填写的数字,称为下标或者索引。

python 复制代码
alist = [1, 2, 3, 4]
print(alist[2])

**注意:**下标是从 0 开始计数的,因此下标为 2,则对应着 3 这个元素。

  • 通过下标不光能读取元素内容,还能修改元素的值。

    python 复制代码
    alist = [1, 2, 3, 4]
    alist[2] = 100
    print(alist)
  • 如果下标超出列表的有效范围,会抛出异常。

    python 复制代码
    alist = [1, 2, 3, 4]
    print(alist[100])
  • 因为下标是从 0 开始的,因此下标的有效范围是 [0, 列表长度 - 1] 。使用 len 函数可以获取到列表的元素个数。

    python 复制代码
    alist = [1, 2, 3, 4]
    print(len(alist))
  • 下标可以取负数,表示"++倒数第几个元素++"。

    python 复制代码
    alist = [1, 2, 3, 4]
    print(alist[3])
    print(alist[-1])

alist[-1] 相当于 alist[len(alist) - 1] 。

7.2.2 切片操作

切片用于一次获取列表中的一组连续元素,生成一个子列表,语法为 列表[起始下标:结束下标:步长] ,核心规则:

  • 区间是前闭后开:包含起始下标元素,不包含结束下标元素

  • 起始下标、结束下标可省略:省略起始下标从 0 开始,省略结束下标到列表末尾

  • 步长:每次访问元素后,下标增加的数值,默认为 1,负数表示从后往前取

python 复制代码
# 切片操作示例
alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 基础切片:[1:3],取下标1、2的元素
print(alist[1:3])  # 输出:[2, 3]

# 省略边界
print(alist[1:])   # 省略结束下标,取到末尾,输出:[2, 3, 4, 5, 6, 7, 8, 9, 10]
print(alist[:-1])  # 省略起始下标,从开头取到倒数第二个元素,输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]
print(alist[:])    # 省略两个边界,复制整个列表,输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 指定步长
print(alist[::2])  # 步长2,取奇数位元素,输出:[1, 3, 5, 7, 9]
print(alist[::-1]) # 步长-1,列表倒序,输出:[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
7.2.3 常用操作
操作类型 方法 / 语法 功能说明
新增元素 append(value) 在列表末尾添加一个元素
新增元素 insert(index, value) 在指定下标位置插入元素
删除元素 pop() 删除列表末尾的元素,返回被删除的元素
删除元素 pop(index) 删除指定下标的元素,返回被删除的元素
删除元素 remove(value) 删除第一个匹配 value 的元素
查找元素 value in alist 判断 value 是否在列表中,返回布尔值
查找元素 index(value) 查找 value 第一次出现的下标,不存在则抛异常
遍历元素 for elem in alist 直接遍历列表中的每个元素
遍历元素 for i in range(len(alist)) 通过下标遍历列表
列表拼接 alist + blist 拼接两个列表,生成新列表,不修改原列表
列表拼接 extend(blist) 将 blist 的元素拼接到 alist 末尾,修改 alist

7.3 元组(tuple)

元组和列表功能几乎一致,核心区别是:元组是不可变类型,创建完成后,无法修改里面的元素、新增 / 删除元素,相当于 "只读列表"。

(1) 基础用法

元组使用 ( ) 来表示。

python 复制代码
# 1. 创建元组
atuple = ()
atuple = tuple()
atuple = (1, 2, 3, 4)
atuple = (1, 'hello', True)
print(atuple)  # 输出:(1, 'hello', True)

# 2. 支持的操作(只读类)
print(atuple[0])    # 下标访问,输出:1
print(atuple[1:3])  # 切片,输出:('hello', True)
print(len(atuple))  # 获取长度,输出:3
print(1 in atuple)  # 判断元素是否存在,输出:True

# 3. 不支持的操作(修改类)
# atuple[0] = 100  # 报错,元组不支持修改元素
# atuple.append(200) # 报错,元组不支持新增元素
(2) 使用场景
  1. 数据不希望被修改时,使用元组保证数据安全,比如函数返回多个值时,默认返回的就是元组

  2. 元组是可哈希类型,可以作为字典的 key,而列表不行

  3. 元组的内存占用更小,访问效率更高,只读场景下优先使用元组

(3) 疑问

既然已经有了列表,为啥还需要有元组?

先对比一下:

特性 列表(list) 元组(tuple)
可变性 可变,支持增删改查 不可变,创建后无法修改
表示符号 [] ()
支持的操作 下标、切片、遍历、增删改查、拼接 下标、切片、遍历、拼接(生成新元组)
可哈希性 不可哈希,不能作为字典的 key 可哈希,能作为字典的 key
性能 内存占用略高,修改效率高 内存占用小,访问效率更高
适用场景 数据需要动态变化的场景 数据固定、不希望被修改的场景

元组相比于列表来说,优势有两方面:

  1. 你有一个列表,现在需要调用一个函数进行一些处理。但是你又不太确认这个函数是否会把你的列表数据弄乱。那么这时候传一个元组就安全很多。

  2. 我们马上要讲的字典,是一个键值对结构。要求字典的键必须是"可 hash 对象"(字典本质上也是一个 hash 表)。而一个可 hash 对象的前提就是不可变。因此元组可以作为字典的键,但是列表不行。

7.4 字典(dict)

7.4.1 字典是什么

字典是一种存储键值对的结构。

++啥是键值对?++这是计算机/生活中一个非常广泛使用的概念。把键(key)和值(value)进行一个一对一的映射,然后就可以根据键,快速找到值。

**举个栗子~~**学校的每个同学,都会有一个唯一的学号。知道了学号,就能确定这个同学。此处"学号"就是"键",这个"同学"就是"值"。

7.4.2 字典的创建与常用操作
(1) 创建字典
  • 创建一个空的字典,使用 { } 表示字典。
python 复制代码
a = { }
b = dict()
print(type(a))
print(type(b))
  • 也可以在创建的同时指定初始值。

  • 键值对之间使用 `,` 分割,键和值之间使用 `:` 分割(冒号后面推荐加一个空格)。

  • 使用 print 来打印字典内容。

    python 复制代码
    student = { 'id': 1, 'name': 'zhangsan' }
    print(student)
  • 为了代码更规范美观,在创建字典的时候往往会把多个键值对分成多行来书写。

    python 复制代码
    student = {
        'id': 1,
        'name': 'zhangsan'
    }
  • 最后一个键值对,后面可以写 `,` 也可以不写。

    python 复制代码
    student = {
        'id': 1,
        'name': 'zhangsan',
    }
(2) 常用操作
操作类型 方法 / 语法 功能说明
查找 key key in dict 判断 key 是否在字典中,返回布尔值,时间复杂度 O (1)
遍历字典 for key in dict 遍历字典的所有 key,通过 key 获取 value
获取所有 key keys() 返回字典中所有的 key,类型为 dict_keys
获取所有 value values() 返回字典中所有的 value,类型为 dict_values
获取所有键值对 items() 返回字典中所有的 (key, value) 元组,类型为 dict_items
python 复制代码
# 字典遍历与常用操作
student = {
    'id': 1,
    'name': '张三',
    'age': 20,
    'score': 90.5
}

# 1. 遍历字典
for key in student:
    print(f'{key}: {student[key]}')

# 2. 遍历键值对
for key, value in student.items():
    print(f'{key}: {value}')

# 3. 获取所有key和value
print(student.keys())   # 输出:dict_keys(['id', 'name', 'age', 'score'])
print(student.values()) # 输出:dict_values([1, '张三', 20, 90.5])
7.4.3 合法的 key 类型

字典的 key 必须是可哈希类型(不可变类型),value 可以是任意类型。

  • 合法的 key 类型:int、float、str、bool、元组(元素均为不可变类型)

  • 非法的 key 类型:列表、字典(可变类型,不可哈希,无法计算哈希值)

python 复制代码
# 合法的key
dict1 = {
    1: '整数key',
    'name': '字符串key',
    (1,2,3): '元组key'
}

# 非法的key,会报错
# dict2 = {
#     [1,2,3]: '列表key'  # TypeError: unhashable type: 'list'
# }

八、文件

变量中的数据存储在内存中,程序重启或电脑关机后,数据就会丢失。如果需要长期保存数据,就需要将数据写入到硬盘的文件中,实现数据持久化

在 Windows"此电脑"中,看到的内容都是文件。

通过文件的后缀名,可以看到文件的类型。常见的文件类型如下:

  • 文本文件(txt)
  • 可执行文件(exe、dll)
  • 图片文件(jpg、gif)
  • 视频文件(mp4、mov)
  • Office 文件(.ppt、.docx)
  • ......

8.1 文件路径

一个机器上会存在很多文件,为了让这些文件更方便地被组织,往往会使用很多的"文件夹"(也叫做目录)来整理文件。

实际一个文件往往是放在一系列的目录结构之中的。

为了方便确定一个文件所在的位置,使用文件路径来进行描述。

例如,QQ.exe 这个文件,描述它的位置就可以使用路径 D:\program\qq\Bin\QQ.exe 来表示:

  • D : 表示盘符,不区分大小写

  • 每一个 \ 表示一级目录。当前 QQ.exe 就是放在"++D 盘下的 program 目录下的 qq 目录下的 Bin 目录中++"

  • 目录之间的分隔符,可以使用 \ 也可以使用 / 。一般在编写代码的时候使用 / 更方便。

上述以盘符开头的路径,我们也称为绝对路径

除了绝对路径之外,还有一种常见的表示方式是相对路径。相对路径需要先指定一个基准目录,然后以基准目录为参照点,间接地找到目标文件。咱们课堂上暂时不详细介绍。

描述一个文件的位置,使用绝对路径相对路径都是可以的。对于新手来说,使用绝对路径更简单、更好理解,也不容易出错。

8.2 文件操作

文件操作的核心分为 3 步:打开文件 → 读写文件 → 关闭文件 ,Python 通过内置函数 open() 完成文件操作。

8.2.1 open 函数
python 复制代码
open(file, mode, encoding=None)
  • file:必填,文件的路径(绝对路径 / 相对路径)

  • mode:必填,文件的打开模式,常用模式如下表

  • encoding:可选,指定文件的编码格式,读取中文文件时,通常指定为utf-8,避免乱码

打开模式 含义 核心说明
r 只读模式 默认模式,文件必须存在,不存在则抛异常,只能读取,不能写入
w 只写模式 文件不存在则创建,文件存在则清空原有内容,只能写入,不能读取
a 追加写模式 文件不存在则创建,文件存在则在末尾追加内容,不会清空原有内容
rb 二进制只读模式 用于读取图片、视频、音频等二进制文件
wb 二进制只写模式 用于写入二进制文件
8.2.2 打开文件

使用内建函数 open 打开一个文件。

python 复制代码
open(file, mode, encoding=None)
  • 第一个参数是一个字符串,表示要打开的文件路径

  • 第二个参数是一个字符串,表示打开方式。其中 `r` 表示按照读方式打开,w 表示按照写方式打开,a 表示追加写方式打开

  • 如果打开文件成功,返回一个文件对象。后续的读写文件操作都是围绕这个文件对象展开。

  • 如果打开文件失败(比如路径指定的文件不存在),就会抛出异常。

8.2.3 关闭文件

文件操作完成后必须调用close() 关闭文件,否则会出现文件句柄泄漏,导致系统能打开的文件数量达到上限。Python 提供了 with 上下文管理器,会在代码块执行完毕后自动关闭文件,无需手动调用 close(),是工业级开发的首选写法。

一个程序能同时打开的文件个数,是存在上限的。

python 复制代码
flist = []
count = 0
while True:
    f = open('d:/test.txt', 'r')
    flist.append(f)
    count += 1
    print(f'count = {count}')

如上面代码所示,如果一直循环地打开文件,而不去关闭的话,就会出现上述报错。当一个程序打开的文件个数超过上限,就会抛出异常。

**注意:**上述代码中,使用一个列表来保存了所有的文件对象。如果不进行保存,那么 Python 内置的垃圾回收机制,会在文件对象销毁的时候自动关闭文件。

但是由于垃圾回收操作不一定及时,所以我们写代码仍然要考虑手动关闭,尽量避免依赖自动关闭。

8.2.4 写文件

文件打开之后,就可以写文件了。

写文件要使用写方式打开,open 第二个参数设为 'w' 。

  • 使用 write 方法写入文件
python 复制代码
f = open('d:/test.txt', 'w')
f.write('hello')
f.close()

用记事本打开文件,即可看到文件修改后的内容。

  • 如果是使用 'r' 方式打开文件,则写入时会抛出异常。

    python 复制代码
    f = open('d:/test.txt', 'r')
    f.write('hello')
    f.close()
  • 使用 'w' 一旦打开文件成功,就会清空文件原有的数据。

  • 使用 'a' 实现"追加写",此时原有内容不变,写入的内容会存在于之前文件内容的末尾。

    python 复制代码
    f = open('d:/test.txt', 'w')
    f.write('hello')
    f.close()
    
    f = open('d:/test.txt', 'a')
    f.write('world')
    f.close()
  • 针对已经关闭的文件对象进行写操作,也会抛出异常。

python 复制代码
f = open('d:/test.txt', 'w')
f.write('hello')
f.close()
f.write('world')
8.2.5 读文件
  • 读文件内容需要使用 'r' 的方式打开文件

  • 使用 read 方法完成读操作。参数表示"读取几个字符"。

    python 复制代码
    f = open('d:/test.txt', 'r')
    result = f.read(2)
    print(result)
    f.close()
  • 如果文件是多行文本,可以使用 for 循环一次读取一行。

先构造一个多行文件。

python 复制代码
f = open('d:/test.txt', 'r')
for line in f:
    print(f'line = {line}')
f.close()

注意:由于文件里每一行末尾都自带换行符,print 打印一行的时候又会默认加上一个换行符,因此打印结果看起来之间存在空行。

使用 print(f'line = {line}', end='') 手动把 print 自带的换行符去掉。

  • 使用 readlines 直接把文件整个内容读取出来,返回一个列表,每个元素即为一行。
python 复制代码
f = open('d:/test.txt', 'r')
lines = f.readlines()
print(lines)
f.close()

此处的 \n 即为换行符。

8.3 中文乱码解决方法

(1) 中文处理

Python 读取中文文件出现乱码,核心原因是文件本身的编码格式和代码中指定的编码格式不匹配。

当文件内容存在中文的时候,读取文件内容不一定顺利。同样上述代码,有的同学执行时可能会出现异常

也有的同学可能出现乱码。

计算机表示中文的时候,会采取一定的编码方式,我们称为"字符集"。

**注意:**所谓"编码方式",本质上就是使用数字表示汉字。

我们知道,计算机只能表示二进制数据。要想表示英文字母、汉字或其他文字符号,都要通过编码。

最简单的字符编码就是 ASCII,使用一个简单的整数就可以表示英文字母和阿拉伯数字。

但是要想表示汉字,就需要一个更大的码表。

一般常用的汉字编码方式,主要是 GBK 和 UTF-8。

必须要保证文件本身的编码方式,和 Python 代码中读取文件使用的编码方式匹配,才能避免出现上述问题。

Python 3 中默认打开文件的字符集跟随系统,而 Windows 简体中文版的字符集采用了 GBK,所以如果文件本身是 GBK 的编码,直接就能正确处理。如果文件本身是其他编码(比如 UTF-8),那么直接打开就可能出现问题。

使用记事本打开文本文件,在++"菜单栏" -> "文件" -> "另存为"窗口++中,可以看到当前文件的编码方式。

  • 如果此处的编码为 ANSI,则表示 GBK 编码

  • 如果此处为 UTF-8,则表示 UTF-8 编码

此时修改打开文件的代码,给 open 方法加上 encoding 参数,显式地指定为和文本相同的字符集,问题即可解决。

python 复制代码
f = open('d:/test.txt', 'r', encoding='utf8')

**PS:**字符编码问题是编程中一类比较常见又比较棘手的问题,需要对字符编码有一定的理解才能从容应对。同学们可以参考腾讯官方账号发表的帖子,详细介绍了里面的细节:程序员必备:彻底弄懂常见的7种中文字符编码 - 知乎

(2) 使用上下文管理器

打开文件之后,是容易忘记关闭的。Python 提供了上下文管理器,来帮助程序员自动关闭文件。

  • 使用 with 语句打开文件

  • 当 with 内部的代码块执行完毕后,就会自动调用关闭方法

python 复制代码
with open('d:/test.txt', 'r', encoding='utf8') as f:
    lines = f.readlines()
    print(lines)

九、总结常见错误与解决方案

9.1 语法类错误

  • 缩进错误:Tab 和空格混合缩进、缩进层级不对,会报 IndentationError

解决方案:统一使用 4 个空格作为一级缩进,开启 IDE 的 "将 Tab 转换为空格" 功能

  • 语法格式错误:if/for/while/def 语句末尾忘记加冒号:,括号不匹配

解决方案:写完一行代码后检查冒号,IDE 会自动标红语法错误,及时修正

  • 关键字作为变量名:使用 if、for、def、list、dict 等关键字 / 内置函数作为变量名,导致后续调用报错

解决方案:禁止使用 Python 关键字和内置函数作为变量名

9.2 数据类型类错误

  • input 输入的类型转换错误:input 返回的是字符串,直接进行算术运算,导致类型错误

解决方案:输入数值时,先通过 int()/float() 转换类型,再进行运算

  • 字符串与数字直接拼接:print('年龄:' + 20),会报 TypeError

解决方案:使用 f-string 格式化,或先将数字转为字符串 str(20)

  • 浮点数直接用 == 判断相等:0.1 + 0.2 == 0.3 结果为 False

解决方案:判断两个浮点数的差值在允许的误差范围内,而非直接相等

9.3 逻辑类错误

  • while 循环忘记更新循环变量:导致死循环

解决方案: while 循环必须在循环体内更新循环变量,确保循环能结束

  • if 条件判断用 = 代替 ==:if num = 10:,会报语法错误

解决方案:相等判断必须用双等号 ==,赋值用单等号 =,区分两者用途

  • 列表 / 字典遍历过程中修改元素:导致遍历异常、元素遗漏

解决方案:遍历过程中不要删除元素,可先复制一份列表,再遍历原列表、修改复制后的列表

9.4 文件操作类错误

  • 文件路径错误:文件不存在,报 FileNotFoundError

解决方案:使用绝对路径,确保路径书写正确,斜杠使用 / 而非 \ (避免转义)

  • 中文乱码:读取中文文件出现乱码

解决方案:打开文件时显式指定 encoding='utf-8',匹配文件的实际编码

  • 文件忘记关闭:导致文件句柄泄漏

解决方案:统一使用 with 上下文管理器打开文件,自动关闭,无需手动处理

十、总结

本文系统梳理了Python基础语法的核心内容:

  1. 基础语法:常量、变量、数据类型、输入输出

  2. 运算符:算术、关系、逻辑、赋值运算符的使用与注意事项

  3. 条件语句if-elif-else 结构及Python特有的缩进语法

  4. 循环语句whilefor 循环及 continue/break 的使用

  5. 函数:定义、调用、参数传递、返回值、作用域、递归等核心概念

  6. 列表与元组:序列数据的创建、访问、修改与遍历

  7. 字典:键值对结构的使用及哈希表的底层原理

  8. 文件操作:文件的打开、读写、关闭及编码处理

Python是一门"易学难精"的语言。掌握这些基础语法只是第一步,后续还需要不断练习,在实战中深入理解。建议读者在学习过程中多动手写代码,用实践检验知识,才能真正将Python内化为自己的技能。

参考资料

1\] Python 3.10+ 官方文档:[https://docs.python.org/3/](https://docs.python.org/3/ "https://docs.python.org/3/") \[2\] PEP 8 -- Style Guide for Python Code:[https://peps.python.org/pep-0008/](https://peps.python.org/pep-0008/ "https://peps.python.org/pep-0008/") \[3\] 比特就业课 Python 基础语法体系 \[4\] TIOBE 编程语言排行榜 2026 年 4 月榜单:[https://www.tiobe.com/tiobe-index/](https://www.tiobe.com/tiobe-index/ "https://www.tiobe.com/tiobe-index/") \[5\][\*.py:以二进制模式打开文件,必要时显式解码为UTF-8(a5349f5d)·提交次数·基里尔·斯梅尔科夫 / pygolang ·GitLab![](https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/CsdnLink/icons/icon-default.png)https://lab.nexedi.com/kirr/pygolang/-/commit/a5349f5d7e53b877db3ab4f2da7c5787e5d460d1](https://lab.nexedi.com/kirr/pygolang/-/commit/a5349f5d7e53b877db3ab4f2da7c5787e5d460d1 "*.py:以二进制模式打开文件,必要时显式解码为UTF-8(a5349f5d)·提交次数·基里尔·斯梅尔科夫 / pygolang ·GitLab") \[6\][Python中元组和列表差异:底层结构分析-CSDN博客](https://blog.csdn.net/2502_92691558/article/details/159931135 "Python中元组和列表差异:底层结构分析-CSDN博客") \[7

Python中列表List和元组Tuple的区别_聚合数据 - 天聚地合https://www.juhe.cn/news/index/id/10101

8

Python函数注解怎么写_类型提示实战解析【教程】-Python教程-PHP中文网https://www.php.cn/faq/1884574.html

9\][Python数据结构的性能比较 -- Multiable 万达宝](https://blog.multiable.com.cn/wz_95104.htm "Python数据结构的性能比较 – Multiable 万达宝") \[10\][解包 Python 的泛泛函数签名参数参数(ParamSpec.kwargs)![](https://csdnimg.cn/release/blog_editor_html/release2.4.6/ckeditor/plugins/CsdnLink/icons/icon-default.png)https://runebook.dev/en/docs/python/library/typing/typing.ParamSpec.kwargs](https://runebook.dev/en/docs/python/library/typing/typing.ParamSpec.kwargs "解包 Python 的泛泛函数签名参数参数(ParamSpec.kwargs)") \[11

快速学会使用Python3.12的新特性https://www.e-com-net.com/article/1727604706739564544.htm

结尾留言

本篇文章3w+字数,耗时近一周,每天都在写作,免不了排版失误,缺失注解和理论错误,欢迎指正!最近sbti很火,俺也去测了测,以下是作者滴,仅供娱乐,欢迎读者们分享(●'◡'●)。

如果本文对你有帮助,欢迎点赞、收藏、评论交流~如果你在 Python 学习过程中有任何问题,都可以在评论区留言,我会一一解答。

相关推荐
Chasing Aurora2 小时前
整理常用的开发工具使用问题和小贴士(二)——软件和浏览器
redis·python·mysql·maven
源代码杀手2 小时前
利用MATLAB®和Simulink®资源的可再生能源
开发语言·matlab
请数据别和我作队2 小时前
Python实现直播弹幕数据采集(WebSocket实时弹幕采集)
开发语言·网络·python·websocket·网络协议·学习分享
biter down2 小时前
C++11 可变参数模板
开发语言·c++
无心使然云中漫步2 小时前
ArcGis常用服务介绍及Arcgis,Openlayers,Leaflet加载
开发语言·arcgis·php
锦瑟弦音2 小时前
Java与SQL基础知识总结
java·开发语言
大黄说说2 小时前
React Hooks 与 Class Components 的本质区别:从“面向对象”到“函数式”的范式转移
开发语言
sycmancia2 小时前
Qt——对话框及其类型
开发语言·qt
IP老炮不瞎唠2 小时前
为什么Python爬虫需要代理 IP?原理与应用详解
爬虫·python·tcp/ip