Python 学习笔记:基础篇
1. 安装 Python
点击下载 Python 3.13.9
安装时勾选 Use admin privileges when installing py.exe 和 Add python.exe to PATH
请自行下载并安装 PyCharm
2. 配置 Python 镜像源
打开 CMD,在其中执行以下命令:
# 升级 PIP
python -m pip install -i https://mirrors.huaweicloud.com/repository/pypi/simple --upgrade pip# 生成 pip.ini 配置文件
pip config set global.index-url https://mirrors.huaweicloud.com/repository/pypi/simple# 编辑 pip.ini 配置文件
[global]
index-url = https://mirrors.huaweicloud.com/repository/pypi/simple
trusted-host = mirrors.huaweicloud.com
timeout = 120
测试项目:获取硬件规格
- 在 PyCharm 中创建一个 python 项目
- 使用 PyCharm 终端安装 psutil 工具
# 安装
pip install psutil# 验证安装
pip list
Package Version
------- -------
pip 25.1.1
psutil 7.1.1 # <- HERE
- 在项目中新建一个
.py文件,在其中添加以下代码
import psutilprint(psutil.cpu_count(logical=False)) # 获取 CPU 物理核心数
print(psutil.cpu_count()) # 获取 CPU 逻辑核心数
- 执行文件,即可看到结果
14
28
3. Python 基础
3.1 Python 语法规则
Python 不同于常见的 C 或 Java 语言,其语末没有 ; 标记,且不使用 {} 标记代码块,使用类似 yaml 语法的缩进进行标记代码所属
示例:
for i in range(5):print(i) # 属于 for 循环print("Hello,world!") # 属于 for 循环
print("End") # 不属于 for 循环
3.2 注释
Python 使用 # 标记单行注释,使用 ''' 或 """ 标记多行注释,语法如下:
# 单行注释'''
多行注释
'''"""
多行注释
"""
[!TIP]
在 PyCharm 中,可以选中需要注释的代码范围,按下
Ctrl + /进行快速注释
3.3 输出函数
3.4 标识符与关键字
Python 的标识符命名规则如下:
- 标示符可以由字母、下划线和数字组成
- 标识符不能以数字开头
- Python 中的标识符严格区分大小写,如
tom和Tom是不同的标识符 - Python 中的标识符不能使用关键字
使用以下代码可以查看关键字列表
import keyword
print(keyword.kwlist)
Python 的标识符命名规范如下:
- 见名知意,如(姓名:name;年龄:age)
- 常量名使用大写的单个单词或由下画线连接的多个单词(ORDER_LIST_LIMIT)。
- 模块名、函数名使用小写的单个单词或由下画线连接的多个单词(low_with_under)。
- 类名使用大写字母开头的单个或多个单词。(Cat,Dog,Person)
3.5 变量
Python 变量不需要在定义时为其指定数据类型
num = 10
print(num)
3.6 数据类型
Python 数据类型大致可分为以下几类:
- 数值
- 字符串
- 组合数据
3.6.1 数值
数值包括以下具体数据类型
| 数据类型 | 示例 |
|---|---|
| 整型(int) | 10、-10、True(1)、False(0) |
| 浮点型(float) | 3.14、-2.7、0.0、2.0 |
| 复数(complex) | 2x+3 |
整型类型用于表示整数,在计算机中,整型常用的计数方式有4种
- 二进制:以
0b或0B开头,使用bin()进行类型转换 - 八进制:以
0o或0O开头,使用oct()进行类型转换 - 十进制:使用
int()进行类型转换 - 十六进制:以
0x或0X开头,使用hex()进行类型转换
在 Python 中,浮点类型属于特殊的整形,其 True 值为 1,False 值为 0
3.6.2 组合数据
组合数据又分为以下三类
- 组合数据
- 序列
- 集合(set)
- 映射(dict)
序列包含一下数据类型
| 数据类型 | 说明 | 示例 |
|---|---|---|
| 列表(list) | 使用 [] 标记,可以存放任意数量、任意类型的元素,可以被修改 | [1, 2, 'hello'] |
| 元组(tuple) | 使用 () 标记,可以存放任意数量、任意类型的元素,不可被修改 | (1, 2, 'hello') |
集合类型与列表和元素类似,可以存放任意数量、任意类型的元素,区别是,集合类型中的数据无序且唯一,使用 {} 标记
映射类型又名字典类型,使用 键(key):值(value) 的键值对方式存储数据,键不能重复,使用 {} 创建键值对
3.6.3 数据类型转换
使用 (数据类型)变量名 可以对变量的数据类型进行转换
| 数据类型中文名 | 数据类型英文名 |
|---|---|
| 整形 | int |
| 浮点型 | float |
| 字符串 | str |
| 列表 | list |
| 元组 | tuple |
| 集合 | set |
| 字典 | dict |
| 复数 | complex |
3.7 变量的输入和输出
变量的输入使用 input() 函数,变量的输出使用 print() 函数
示例:
num = input("Input a number: ")
print(num)
运行效果如下:
Input a number: # 100
100
3.7.1 输入函数 input()
输入函数默认的输入数据类型为 str
语法如下:
变量=input([提示字符串])
示例:
age = input("Please input your age: ")
3.7.2 输出函数 print()
print() 函数语法如下:
print([输出文本][, sep=分隔符][, end=结尾符][, file=输出文件对象])# 输出文本:字面意思
# 分隔符:设置多个内容之间使用指定字符进行分割,默认为空格
# 结尾符:设置输出结尾符号,默认为回车 \n
示例:
for i in range(10):print(i, end='')print()for i in range(10):print(i, end=' ')
示例 2:九九乘法表
for i in range(1,10):for j in range(1,i+1):print(f'{j}x{i}={i*j}',end='\t')print()
3.8 运算符
3.8.1 算术运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
+ | 算数加运算符 | 1+3=4 |
- | 算数减运算符 | 3-1=2 |
* | 算数乘运算符 | 1*3=3 |
/ | 算数除运算符,结果自动转换为浮点数 | 10/5=2.0 |
// | 算数整除运算符,结果保留 int 类型 | 10//5=2 |
% | 取余运算符 | 10%3=1 |
** | 幂运算符,a**b 实为 a^b | 2**3=8 |
3.8.2 赋值运算符
| 运算符 | 说明 | 示例 |
|---|---|---|
+= | 变量增加指定的数值 | 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 |
%= | 变量取余指定的数值 | a%=2 等价于 a=a%2 |
**= | 变量幂运算指定的数值 | a**=2 等价于 a=a**2 |
:= | 海象运算符,更新于 python3.8,用于在表达式内部为变量赋值 | result = num_one + (num_two:=2) |
3.8.3 比较运算符
| 运算符 | 说明 |
|---|---|
| == | 比较两个值是否相等 |
| != | 比较两个值是否不相等 |
| > | 比较某个值是否大于另一个值 |
| < | 比较某个值是否小于另一个值 |
| >= | 比较某个值是否大于等于另一个值 |
| <= | 比较某个值是否小于等于另一个值 |
3.8.4 逻辑运算符
| 运算符 | 说明 |
|---|---|
| AND | 逻辑与运算符 |
| OR | 逻辑或运算符 |
| NOT | 逻辑非运算符 |
3.8.5 成员运算符
| 运算符 | 说明 |
|---|---|
| IN | 判断某个值是否位于某个成员中 |
| NOT IN | 判断某个值是否不位于某个成员中 |
3.8.6 位运算符
| 运算符 | 说明 |
|---|---|
| >> | 操作数按位右移 |
| << | 操作数按位左移 |
| & | 按位与运算 |
| | | 按位或运算 |
| ^ | 按位非运算 |
| ~ | 按位取反 |
4. 流程控制语句
4.1 判断语句
4.1.1 if
if 语句语法如下:
if 条件表达式:代码块
当条件表达式值为 True 时,执行代码块;若条件表达式值为 False 时,则跳过代码块
示例:判断输入的成绩是否合格,若合格,输出 “PASS”
score=input("Please input score: ")
if int(score)>=60:print("PASS")
执行效果如下:
Please input score: # 88
PASSPlease input score: # 10
# 无输出
4.1.2 if-else
if-else 语句语法如下:
if 条件表达式:代码块1
else:代码块2
当条件表达式值为 True 时,执行代码块1;若条件表达式值为 False 时,则执行代码块2
示例:判断输入的成绩是否合格,若合格,输出 “PASS”;若不合格,输出 “FAIL”
score=input("Please input score: ")
if int(score)>=60:print("PASS")
else:print("FAIL")
执行效果如下:
Please input score: # 88
PASSPlease input score: # 10
FAIL
4.1.3 if-elif-else
if-elif-else 语句语法如下:
if 条件表达式1:代码块1
elif 条件表达式2:代码块2
elif 条件表达式3:代码块3
...
else:代码块n
从条件表达式1开始进行逻辑判断,直到结果为 True 时,执行对应的代码块
示例 1:对输入的成绩进行判断,90~100 输出 “A”,80~89 输出 “B”,70~79 输出 “C”,60~69 输出 “D”,其余输出 “E”
score=input("Please input score: ")
score=int(score)if score>=90:print("A")
elif score>=80:print("B")
elif score>=70:print("C")
elif score>=60:print("D")
else:print("E")
运行效果如下:
Please input score: # 100
APlease input score: # 74
CPlease input score: # 50
E
示例 2:输入年份和月份,输出这个月有多少天
year=int(input("Enter year: "))
month=int(input("Enter month: "))if month in (1,3,5,7,8,10,12):print("31 Days")
elif month == 2:if year%400==0 or (year%4==0 and year%100!=0):print("29 Days")else:print("28 Days")
else:print("30 Days")
4.2 循环语句
4.2.1 while
while 语句语法如下:
while 循环条件:循环体
当循环条件为 True 时,执行循环体,然后返回继续判断循环条件,如果仍为 True,则继续循环,如果为 False,则退出循环
示例:输出 1~10
num=1
while num<=10:print(num,end=' ')num=num+1
输出效果如下:
1 2 3 4 5 6 7 8 9 10
4.2.2 for
for 循环语句语法如下:
for 变量名 in 范围:循环体for 变量名 in range(其实范围,终止范围,变化规则)
示例:求和 1~100
sum=0
for i in range(1,101):sum=sum+i
print(sum)
示例:求 1~100 的基数和
sum=0
for i in range(1,101,2):sum=sum+i
print(sum)
4.2.3 continue
continue 关键字用于跳过本次循环,从 continue 所在位置以后的循环体代码将不会继续执行
示例:
for i in range(3):print("Hello,world!")continueprint("This wont be print")
输出如下:
Hello,world!
Hello,world!
Hello,world!
4.2.4 break
break 关键字用于退出当前循环,从 break 所在位置以后的循环体及循环判断将不会继续执行,程序将直接从循环后的代码继续运行
示例:
for i in range(5):print("Hello,world!")if i == 2:breakprint("This only print 2 times")
输出如下:
Hello,world!
This only print 2 times
Hello,world!
This only print 2 times
Hello,world!
5. 字符与字符串
5.1 字符串样式
Python 中使用 ' '、" "、''' ''' 定义字符串,其中 ' ' 和 " " 通常用于定义单行字符串,''' ''' 通常用于定义多行字符串
如:
print('Hello,world!') # 单引号,单行
print("Hello,world!") # 双引号,单行
print('''Hello,
World!''') # 三引号,多行
输出如下:
Hello,world!
Hello,world!
Hello,
World!
[!IMPORTANT]
注:尽量避免出现同类型引号功能混用的状况,如
print('it's work!')
5.2 转义字符
转义字符使用 \ 加上特定的字符组成转义字符,以实现特殊的功能
常见的转义字符如下:
| 转义字符 | 功能 |
|---|---|
\b | 退格(Backspace) |
\n | 换行 |
\v | 纵向制表符 |
\t | 横向制表符(Tab) |
\r | 回车(Enter) |
5.3 字符串格式化
格式化字符串是指将的字符串转化为想要的格式,Python 中有三种格式化字符串的方式:使用 % 格式化、使用 format() 方法格式化和使用 f-string 格式化
5.3.1 %
使用 % 加上一个字符可以指定一个占位符,用于指定这个位置将要填入的数据的数据类型,常用的占位符类型如下:
| 格式占位符 | 格式 |
|---|---|
%c | 字符 |
%s | 字符串 |
%d | 整型 |
%u | 无符号整型 |
%o | 无符号八进制整形 |
%x | 无符号十六进制整形 |
%f | 浮点型,可指定小数位数,默认为 6 位 |
填入数据,需要使用 字符串变量名 % 填入数据变量 的形式进行,如:
txt = "I'm %d years old"
age = 20
print(txt % 20) # 直接赋值
print(txt % age) # 使用变量赋值
如果遇到多个变量赋值,则需要使用 () 将变量扩起,示例
name = "ZhangSan"
age = 20
info='''name: %s
age: %d'''print(info % (name, age))
输出如下:
name: ZhangSan
age: 20
5.3.2 format()
Python 可以在字符串变量名后使用 format() 函数对字符串进行格式化,使用 {} 为需要填入的数据占位,示例:
name = "ZhangSan"
age = 20
info='''name: {}
age: {}'''print(info.format(name, age))
输出如下:
name: ZhangSan
age: 20
使用 {} 占位时,可以使用数字编号指定输入顺序,编号从 0 开始,示例:
name = "ZhangSan"
age = 20
info='''name: {1}
age: {0}'''print(info.format(age, name))
输出如下:
name: ZhangSan
age: 20
也可以创建新的名称辅助指定输入顺序。示例:
name = "ZhangSan"
age = 20
sex = "male"info='''userinfo:
name: {b}
age: {a}
sex: {c}'''print(info.format(a=age, b=name, c=sex))
输出如下:
userinfo:
name: ZhangSan
age: 20
sex: male
5.3.3 f-string
f-string 提供了一种更为简洁的格式化字符串的方式,它在形式上以 f 或 F 引领字符串,在字符串中使用 {变量名} 标明被替换的真实数据和其所在位置,示例:
name = "ZhangSan"
age = 20print(f'name: {name} age: {age}')
输出如下:
name: ZhangSan age: 20
5.4 查找、替换与处理
5.4.1 查找
Python 中提供了用于字符串查找操作的 find() 方法,该方法可查找字符串中是否包含子串,若包含则返回子串首次出现的索引位置,否则返回 -1,语法如下:
字符串变量名.find(子字符串[,查找起始位置[,查找终止位置]])
示例:
str = "1234567"
print(str.find('4'))
print(str.find('8'))
输出如下:
3
-1
5.4.2 替换
Python 中提供了用于实现字符串替换操作的 replace() 方法,该方法可将当前字符串中的指定子串替换成新的子串,并返回替换后的新字符串,语法如下:
字符串变量名.replace(旧字符串,新字符串[,替换次数])
示例:
str = "01101011"
print(str.replace('0','1'))
输出如下:
11111111
5.4.3 拆分
Python 中的 split() 方法可以按照指定分隔符对字符串进行分割,该方法会返回由分割后的子串组成的列表,语法格式如下:
字符串变量名.split([拆分分隔符][,拆分次数])
# 默认使用 空格 作为拆分分隔符
示例:
str = "192.168.100.10"
print(str.split('.'))
输出如下:
['192', '168', '100', '10']
5.4.4 拼接
Python 中的 join() 方法使用指定字符连接字符串并生成一个新的字符串,语法格式如下:
连接符.join(目标字符串)
示例:
ch = '-'
str = "python"
print(ch.join(str))
输出结果如下:
p-y-t-h-o-n
在 Python 中,还可以使用 + 和 * 号,以一种运算的方式将字符串拼接,示例:
str1 = "ba"
str2 = "na"
print(str1 + (str2 * 2))
输出结果如下:
banana
5.4.5 删除指定字符
字符串中可能会包含一些无用的字符(如空格),在处理字符串之前往往需要先删除这些无用的字符
Python中的 strip()、lstrip() 和 rstrip() 方法可以删除字符串中的指定字符
| 方法名 | 用途 |
|---|---|
| strip() | 移除字符串头尾指定的字符 |
| lstrip() | 移除字符串头部指定的字符 |
| rstrip() | 移除字符串尾部指定的字符 |
它们的语法格式均为 字符串变量名.函数名(字符/字符串)
示例:
str1 = "abc11111abc"print("source: \t" + str1)
print("strip(): \t" + str1.strip("abc"))
print("lstrip(): \t" + str1.lstrip("abc"))
print("rstrip(): \t" + str1.rstrip("abc"))
输出结果如下:
source: abc11111abc
strip(): 11111 # 少了头和尾的 abc
lstrip(): 11111abc # 少了头的 abc
rstrip(): abc11111 # 少了尾的 abc
5.4.6 字符大小写转换
Python 中支持字母大小写转换的方法有 upper()、lower()、capitalize() 和 title()
| 函数名 | 用途 |
|---|---|
| upper() | 将所有小写字母转换为大写字母 |
| lower() | 将所有大写字母转换为小写字母 |
| capitalize() | 将字符串中的第一个字母转换为大写,其余字符转换为小写 |
| title() | 将字符串中的每个单词的首字母转换为大写,其余字符转换为小写 |
示例:
str1 = "python is the BEST language!"print("source: \t\t" + str1)
print("upper(): \t\t" + str1.upper())
print("lower(): \t\t" + str1.lower())
print("capitalize(): \t" + str1.capitalize())
print("title(): \t\t" + str1.title())
输出结果如下:
source: python is the BEST language!
upper(): PYTHON IS THE BEST LANGUAGE! # 全部大写
lower(): python is the best language! # 全部小写
capitalize(): Python is the best language! # 首字母大写,其余小写
title(): Python Is The Best Language! # 每个单词的首字母大写,其余小写
5.4.7 字符串对齐
Python提供了 center()、ljust()、rjust() 这 3 个方法来设置字符串的对齐方式
| 函数名 | 语法格式 | 用途 |
|---|---|---|
| center() | center(width[,fillchar]) | 返回长度为 width 的字符串,源字符串居中 |
| ljust() | ljust(width[,fillchar]) | 返回长度为 width 的字符串,源字符串居左 |
| rjust() | rjust(width[,fillchar]) | 返回长度为 width 的字符串,源字符串居右 |
fillchar 是填充空位的字符,默认为
示例:
str1 = "12345678"print("12length: \t|----------|")
print("center(): \t" + str1.center(12))
print("ljust(): \t" + str1.ljust(12, '-'))
print("rjust(): \t" + str1.rjust(12, '%'))
print("12length: \t|----------|")
输出结果如下:
12length: |----------|
center(): 12345678 # 居中,补空格
ljust(): 12345678---- # 居左,补 -
rjust(): %%%%12345678 # 居右,补 %
12length: |----------|
6. 组合数据类型
6.1 序列
Python 中常用的序列类型有字符串(str)、列表(list)和元组(tuple)
Python 中的序列支持双向索引:正向递增索引和反向递减索引
- 正向递增索引从左向右依次递增,第一个元素的索引为
0,第二个元素的索引为1,以此类推 - 反向递减索引从右向左依次递减,从右数第一个元素的索引为
-1,第二个元素的索引为-2,以此类推。
列表元素可以是整型、浮点型、字符串等基本类型,也可以是列表、元组、字典等组合类型,还可以是其他自定义类型
列表元素的类型可以相同也可以不同
6.2 序列 - 列表
6.2.1 列表的基本使用
创建序列的语法如下:
列表变量名=[列表元素1,列表元素2,...,列表元素n]
列表元素使用索引编号进行访问,语法如下:
列表变量名[索引号]
列表变量名[[起始索引]:[终止索引]:[步进]]
# 起始索引:从指定位置开始,包含当前位置,默认为列表开始
# 终止索引:到指定位置结束,不包含当前位置,默认为列表末尾
# 步进:当前到下一个位置的间隔,默认为 1
使用示例:
mylist=[1,2,3,4,5,6]
print(mylist) # 输出整个列表
print(mylist[3]) # 输出第 4 个列表元素
print(mylist[-2]) # 输出倒数第 2 个列表元素
print(mylist[:3]) # 输出第 1~3 个元素
print(mylist[1::2]) # 从第 2 个元素开始输出到末尾,间隔 1 个元素
输出如下:
[1, 2, 3, 4, 5, 6]
4
5
[1, 2, 3]
[2, 4, 6]
6.2.2 添加列表元素
Python 提供了 append()、extend() 和 insert() 这几个方法向列表末尾、指定位置添加元素
1. append()
append() 方法用于向列表末尾添加新的元素
示例:
mylist = [1, 2, 3, 4, 5]
mylist.append(6)
print(mylist)
输出如下:
[1, 2, 3, 4, 5, 6]
2. extend()
extend() 在列表末尾一次性添加另一个列表中的所有元素,即使用新列表扩展原来的列表
示例:
mylist_1 = [1, 2, 3, 4, 5]
mylist_2 = [6, 7, 8, 9]
mylist_1.extend(mylist_2)
print(mylist_1)
输出如下:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
3. insert()
insert() 方法用于将新元素插入列表的指定位置,语法如下:
列表变量名.insert(索引下标, 值s)
示例:
mylist = [1, 2, 3, 5, 6]
mylist.insert(3, 4) # 在第 4 个位置插入数值 4
print(mylist)
输出如下:
[1, 2, 3, 4, 5, 6]
6.2.3 列表元素排序
列表的排序是将元素按照某种规定进行排列,常用的排序方法有 sort()、reverse()、sorted()
1. sort()
sort() 函数按照特定顺序对元素列表进行排序,语法如下:
sort(key=排序依据,reverse=升降序)
# key 常用的参数
# len: 长度
#
# reverse 常用的参数
# True: 按照降序排序
# False: 按照升序排序(默认)
6.2.4 删除列表元素
删除列表元素的常用方式有 del 语句、remove()、pop() 和 clear() 方法
| 函数/语句名 | 语法 | 用途 |
|---|---|---|
| del | del 列表变量名[目标下标] | 删除指定位置的元素 |
| remove() | 列表变量名.remove(字符/字符串) | 移除首个匹配到的元素 |
| pop() | 列表变量名.pop([下标]) | 移除指定下标的元素,默认为最后一个元素 |
| clear() | 列表变量名.clear() | 清空列表 |
示例:
list1 = ["Jarry", "Jarry", "Tom", "Spike"]
print("source list: ", list1)
del list1[2]
print("del list1[2]: ", list1)list1 = ["Jarry", "Jarry", "Tom", "Spike"] # 重新赋值
list1.remove('Jarry')
print("list1.remove('Jarry'): ", list1)list1 = ["Jarry", "Jarry", "Tom", "Spike"] # 重新赋值
list1.pop(2)
print("list1.pop(2): ", list1)list1 = ["Jarry", "Jarry", "Tom", "Spike"] # 重新赋值
list1.clear()
print("list1.clear(): ", list1)
输出结果如下:
source list: ['Jarry', 'Jarry', 'Tom', 'Spike']
del list1[2]: ['Jarry', 'Jarry', 'Spike']
list1.remove('Jarry'): ['Jarry', 'Tom', 'Spike']
list1.pop(2): ['Jarry', 'Jarry', 'Spike']
list1.clear(): []
6.2.5 列表推导式
列表推导式是符合 Python 语法规则的复合表达式,它用于以简洁的方式根据已有的列表构建满足特定需求的列表
语法如下:
[表达式 for 变量名 in 列表变量名]
示例:将一个列表中的数值转换为自身的平方
list1 = [1,2,3,4,5,6,7,8]
list2 = [num * num for num in list1]
print("list1: ", list1)
print("list2: ", list2)
输出结果如下:
list1: [1, 2, 3, 4, 5, 6, 7, 8]
list2: [1, 4, 9, 16, 25, 36, 49, 64]
列表推导式中可以嵌套判断和循环语句,如 if 和 for
示例 1:生成一个包含 1 到 10 之间所有偶数的平方的列表
list1 = [1,2,3,4,5,6,7,8,9,10]
list2 = [num * num for num in list1 if num%2==0]
print("list1: ", list1)
print("list2: ", list2)
输出结果如下:
list1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2: [4, 16, 36, 64, 100]
示例 2:生成一个包含 1 到 3 和 4 到 6 之间所有数字之和的列表(即计算所有 x + y,其中 x 来自 1~3,y 来自 4~6)
list1 = [1,2,3]
list2 = [4,5,6]
list3 = [x+y for x in list1 for y in list2]
print("list1: ", list1)
print("list2: ", list2)
print("list3: ", list3)
输出结果如下:
list1: [1, 2, 3]
list2: [4, 5, 6]
list3: [5, 6, 7, 6, 7, 8, 7, 8, 9]
示例 3:有 list1 和 list2 两个列表,计算当 list1 的值小于 list2 时,两值的乘积
list1 = [1,2,3,4,5]
list2 = [1,2,3,4,5]
list3 = [x*y for x in list1 for y in list2 if x<y]
print("list1: ", list1)
print("list2: ", list2)
print("list3: ", list3)
输出结果如下:
list1: [1, 2, 3, 4, 5]
list2: [1, 2, 3, 4, 5]
list3: [2, 3, 4, 5, 6, 8, 10, 12, 15, 20]
6.3 序列 - 元组
元组的表现形式为一组包含在圆括号 () 中、由逗号分隔的元素,元组中元素的个数、类型不受限制。使用圆括号可以直接创建元组,还可以使用内置函数 tuple() 构建元组
当使用圆括号 () 创建元组时,如果元组中只包含一个元素,那么需要在该元素的后面添加逗号,从而保证 Python 解释器能够识别其为元组类型
示例:
t1 = () # 空元组
t2 = (1,) # 包含单个元素的元组
t3 = (1,2,3) # 包含多个元素的元组
t4 = (1,'h',('o',2)) # 元组嵌套
使用内置函数 tuple() 也可以创建元组,当函数的参数列表为空时该函数常见空元组,当参数为可迭代对象时该函数创建非空元组
示例:
t1 = tuple() # 创建空元组
t2 = tuple([1,2,3]) # 利用列表创建元组(1,2,3)
t3 = tuple('python') # 利用字符串创建元组('p','y','t','h','o','n')
t4 = tuple(range(5)) # 利用可迭代对象创建元组(0,1,2,3,4)
与列表相同,Python支持通过索引和切片访问元组的元素,也支持在循环中遍历元组
print(t2[1]) # 以索引方式访问元组元素
print(t3[2:5]) # 以切片方式访问元组元素
for data in t3: # 在循环中遍历元组print(data,end='')
[!IMPORTANT]
元组是不可变类型,元组中的元素不能修改,即它不支持添加元素,删除元素和排序操作
6.4 集合
Python 集合具备确定性、互异性和无序性三个特性
Python 要求放入集合中的元素必须是不可变类型,Python 中的整型、浮点型、字符串类型和元组属于不可变类型,列表、字典及集合本身都属于可变的数据类型
- 确定性:给定一个集合,那么任何一个元素是否在集合中就确定了
- 互异性:集合中的元素互不相同
- 无序性:集合中的元素没有顺序,顺序不同但元素相同的集合可视为同一集合
6.5 映射
映射类型以键值对的形式存储元素,键值对中的键与值之间存在映射关系
字典(dict)是 Python 唯一的内置映射类型,字典的键必须遵守以下两个原则:
- 每个键只能对应一个值,不允许同一个键在字典中重复出现
- 字典中的键是不可变类型
7. 函数
7.1 函数的定义与调用
函数的定义语法如下:
def 函数名([参数列表]):函数体[return 语句]
函数分为有参函数和无参函数,有参函数的形参列表中需要包含参数,无参函数的形参列表为空
如果需要将函数运算的结果返回给调用函数,则需要加上 return 语句和要返回的值
示例:
# 无参函数
def hello():print("Hello,world")# 有参函数
def add(a,b):result = a + breturn result # 返回 result
函数在定义完成后不会立刻执行,直到被程序调用时才会执行,调用函数只需要写下函数名即可,如果是有参函数还需要加上传递的参数
示例:
# 无参函数
def hello():print("Hello,world")# 有参函数
def add(a,b):result = a + breturn result # 返回 resulta=1
b=2hello()
print(add(a,b))
运行结果如下:
Hello,world
3
函数内可以嵌套定义函数
7.2 函数参数传递
我们通常将定义函数时设置的参数称为形式参数,简称形参;将调用函数时传入的参数称为实际参数,简称实参
函数的参数传递是指将实际参数传递给形式参数的过程
函数参数的传递可以分为位置参数传递、关键字参数传递、默认参数传递、参数的打包与解包以及混合传递五种方法
7.2.1 位置参数传递
函数在被调用时会将实参按照相应的位置依次传递给形参,也就是说将第一个实参传递给第一个形参,将第二个实参传递给第二个形参,以此类推
示例:
def add(a,b):result = a + breturn resultprint(add(1,2))
7.2.2 关键字参数传递
关键字参数的传递是通过 “形参=实参” 的格式将实参与形参相关联,将实参按照相应的关键字传递给形参
示例:
def connect(ip,port):print(f'设备 {ip}:{port} 连接!')connect(ip='127.0.0.1', port=8080)
从 Python 3.8 开始新增了仅限位置形参的语法,使用符号 / 和 * 来限定部分形参只接收采用位置传递方式的实参
/前的形参必须使用位置参数传递*后的形参必须使用关键字参数传递
示例:
def func(a,/,b,*,c):print(a,b,c)
# a 仅限使用参数传递
# c 仅限使用关键字传递func(10,20,c=30) # Success
func(10,b=20,c=30) # Success
# func(a=10,b=20,c=30) # Failed
# func(10,20,30) # Failed
7.2.3 默认参数传递
函数在定义时可以指定形参的默认值,如此在被调用时可以选择是否给带有默认值的形参传值,若没有给带有默认值的形参传值,则直接使用该形参的默认值
示例:
def connect(ip,port=8080):print(f'设备 {ip}:{port} 连接!')
connect(ip="127.0.0.1") # 未传递参数,使用默认参数
connect(ip="127.0.0.1",port=3306) # 传递参数,使用传递参数
输出结果如下:
设备 127.0.0.1:8080 连接!
设备 127.0.0.1:3306 连接!
7.2.4 参数的打包与解包
打包如果函数在定义时无法确定需要接收多少个数据,那么可以在定义函数时为形参添加 “*” 或 “**”:
1. 打包
*: 以元组的形式打包多个值**: 以字典的形式打包多个值
示例:
def func1(*args):print(args)print(type(args))def func2(**args):print(args)print(type(args))func1(1,2,3,4,5)
func2(a=1,b=2,c=3,d=4)
输出结果如下:
(1, 2, 3, 4, 5)
<class 'tuple'>
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
<class 'dict'>
2. 解包
解包与打包的符号用法一致,只是方向不同
示例:
def func1(a,b,c,d,e):print(a,b,c,d,e)def func2(a,b,c,d,e):print(a,b,c,d,e)nums1 = [1,2,3,4,5]
nums2 = {'a':1,'b':2,'c':3,'d':4,'e':5}func1(*nums1)
func2(**nums2)
输出结果如下:
1 2 3 4 5
1 2 3 4 5
7.2.5 返回值
函数中的 return 语句会在函数结束时将数据返回给程序,同时让程序回到函数被调用的位置继续执行
示例:
num1 = int(input("Enter a number: "))
num2 = int(input("Enter another number: "))def add(num1, num2):return num1 + num2 # 将运算结果返回给上一层调用print(add(num1, num2)) # 返回值将直接被输出
输出结果如下:
Enter a number: # 3
Enter another number: # 5
8
如果遇到需要返回多个值,则需要在这些值之间加上 , 进行区分,且返回值类型会变为元组类型
示例:
def func():return 1, 2print(func(), type(func()))
输出结果如下:
(1, 2) <class 'tuple'>
7.3 变量作用域(scope)
变量并非在程序的任意位置都可以被访问,其访问权限取决于变量定义的位置,其所处的有效范围称为变量的作用域
7.3.1 局部变量与全局变量
根据作用域的不同,变量可以划分为局部变量和全局变量
- 局部变量(Local Variable):一般指函数内部定义的变量,只能在函数内部被使用
- 全局变量(Global Variable):可以在整个程序的范围内起作用,可以在程序的任意位置被访问,它不会受到函数范围的影响
示例:
num = 10 # 全局变量def func1():num = 5 # 局部变量(只在 func1 内部有效)print("func1 内部的 num:", num)def func2():print("func2 访问到的 num:", num) # 未定义局部变量时,会访问全局变量print("全局 num:", num)
func1() # 调用 func1,打印局部变量
func2() # 调用 func2,打印全局变量
print("函数调用后,全局 num 仍然是:", num)
输出结果如下:
全局 num: 10
func1 内部的 num: 5
func2 访问到的 num: 10
函数调用后,全局 num 仍然是: 10
7.3.2 global 关键字
如果想在函数内部修改全局变量的值,需要使用关键字 global,示例:
num = 10def change_global():global numnum = 20 # 修改全局变量print("在函数中修改 num:", num)change_global()
print("修改后的全局 num:", num)
输出结果如下:
在函数中修改 num: 20
修改后的全局 num: 20
7.3.3 nonlocal 关键字
使用 nonlocal 关键字可以在局部作用域中修改嵌套作用域中定义的变量,示例:
def outer():num = 10def inner():nonlocal num # 声明使用外层函数的变量(非全局)print("inner 内访问 num:", num)num = 20print("inner 内修改 num:", num)inner()print("outer 内的 num:", num)outer()
输出结果如下:
inner 内访问 num: 10
inner 内修改 num: 20
outer 内的 num: 20
7.4 匿名函数 lambda
匿名函数是一类无需定义标识符的函数,它与普通函数一样可以在程序的任何位置使用。Python 中使用 lambda 关键字定义匿名函数
匿名函数与普通函数的主要区别如下:
- 普通函数使用
def定义,有函数名;匿名函数使用lambda定义,无函数名 - 普通函数的函数体可以包含多条语句;匿名函数的函数体只能是一个表达式,且自动作为返回值
- 匿名函数通常用于一次性使用或简短逻辑的场景,比如作为函数参数
语法如下:
[变量名 = ]lambda [形参列表]: 表达式
# 一般建议将匿名函数赋值给变量,方便重复使用
示例:
temp = lambda x: pow(x,2)
print("2 ^ 2 =", temp(2))
输出结果如下:
2 ^ 2 = 4
8. 文件处理
8.1 文件
文件在计算机中应用广泛,计算机中的文件是以硬盘等外部介质为载体,存储在计算机中的数据的集合,文本文档、图片、程序、音频等都是文件
类似于程序中使用的变量,计算机中的每个文件也有唯一确定的标识,以便识别和引用文件
文件标识用于找到计算机中唯一确定的文件,其由文件路径、文件名主干、文件扩展名组成
文件类型根据数据的逻辑存储结构,人们将计算机中的文件分为文本文件和二进制文件
- 文本文件:专门存储文本字符数据(使用记事本)
- 二进制文件:不能直接使用文字处理程序正常读写,必须先了解其结构和序列化规则,再设计正确的反序列化规则,才能正确获取文件信息
总结:二进制文件和文本文件这两种类型的划分基于数据逻辑存储结构而非物理存储结构,计算机中的数据在物理层面都以二进制形式存储
8.2 Python 标准文件
Python 的 sys 模块中定义了 3 个标准文件,分别为:
- stdin:标准输入文件,标准输入文件对应输入设备,如键盘
- stdout:标准输出文件
- stderr:标准错误文件,标准输出文件和标准错误文件对应输出设备,如显示器
在解释器中导入 sys 模块后,便可对标准文件进行操作
示例:
import sys
file = sys.stdout
file.write('lucky cloud')
8.3 文件基本操作
将数据写入到文件之前需要先打开文件;数据写入完毕后需要将文件关闭以释放计算机内存
8.3.1 打开文件
内置函数 open() 用于打开文件,该方法的声明如下
open(FILE[, mode='MODE', buffering=BUFFERING])
# FILE: 文件路径
# MODE: 文件打开模式,可组合,可填写参数如下:
# - r: 以只读方式打开,默认
# - w: 以只写方式打开
# - a: 以追加方式打开
# - b: 以二进制形式打开
# - +: 以更新方式打开(可读可写)
# BUFFERING: 设置访问文件的缓冲方式。取值为 0 或 1
示例:在 E:\ 创建一个文件 1.txt,打开这个文件
file = open("E:\\1.txt")
print(file)
输出结果如下:
# 如果文件存在,则会返回正常结果
<_io.TextIOWrapper name='E:\\1.txt' mode='r' encoding='cp936'># 如果文件不存在,则会抛出异常
FileNotFoundError: [Errno 2] No such file or directory: 'E:\\1.txt'
8.3.2 关闭文件
Python 可通过 close() 方法关闭文件,也可以使用 with 语句实现文件的自动关闭
close() 方法,是文件对象的内置方法,使用语法如下:
文件变量名.close()
with 语句,可预定义清理操作,以实现文件的自动关闭,示例:
with open('E:\\1.txt') as f:print('文件关闭')pass
8.3.3 文件读写
Python 提供了一系列读写文件的方法,包括读取文件的 read()、readline()、readlines() 方法和写文件的 write()、writelines() 方
1. read()
read() 方法可以从指定文件中读取指定字节的数据,语法格式如下:
read([SIZE])
# SIZE: 指定读取的数据长度,单位:Byte,默认读取全部数据
示例:
# 打开文件
file = open("E:\\1.txt")
# 读取文件
str = file.read()
# 输出文件内容
print(str)
# 关闭文件
file.close()##### 也可以 #####
with open("E:\\1.txt") as f:print(f.read(2)) # 指定获取长度print(f.read()) # 获取所有数据
2. readline()
readline() 方法可以从指定文件中读取一行数据,其语法格式如下:
文件变量名.readline()
示例:修改 1.txt 文件内容为:
Nice to meet you!
Nice to meet you, too!
Nice to meet you, three!
Nice to meet you, four!
file = open("E:\\1.txt")
str = file.readline()
print(str)
file.close()
输出如下:
Nice to meet you!
3. readlines()
readlines() 方法可以一次读取文件中的所有数据,若读取成功,该方法会返回一个列表,文件中的每一行对应列表中的一个元素
函数语法格式如下:
文件变量名.readlines()
4. write()
write() 方法可以将指定字符串写入文件,其语法格式如下
write(DATA)
若数据写入成功,write() 方法会返回本次写入文件的数据的字节数
示例:在文件中添加 "Nice to meet you, too!,
text='\nNice to meet you, too!'with open("E:\\1.txt","r+") as f:# 读取文件f.seek(0)str1 = f.read()print("===== Original content =====")print(str1)# 写入字符串f.write(text)# 再次读取文件f.seek(0) # 将文件指针移动到文件头str2 = f.read()print("\n===== Content after writing =====")print(str2)
输出结果如下:
===== Original content =====
Nice to meet you!===== Content after writing =====
Nice to meet you!
Nice to meet you, too!
5. writelines()
writelines() 方法用于将行列表写入文件,其语法格式如下
writelines(LINES)
- 以上格式中的参数
lines表示要写入文件中的数据,该参数可以是一个字符串或者字符串列表 - 若写入文件的数据在文件中需要换行,需要显式指定换行符
示例:
textlines=['\nNice to meet you, three!', '\nNice to meet you, four!']with open("E:\\1.txt","r+") as f:# 读取文件f.seek(0) # 将文件指针移动到文件头str1 = f.read()print("===== Original content =====")print(str1)# 写入字符串f.writelines(textlines)# 再次读取文件f.seek(0) # 将文件指针移动到文件头str2 = f.read()print("\n===== Content after writing =====")print(str2)
输出效果如下:
===== Original content =====
Nice to meet you!
Nice to meet you, too!===== Content after writing =====
Nice to meet you!
Nice to meet you, too!
Nice to meet you, three!
Nice to meet you, four!
8.3.4 数据定位读写
有以下代码:
# 文件内容: ABCDEFGHIJKLMN
with open("E:\\1.txt","r+") as f:str1 = f.read(2)print(str1)str2 = f.read(3)print(str2)
输出内容如下:
AB
CDE
read() 方法读取了文件 luckycloud.txt,结合代码与程序运行结果进行分析,可以发现 read() 方法第 1 次读取了 2 个字符,第 2 次从第 3 个字符开始读取了 5 个字符
在文件的一次打开与关闭之间进行的读写操作是连续的,程序总是从上次读写的位置继续向下进行读写操作
每个文件对象都有一个称为“文件读写位置”的属性,该属性会记录当前读写的位置,文件读写位置默认为 0,即在文件头
Python提供了一些获取与修改文件读写位置的方法,以实现文件的定位读写:
tell():获取文件当前的读写位置seek():控制文件的读写位置
1. tell()
tell() 方法用于获取文件当前的读写位置,示例:
with open("E:\\1.txt","r+") as f:str1 = f.read(2)print(str1)print(f.tell())str2 = f.read(3)print(str2)
输出结果如下:
AB
2
CDE
2. seek()
seek() 方法用于可控制文件的读写位置,实现文件的随机读写,语法格式如下
seek(offset, from)
# offset: 表示偏移量,即读写位置需要移动的字节数
# from: 用于指定文件的读写位置,可设置参数为:
# 0: 文件头
# 1: 当前位置
# 2: 文件尾
示例:
# 文件内容:ABCDEFG
with open("E:\\1.txt","r+") as f:str1 = f.read(3)print(str1)f.seek(0) # 将文件指针指向文件头str2 = f.read(3)print(str2)f.seek(0,1) # 使用当前位置继续读写str3 = f.read(3)print(str3)f.seek(1,0) # 将文件指针指向文件头,向右偏 1 个字符str4 = f.read(3)print(str4)
输出结果如下:
ABC
ABC
DEF
BCD
8.3.5 文件与目录管理
对于用户而言,文件和目录以不同的形式展现,但对计算机而言,目录是文件属性信息集合,它本质上也是一种文件
os 模块中定义了与文件操作相关的函数,利用这些函数可以实现删除文件、文件重命名、创建/删除目录、获取当前目录、更改默认目录与获取目录列表等操作
1. remove()
使用 os 模块的 remove() 函数可删除文件,该函数要求目标文件存在,语法如下:
remove(FILE)
示例:
import os
os.remove("E:\\1.txt.bak")
2. rename()
使用 os 模块中的 rename() 函数可以更改文件名,该函数要求目标文件已存在,语法如下:
rename(FILE, NEW_FILE)
[!NOTE]
- 当目标文件存在时,无法重命名
- 源文件名与目标文件名均为文件路径形式
示例:
import os
os.rename("E:\\1.txt.bak", "E:\\1.file")
3. getcwd()
os 模块中的 getcwd() 函数用于获取当前目录,即 Python 当前的工作路径,调用该函数可获取当前工作目录的绝对路径,示例:
import os
print(os.getcwd())
4. mkdir() / rmdir()
os 模块中的 mkdir() 函数用于创建目录,rmdir() 函数用于删除目录,这两个函数的参数都是目录名称
mkdir() 函数用于在当前目录下创建目录,需要注意,待创建的目录不能与已有目录重名,否则将创建失败
示例:在 E:\ 下创建一个目录 py1
import os
os.mkdir("E:\\py1")
rmdir() 用于删除目录,示例:将刚刚创建的目录删除
import os
os.rmdir("E:\\py1")
5. chdir()
os 模块中的 chdir() 函数用于更改默认目录。若在对文件或文件夹进行操作时传入的是文件名而非路径名,Python 解释器会从默认目录中查找指定文件,或将新建的文件放在默认目录下。若没有特别设置,当前目录即为默认目录
使用 chdir() 函数更改默认目录为F盘,再次使用 getcwd() 函数获取当前目录,示例:
import os
print('更改前默认路径:',os.getcwd())
os.chdir('F:\\')
print('更改后默认路径:',os.getcwd())
6. listdir()
实际使用中常常需要先获取指定目录下的所有文件,再对目标文件进行相应操作。os 模块中提供了 listdir() 函数,使用该函数可方便快捷地获取指定目录下所有文件的文件名列表
示例:
import os
print(os.listdir("E:\\py1"))
8.3.6 数据维度与数据格式化
1. 数据维度
根据组织数据时与数据有联系的参数的数量,数据可分为一维数据、二维数据和多维数据
- 一维数据:具有对等关系的一组线性数据,如一维列表、一维元组、集合
- 二维数据:二维数据关联参数的数量为 2,如矩阵、二维数组、二维列表、二维元组
- 多维数据:利用键值对等简单的二元关系展示数据间的复杂结构,如字典
2. 一二维数据的存储与读写
程序中与数据相关的操作分为数据的存储与读写,下面我们就一起掌握如何存储与读写不同维度的数据
数据通常存储在文件中,为了方便后续的读写操作,数据通常需要按照约定的组织方式进行存储。
一维数据呈线性排列,一般用特殊字符分隔,例如:
- 使用
' '分隔:成都 杭州 重庆 武汉 苏州 西安 天津 - 使用
,分隔:成都,杭州,重庆,武汉,苏州,西安,天津 - 使用
&分隔:成都&杭州&重庆&武汉&苏州&西安&天津
一维数据的存储需要注意以下几点:
- 同一文件或同组文件一般使用同一分隔符分隔
- 分隔数据的分隔符不应出现在数据中
- 分隔符为英文半角符号,一般不使用中文符号作为分隔符
二维数据可视为多条一维数据的集合,当二维数据只有一个元素时,这个二维数据就是一维数据
CSV(Commae-Separeted Values,逗号分隔值)是国际上通用的一二维数据存储格式
CSV 格式规范:
- 以纯文本形式存储表格数据
- 文件的每一行对应表格中的一条数据记录
- 每条记录由一个或多个字段组成
- 字段之间使用逗号(英文、半角)分隔
- CSV 也称字符分隔值,具体示例如下:
姓名,语文,数学,英语,理综
刘备,124,137,145,260
张飞,116,143,139,263
关羽,120,130,148,255
周瑜,115,145,131,240
诸葛亮,123,108,121,235
黄月英,132,100,112,210
CSV 广泛应用于不同体系结构下网络应用程序之间表格信息的交换中,它本身并无明确格式标准,具体标准一般由传输双方协议决定
Windows 平台中 CSV 文件的后缀名为 .csv,可通过 Office Excel 或记事本打开。
[!TIP]
尝试创建一个文件
1.csv,并将样例文本复制粘贴进去,再用 Excel 打开这个文件,会发现自动生成了一个 Excel 表格但请注意,文件的编码格式应当为
ANSI,否则会出现乱码
Python 在程序中读取 .csv 文件后会以二维列表形式存储其中内容
示例:
import chardetwith open('E:\\1.csv','rb') as f:raw_data = f.read()encoding = chardet.detect(raw_data)['encoding']with open('E:\\1.csv',encoding=encoding,errors='ignore') as f:lines = []for line in f:line = line.replace('\n','')lines.append(line.split(','))print(lines)
输出结果如下:
[['姓名', '语文', '数学', '英语', '理综'], ['刘备', '124', '137', '145', '260'], ['张飞', '116', '143', '139', '263'], ['关羽', '120', '130', '148', '255'], ['周瑜', '115', '145', '131', '240'], ['诸葛亮', '123', '108', '121', '235'], ['黄月英', '132', '100', '112', '210']]
示例:
import chardet#默认字符集处理
def open_file(address):with open(address,'rb') as f:raw_data = f.read()return chardet.detect(raw_data)['encoding']addr = 'E:\\1.csv'
with open(addr,encoding=open_file(addr),errors='ignore') as f:file_new = open('E:\\1.csv','w+')lines = []for line in f:line = line.replace('\n','')lines.append(line.split(','))#添加表头字段lines[0].append('total')#添加总计for i in range(len(lines)-1):idx = i+1sun_score = 0for j in range(len(lines[idx])):if lines[idx][j].isnumeric():sun_score += int(lines[idx][j])lines[idx].append(str(sun_score))for line in lines:print(line)file_new.write(','.join(line)+'\n')
3. 多维数据格式化
为了直观地表示多维数据,也为了便于组织和操作,三维及以上的多维数据统一采用键值对的形式进行格式化
网络平台上传递的数据大多是高维数据,JSON是网络中常见的高维数据格式。JSON格式的数据遵循以下语法规则
- 数据存储在键值对(key:value)中,例如
"姓名": "张飞"。 - 数据的字段由
,分隔,例如"姓名": "张飞", "语文": "116" - 一个
{}保存一个 JSON 对象,例如{"姓名": "张飞", "语文": "116"} - 一个
[]保存一个数组,例如[{"姓名": "张飞", "语文": "116"}]
利用 JSON 模块的 dumps() 函数和 loads() 函数可以实现 Python 对象和 JSON 数据之间的转换,这两个函数的具体功能如表所示
| 函数 | 功能 |
|---|---|
dumps() | 对 Python 对象进行转码,将其转化为 JSON 字符串 |
loads() | 将 JSO N字符串解析为 Python 对象 |
Python 对象与 JSON 数据转化时的类型对照表
| Python对象 | JSON数据 |
|---|---|
| dict | object |
| list,tuple | array |
| str,unicode | string |
| int,long,float | number |
| True | true |
| False | false |
| None | null |
使用 dumps() 函数对 Python 对象进行转码
示例:
import json
pyobj = [[1,2,3],10,3,14,'tom',{'java':98,'python':100},True,False,None]
jsonobj = json.dumps(pyobj)
print(jsonobj)
输出结果如下:
[[1, 2, 3], 10, 3, 14, "tom", {"java": 98, "python": 100}, true, false, null]
使用 loads() 函数将 JSON 数据转换为符合 Python 语法要求的数据类型
import jsonpyobj = [[1,2,3],10,3,14,'tom',{'java':98,'python':100},True,False,None]
jsonobj = json.dumps(pyobj)
print(jsonobj)# 反序列化操作
new_obj = json.loads(jsonobj)
print(new_obj)
输出结果如下:
[[1, 2, 3], 10, 3, 14, "tom", {"java": 98, "python": 100}, true, false, null]
[[1, 2, 3], 10, 3, 14, 'tom', {'java': 98, 'python': 100}, True, False, None]
9. 面向对象
9.1 类和对象
面向对象编程有两个非常重要的概念:类和对象
- 对象映射现实中真实存在的事物,如一本书
- 具有相同特征和行为的事物的集合统称为类
对象是根据类创建的,一个类可以对应多个对象,类是对象的抽象,对象是类的实例
9.1.1 类
类是由 3 部分组成:
- 类的名称:大驼峰命名法,首字母一般大写,比如 Person
- 类的属性:用于描述事物的特征,比如姓名,性别,身高,体重等(静态描述)
- 类的方法:用于描述事物的行为,比如吃饭,睡觉,健身,娱乐等(动态描述)
类定义语法如下:
class 类名:属性名 = 值def 方法名(self): 方法体
示例:
class car: # 类名: carwheel = 4 # 类属性 wheel 值为 4def drive(self): # 类方法 drive()print("Driving")
9.1.2 对象
根据类创建对象的语法格式如下:
对象名 = 类名()
示例:
class Car:wheel = 4def drive(self):print("Driving")c1 = Car() # 创建对象
print(c1.wheel) # 输出对象属性
c1.drive() # 输出对象方法
输出结果如下:
4
Driving
9.2 类的成员
9.2.1 属性
属性按声明的方式可以分为两类:类属性和实例属性
1. 类属性
类属性指声明在类内部、方法外部的属性。可以通过类或对象进行访问,但只能通过类进行修改
示例:
class Car:wheels = 4 # 属性def drive(self): # 方法print("Driving")c1 = Car()
print(Car.wheels)
print(c1.wheels)# 通过类修改类属性
Car.wheels = 3
print(Car.wheels) # 类的属性将受到影响
print(c1.wheels) # 对象的属性将受到影响# 通过对象修改类属性
c1.wheels = 4
print(Car.wheels) # 类的属性将不受到影响
print(c1.wheels) # 对象的属性将受到影响
输出结果如下:
4
4
3
3
3
4
2. 实例属性
实例属性是在方法内部声明的属性,只能通过对象修改和访问,Python 支持动态添加实例属性
示例:
class Car:def drive(self): # 方法self.wheels = 4 # 实例属性# 访问属性
c1 = Car()
c1.drive()
print(c1.wheels)
# print(Car.wheels) # ERROR# 修改属性
c1.wheels = 3
print(c1.wheels)# 动态添加属性
c1.color = "green"
print(c1.color)
输出结果如下:
4
3
green
9.2.2 方法
Python 中的方法按定义方式和用途可以分为三类:实例方法、类方法和静态方法
1. 实例方法
实例方法形似函数,但它定义在类内部,以 self 为第一个形参,self 参数代表对象本身,只能通过对象调用
示例:
class Car:def drive(self):print("Driving")c1 = Car()
c1.drive()
# Car.drive() # ERROR
Car.drive(c1)
输出结果如下:
Driving
Driving
2. 类方法
类方法是定义在类内部,使用装饰器 @classmethod 修饰的方法,第一个参数为cls,代表类本身,可以通过类和对象调用
示例:
class Car:def drive(self): # 方法print("Driving")@classmethoddef stop(cls): # 类方法print("Stopping")c1 = Car()
c1.stop() # 使用对象调用类方法
Car.stop() # 使用类调用类方法
输出结果如下:
Stopping
Stopping
类方法中可以使用 cls 访问和修改类属性的值,示例:
class Car:color = 'red'@classmethoddef func(cls): # 类方法print(cls.color)cls.color = "blue"print(cls.color)c1 = Car()
c1.func()
输出结果如下:
red
blue
3. 静态方法
静态方法是定义在类内部,使用装饰器 @staticmethod 修饰的方法,没有任何默认参数
静态方法可以通过类和对象调用,独立于类所存在
示例:
class Car:@staticmethoddef drive():print("Driving")c1 = Car()
c1.drive()
Car.drive()
输出结果如下:
Driving
Driving
静态方法内部不能直接访问属性或方法,但可以使用类名访问类属性或调用类方法
示例:
class Car:wheels = 4 # 类属性@staticmethoddef get_wheels():print(f"{Car.wheels}")c1 = Car()
c1.get_wheels()
Car.get_wheels()
输出结果如下:
4
4
9.2.3 私有成员
类的成员默认是公有成员,可以在类的外部通过类或对象随意地访问,这样显然不够安全,为了保证类中数据的安全,Python 支持将公有成员改为私有成员,在一定程度上限制在类的外部对类成员的访问。
Python 通过在类成员的名称前面添加 __ 的方式来表示私有成员,语法格式如下:
__属性名/方法名
示例:
class Car:__wheels = 4 # 私有属性def __drive(self): # 私有方法print("Driving")def test(self):# 使用类公有方法访问类私有方法print(f"Wheels: {self.__wheels}")self.__drive()c1 = Car()
c1.test()
输出结果如下:
Wheels: 4
Driving
9.3 特殊方法
类中还包括两个特殊的方法:构造方法和析构方法,这两个方法都是系统内置方法
9.3.1 构造方法
构造方法指的是 init() 方法
创建对象时系统自动调用,从而实现对象的初始化
每个类默认都有一个 init() 方法,可以在类中显式定义 init() 方法,init() 方法可以分为无参构造方法和有参构造方法
当使用无参构造方法创建对象时,所有对象的属性都有相同的初始值,示例:
class Car:def __init__(self): # 无参构造方法self.color = 'red'def show_color(self):print(f"color: {self.color}")c1 = Car()
c1.show_color()
输出结果如下:
color: red
当使用有参构造方法创建对象时,对象的属性可以有不同的初始值,示例:
class Car:def __init__(self, color): # 有参构造方法self.color = colordef show_color(self):print(f"color: {self.color}")c1 = Car("green") # 将 green 传递给 color
c1.show_color()
输出结果如下:
color: green
9.3.2 析构方法
析构方法 del() 是销毁对象时系统自动调用的方法,每个类默认都有一个 del() 方法,可以显式定义析构方法,示例:
class Car:def __init__(self, color): # 有参构造方法self.color = colordef __del__(self): # 析构方法print("Bye!")def show_color(self):print(f"color: {self.color}")c1 = Car("green")
c1.show_color()
9.4 封装
封装是面向对象的重要特性之一,它的基本思想是对外隐藏类的细节,提供用于访问类成员的公开接口
如此,类的外部无需知道类的实现细节,只需要使用公开接口便可访问类的内容,这在一定程度上保证了类内数据的安全
为了契合封装思想,我们在定义类时需要满足以下两点要求
- 将类属性声明为私有属性
- 添加两类供外界调用的公有方法,分别用于设置或获取私有属性的值
class Person:def __init__(self, name):self.name = name # 公有属性self.__age = 1 # 私有属性def set_age(self, new_age):if 0 < new_age <= 120:self.__age = new_agedef get_age(self):return self.__ageperson = Person("Jack")
person.set_age(22)
print(f"name: {person.name}")
print(f"age: {person.get_age()}")
输出结果如下:
name: Jack
age: 22
9.5 继承
继承是面向对象的重要特性之一,它主要用于描述类与类之间的关系,在不改变原有类的基础上扩展原有类的功能
若类与类之间具有继承关系,被继承的类称为父类或基类,继承其他类的类称为子类或派生类,子类会自动拥有父类的公有成员
9.5.1 单继承
单继承即子类只继承一个父类。现实生活中,波斯猫、折耳猫、短毛猫都属于猫类,它们之间存在的继承关系即为单继承,语法如下:
class 子类名(父类名):
子类继承父类的同时会自动拥有父类的公有成员,自定义类默认继承基类 object
示例:
class Square:def __init__(self):self.a = 3def set_a(self, a):self.a = adef get_area(self):return self.a * self.aclass Rectangle(Square):passr1 = Rectangle()
print(r1.get_area())
输出结果如下:
9
9.5.2 多继承
程序中的一个类也可以继承多个类,如此子类具有多个父类,也自动拥有所有父类的公有成员
Python 中多继承的语法格式如下:
class 子类名(父类名1, 父类名2, ...):
示例:
class Car:def drive(self):print("Driving")class Plane:def fly(self):print("Flying")class Deluxo(Car, Plane):passd1 = Deluxo()
d1.drive()
d1.fly()
输出内容如下:
Driving
Flying
[!NOTE]
如果多继承时出现多个同名方法时,则按照继承顺序优先集成
9.5.3 重写
子类会原封不动地继承父类的方法,但子类有时需要按照自己的需求对继承来的方法进行调整,也就是在子类中重写从父类继承来的方法
在子类中定义与父类方法同名的方法,在方法中按照子类需求重新编写功能代码即可
示例:
class square:def get_shape(self):print("square")class triangle(square):def get_shape(self):print("triangle")s1 = square()
s2 = triangle()
s1.get_shape()
s2.get_shape()
输出内容如下:
square
triangle
子类重写了父类的方法之后,无法直接访问父类的同名方法,但可以使用 super() 函数间接调用父类中被重写的方法,示例:
class square:def get_shape(self):print("square") # squareclass triangle(square):def get_shape(self):super().get_shape() # squareprint("triangle") # triangles1 = square()
s2 = triangle()
s1.get_shape()
s2.get_shape()
9.6 多态
多态是面向对象的重要特性之一,它的直接表现即让不同类的同一功能可以通过同一个接口调用,表现出不同的行为
示例:
class Computer:def usb1(self, obj):obj.set()def usb2(self, obj):obj.set()class Mouse:def set(self):print('Mouse is set')class Keyboard:def set(self):print('Mouse is set')mouse = Mouse()
keyboard = Keyboard()computer = Computer()
computer.usb1(mouse)
computer.usb1(keyboard)
输出内容如下:
Mouse is set
Keyboard is set
10. 异常
10.1 什么是异常
程序开发或运行时可能出现异常,开发人员和运维人员需要辨别程序的异常,明确这些异常是源于程序本身的设计问题,还是由外界环境的变化引起,以便有针对性地处理异常
程序运行出现异常时,若程序中没有设置异常处理功能,解释器会采用系统的默认方式处理异常,即返回异常信息、终止程序
异常信息中通常包含异常代码所在行号、异常的类型和异常的描述信息
示例:print(1/0)
Traceback (most recent call last):File "C:\Users\XXXXX\PycharmProjects\PythonProject\105\test\test.py", line 1, in <module>print(1/0)~^~
ZeroDivisionError: division by zero
10.2 异常类型
Python 程序运行出错时产生的每个异常类型都对应一个类,程序运行时出现的异常大多继承自 Exception 类,Exception 类又继承了异常类的基类 BaseException

10.2.1 NameError
NameError 是程序中使用了未定义的变量时会引发的异常
示例:print(a)
Traceback (most recent call last):File "C:\Users\XXXXX\PycharmProjects\PythonProject\105\test\test.py", line 1, in <module>print(a)^
NameError: name 'a' is not defined
10.2.2 IndexError
IndexError 是程序越界访问时会引发的异常
示例:
# s = "Hello"
# print(s[100])Traceback (most recent call last):File "C:\Users\XXXXX\PycharmProjects\PythonProject\105\test\test.py", line 2, in <module>print(s[100])~^^^^^
IndexError: string index out of range
10.2.3 AttributeError
AttributeError 是使用对象访问不存在的属性时引发的异常
示例:
# class Car:
# wheels = 4
#
# c1 = Car()
# print(c1.color)Traceback (most recent call last):File "C:\Users\XXXXX\PycharmProjects\PythonProject\105\test\test.py", line 5, in <module>print(c1.color)^^^^^^^^
AttributeError: 'Car' object has no attribute 'color'
10.2.4 FileNotFoundError
FileNotFoundError 是未找到指定文件或目录时引发的异常
示例:
# f = open("F:\\1.txt","w")Traceback (most recent call last):File "C:\Users\XXXXX\PycharmProjects\PythonProject\105\test\test.py", line 1, in <module>f = open("F:\\1.txt","w")
FileNotFoundError: [Errno 2] No such file or directory: 'F:\\1.txt'
10.3 异常捕获
Python 既可以直接通过 try-except 语句实现简单的异常捕获与处理的功能,也可以将 try-except 语句与 else 或 finally 子句组合实现更强大的异常捕获与处理的功能
10.3.1 try-except
try-except 语句语法如下:
try:监控代码
except [异常类型 [as error]]捕获异常后的处理代码
示例:
num1 = int(input("Enter a division: "))
num2 = int(input("Enter another division: "))try:result = num1 / num2print(result)
except ZeroDivisionError:print("Division by zero!")
输出结果如下:
Enter a division: # 3
Enter another division: # 0
Division by zero!
10.3.2 else 字句
else 子句可以与 try-except 语句组合成 try-except-else 结构,若 try 监控的代码没有异常,程序会执行 else 子句后的代码,语法如下:
try:监控代码
except [异常类型 [as error]]捕获异常后的处理代码
else:未捕获异常后的处理代码
示例:
num1 = int(input("Enter a division: "))
num2 = int(input("Enter another division: "))try:result = num1 / num2
except ZeroDivisionError:print("Division by zero!")
else:print(result)
输出结果如下:
Enter a division: # 3
Enter another division: # 2
1.5
10.3.3 finally 字句
finally 子句可以和 try-except 一起使用,语法如下:
try:监控代码
except [异常类型 [as error]]捕获异常后的处理代码
finally:一定执行的代码
示例:
num1 = int(input("Enter a division: "))
num2 = int(input("Enter another division: "))try:result = num1 / num2
except ZeroDivisionError:print("Division by zero!") # 异常输出
else:print(result) # 无异常输出
finally:print("Bye!") # 有无异常都输出
输出结果如下:
# 正常示例
Enter a division: # 3
Enter another division: # 2
1.5
Bye!# 异常示例
Enter a division: # 3
Enter another division: # 0
Division by zero!
Bye!
10.4 异常抛出
Python 程序中的异常不仅可以自动触发异常,而且还可以由开发人员使用 raise 和 assert 语句主动抛出异常
10.4.1 raise
使用 raise 语句可以显式地抛出异常,raise 语句的语法如下:
raise 异常类 # 使用异常类名引发指定的异常
raise 异常类对象 # 使用异常类的对象引发指定的异常
raise # 使用刚出现过的异常重新引发异常
10.4.2 assert
assert 语句又称为断言语句,其语法如下:
assert 表达式[, 异常信息]
# 表达式不成立时,输出异常信息
示例:
num1 = int(input("Enter a number: "))
num2 = int(input("Enter another number: "))assert num2 !=0 , print("Division by zero!")result = num1 / num2
print("The result is: ", result)
输出结果如下:
# 正常
Enter a number: # 3
Enter another number: # 2
The result is: # 1.5# 异常
Enter a number: # 3
Enter another number: # 0
Traceback (most recent call last):File "C:\Users\XXXXX\PycharmProjects\PythonProject\105\test\test.py", line 4, in <module>assert num2 !=0 , "Division by zero!"^^^^^^^^
AssertionError: Division by zero!
10.4.3 异常传递
异常(exceptions)是通过栈(stack)传递的。当函数中发生异常,该异常会被抛出(raised),然后
由最内层的函数向外传递,直到被捕获(caught)或者导致程序终止
使用 raise 异常类型s(异常信息) 可以将异常抛出
示例:
def func_b():print('func_b')raise ValueError('ERROR') # 抛出异常 ERRORdef func_a():print('func_a')func_b() # func_b() 的异常会传递给 func_a()try:func_a() # func_b() 传递给 func_a() 的异常会被捕捉
except ValueError as e:print(f'Get Error: {e}')
输出结果如下:
func_a
func_b
Get Error: ERROR
10.4.4 自定义异常
自定义异常类可以满足开发者对于自定义的特定情况所要抛出异常的需求,自定义异常类需要继承自 Exception 或其子类,类名一般以 Error 为结尾
示例:
class InvalidAgeError(Exception): # 自定义异常类def __init__(self, age):self.age = ageself.message = "Invaild Age (0~100)"def check_age(age):if not (0 < age < 100):raise InvalidAgeError(age)print(f"Age OK!")try:check_age(int(input("Please input your age: ")))
except InvalidAgeError as e:print(f"Error: " + str(e.message))
输出结果如下:
# 正常
Please input your age: # 20
Age OK!# 异常
Please input your age: # 200
Error: Invaild Age (0~100)
