python 安装


windows

  1. 官网下载 windows 安装包
  2. 运行安装包
  3. 选择配置到PATH环境
  4. 选择安装位置
  5. 下一步…
  6. 完成

Linux

  1. 官网找到 linux 下载页面
  2. 操作系统类型选择未编译源码 source relese
  3. 版本选择:gzip进行压缩的源码文件 Gzipped source tarball
  4. 复制链接地址
  5. linux 终端中通过
    1. wget url地址 下载 python
    2. tar -xvf python文件全称.tgz 解压压缩包
    3. cd 解压出来的文件夹 进入解压出来的目录
    4. ./configure --prefix=/usr/loacl/python安装目录 配置程序的安装路径(可以不进行配置)
      1. 如果不进行配置编译和安装的文件:
        • 可执行文件在 /usr/local/bin
        • 库文件在 /usr/loacl/lib
    5. make && make install 编译和安装源代码
      1. make:编译源代码
      2. make install:将可执行文件复制到指定路径
    6. 配置软链接(快速调用)
      1. 删除 linux 自带老版本链接:rm -f /usr/bin/python
      2. 配置新链接:ls -s /usr/loacl/python安装目录/bin/python运行文件 /usr/bin/python
      3. linux 终端直接使用 python 命令即可调用
    7. 修改了python 快速启动,造成 yum 无法使用需要修改相关配置
      1. 修改两个文件
        • /usr/bin/yum
        • /usr/libbexec/urlgrabber-ext-down
      2. 使用 vi 编辑器,将这两个文件第一行,从 #!/usr/binn/python 修改为 #!/usr/bin/python2

pyCharm 安装

新建项目,配置解释器

  1. new project 新建项目
  2. location ../../选择项目路径/项目名称
  3. Previously configured interpreter 选择以前配置的解释器
    1. Add Interpreter 添加解释器
    2. System Interpreter 选择系统解释器

pyCharm 配置

  • 主题配置
    • 右上角设置按钮
    • theme
  • 字体大小
    • 右上角设置按钮
    • settings
    • 搜索 incre
  • 中文包
    • 右上角设置按钮
    • settings
    • 搜索 Natural Languages

基础


python 运行

python 解释器

python 解释器作用:用于将 python 代码转换成计算机能够识别的 0 1
python 解释器是哪个:python 代码的运行需要 python解释器,python 解释器就是安装的 python 程序, python.exe 文件就是调用 python 解释器的入口,命令行中的 python 命令也就是调用 python.exe

代码运行

  • 命令行一次只能运行一条 python 代码
    1. 调用 python 命令,打开 python 控制台
    2. 输入 python 代码
    3. 退出 python 控制台 exit()
  • 将 python 代码放在 .py 文件中,python 解释器可以一次性执行文件中所有代码
    • python d:\test.py

注释

  • 单行注释 #
  • 多行注释 """ xxxx """

变量

  • 变量是在程序运行时,存储和引用数据的抽象概念
  • 变量没有类型

定义方式:变量名 = 值


变量作用域

  • 变量作用域就是变量可以被使用的范围
  • 根据作用域不同分为 局部变量全局变量
    • 局部变量:函数体中定义的变量只能在函数体中调用,此函数体外任何部位都不可访问此变量
    • 全局变量:不在函数体中定义的变量,可以在后续代码任何部位调用
  • 局部变量全局变量 的变量名相同,则 局部变量 会替换掉 全局变量
    • 因此函数体中直接给 全局变量 赋值,其实是初始化了一个新的 局部变量
    • 函数体中希望给 全局变量 赋值,先使用 global 关键词定义变量为全局变量
1
2
3
4
5
6
7
8
name = "小明"
age = 10
def fn():
global name # 定义为全局变量
name = "小红" # 修改的是全局变量值
age = 20 # 定义了新的局部变量
fn()
print(name,age) # 小红, 10

标识符

什么是标识符:编写代码时,对变量,类,方法等定义的名字,叫做标识符

标识符规范:

  • 只能使用 中文英文数字下划线 定义标识符
  • 不能以数字开头
  • 大小写敏感
  • 不可以使用关键词定义标识符

运算符

运算符的优先级从高到低依次为:

  1. 括号 ()
  2. 指数 **
  3. 正负号 +x-x
  4. 乘法、除法、取模和整除 */%( 取余除 ),//( 取整除 )。
  5. 加法和减法 +-
  6. 位移运算符 <<>>
  7. 按位与 &
  8. 按位异或和按位或 ^|
  9. 比较运算符 ==!=>>=<<=
  10. 赋值运算符 =+=-=, *=, /=, //=, %=, **=, &=, |=, ^=, >>=, <<=
  11. 身份运算符 is, is not
  12. 成员运算符 in, not in
  13. 逻辑运算符 not, and, or

可以使用括号来更改表达式中运算符的优先级。例如:(2 + 3) * 4 = 20


表达式和语句

  • python 中代码可以分为 表达式语句 两类
  • 表达式
    • 表达式是一个计算并返回值的语句
    • 虽然表达式可以被用作语句的一部分,但它并不是一种特殊的语句
    • (字面量是一个表达式)
  • 语句
    • 语句是一条执行指令,不返回值
    • (变量被认为是语句)

数据类型

字面量

  • 可以直接在代码中书写的数据值就是字面量
  • 标准数据类型都可以通过字面量方式定义

标准数据类型

“标准”数据类型,是 Python 语言内置的,可以直接使用,不需要导入任何模块

  • None:<class 'NoneType'>
    • None 是一个特殊的标准数据类型字面量,表示空的,无意义的
    • 初始化变量时不需要具体值,可以使用 None 代替
    • 函数默认返回值为 None
  • 数字(Number)
    • 整型:<class 'int'>
    • 浮点型:<class 'float'>
  • 布尔值:<class 'bool'>
  • 字符串:<class 'str'>
  • 列表:<class 'list'>
  • 元组:<class 'tuple'>
  • 集合:<class 'set'>
  • 字典:<class 'dict'>

类型分类

类型的分类是针对 标准数据类型 不同特性的划分

不可变数据类型

一旦创建,其值就不能被修改的数据类型。如果你尝试修改一个不可变数据类型的值,将会得到一个错误。通过方法对其操作返回的都是一个新值

  • 数字
  • 字符串
  • 元组
  • None
可变数据类型

可以修改其值的数据类型。可以在这些数据类型中添加、删除或修改元素

  • 列表
  • 字典
  • 集合
可迭代类型
  1. 指那些可以被迭代的数据类型对象
  2. 只要是实现了 __iter____getitem__ 方法的对象就是可迭代对象
  3. 可迭代类型都可以使用 for循环 遍历
  4. 不是所有可迭代的数据类型都是序列类型
  • 列表
  • 元组
  • 字符串
  • 字典
  • 集合
  • 任何实现了 __iter____getitem__ 方法的对象都可以被视为可迭代对象
序列类型
  1. 序列类型是一种特殊的可迭代数据类型
  2. 序列中的元素是有序的,可以通过索引来访问
  3. 序列支持切片操作,可以获取序列的一部分
  4. 序列支持连接和重复操作
  • 列表
  • 元组
  • 字符串
有长度数据类型
  1. 具有 __len__ 方法的标准数据类型
  2. 支持 len( ) 函数
  3. 实现 __len__ 方法的自定义类都是具有长度的类型,都可以使用 len( ) 函数
  • 字符串
  • 列表
  • 元组
  • 字典
  • 集合
数据容器类型

用于存储和管理数据的数据结构 数据容器详情

  • 每一份数据称为一个元素
  • 每个元素可以是任意类型的数据
  • 不同的数据容器有不同的特点和用途
    • 字符串(str)
      • 有序的数据容器
      • 字符串一旦创建就不能修改
    • 列表(list)
      • 有序的数据容器
      • 可以进行增删改查等操作
    • 元组(tuple)
      • 一种有序的数据容器
      • 元组一旦创建就不能修改
    • 字典(dict)
      • 无序的数据容器
      • 用于存储键值对,可以通过键来快速访问对应的值
      • 键必须是唯一的
    • 集合(set)
      • 无序的数据容器
      • 存储不重复的元素
      • 支持集合运算,如并集、交集和差集等

类型解释


字符串


特性
  1. 字符串定义:可以通过单引号 ' 或双引号 " 进行定义
  2. 通过下标获取字符:字符串可以通过下标获取某字符 "abcde"[1] == "b" "abcde"[-2] == "d"
  3. 多行字符串:可以使用三引号("""''')来定义多行字符串
  4. 多行字符串与多行注释:多行注释和多行字符串定义语法相同,不同之处是一个被调用一个没被调用,没有被调用就是注释将不会被执行
  5. 字符串是不可变的:这意味着一旦创建了一个字符串,就不能修改它。如果修改一个字符串,将创建一个新的字符串
  6. 引号嵌套:双引号和单引号可以相互嵌套,嵌套的引号可以直接作为字符。或者引号中使用 \ 转义字符转义引号 " \"x\" "
  7. 字符串的比较
    1. 字符的比较是根据字符对应的 ASCII 值的大小比较
    2. 字符串比较是按位字符的比较,只要有一位字符大于同位另一字符串的字符,则整个字符串大于另一个字符串

操作

拼接
  • 字符串之间使用 + 进行拼接
  • 返回一个新字符串
  • 字符串不能与其他类型数据进行拼接

格式化占位符

% 方式

  • 作用: 可以将其他类型值插入到字符串中的占位符位置,生成一个完整字符串
  • 占位: 使用 %s %d %f 在字符串中进行占位
    • %s
      • 将要插入的内容转换为字符串,然后放入占位符位置
    • %d
      • 只能插入实数。
      • 如果是浮点数,则会转换成整数,然后放入占位符位置
    • %f
      • 只能插入实数。
      • 如果是整数,则会转换成浮点数,然后放入占位符位置
  • 插入:
    • 字符串后紧跟 %(,,,) 用于将小括号内的值按照占位符顺序插入对应占位符
    • 一个值可以省略小括号 %xx
    • 可以插入变量、字面量、表达式
  • 格式化
    • 格式化控制只能针对 %d %f 占位符。
    • 对插入的数字进行格式化处理 (格式化值:先依据规则转换然后进行格式化)
      • %m.n[d|f]
        • m:表示插入数值的 整数、点、小数 各部位字符总个数,如果 m 大于插入值,则整数部分左侧用空格填充多余字符个数。小于则不起作用
        • n:表示小数部分显示位数
          • %5d:如果定义数值小于整数部分则不起作用。如果定义数值大于整数部分多余的个数作为整数部分前面的空格
          • %5.2d:效果等同于 %5d 小数部分不起作用
          • %5.2f:小数部分保留两位。整数部、点、小数部分 总长度为5,不足整数部分左侧用空格填充。小于不起作用
          • %5.0f:效果等同于 %5d,省略掉小数部分
          • %.2f:小数部分将保留两位
1
2
3
4
5
6
7
8
"aaa%saaa"%123 // "aaa123aaa"
"abcd%sefg%shi"%(123,456) // "abccd123efg456hi"

"aaa%5daaa"%123 // "aaa 123aaa"
"aaa%5.2daaa"%123 // "aaa 123aaa"
"aaa%7.2faaa"%123.123 // "aaa 123.12aaa"
"aaa%7.0faaa"%123.123 // "aaa 123aaa"
"aaa%.2faaa"%123.123 // "aaa123.12aaa"

{…} 方式

  • 字符串前添加 f 关键字
  • 字符串中的 { } 里可以直接输入 变量、字面量、表达式
  • 插入的数据可以是任何类型
1
f"abc{123}defg" // "abc123defg"

查询某字符下标

字符串.index(字符)

  • 功能:查找字符(串)在字符串中的起始下标,如果找不到报错
  • 参数1:要在字符串中查找的字符(串)
  • 返回值:字符(串)所在起始下标
1
2
3
str = "abcdefg"
i = str.index("d")
print(i) # 3

字符串的替换

字符串.replace(字符串1, 字符串2)

  • 功能:将字符串中的所有 字符串1 替换成 字符串2。不是修改了字符串,而是生成了一个新字符串
  • 参数1:要被替换掉的 字符串
  • 参数2:要使用的新 字符串
  • 返回值:替换后的新字符串
1
2
3
str = "abcdefga"
str2 = str.replace("a","h")
print(str2) # hbcdefgh

将字符串拆分成列表

字符串.split(分割符字符串)

  • 功能:根据参数将字符串拆分成列表
  • 参数1:字符串中根据此字符串拆分
  • 返回值:字符串本身不变,返回一个新列表对象
1
2
3
str = "abcdefg"
lis = str.split("d")
print(lis) #["abc","efg"]

去除首尾指定字符或空格

字符串.strip() 字符串.strip(字符串)

  • 功能:去除字符串首尾指定字符(串)或空格
  • 参数:
    • 不传:去除字符串首尾空格
    • 1:去除字符串首尾指定字符(串)
  • 返回值:去除了指定字符(串)的新字符串
1
2
3
str = "abcdefg "
str2 = str.strip() # "abcdefg"
str3 = str.strip("ab") # "cdefg "

统计字符(串)在字符串中的数量

字符串.count(字符串)

  • 功能:统计字符(串)在字符串中的数量
  • 参数1:要统计的字符(串)
  • 返回值:字符(串)数量
1
2
str = "abcdefa"
con = str.count("a") # 2

布尔类型


特性
  • 布尔类型只有两个值:True False
  • TrueFalse 都是关键字
  • 在 Python 3 中,不同类型的数据之间不能进行比较(Python 2 中,不同类型的数据之间可以进行比较,但结果可能不是你所期望的)
  • 与数字进行比较时,True 被视为 1,而 False 被视为 0
  • 和逻辑运算符一起使用,生成一个新的布尔值
  • 转换成数字,True 转换成 1 | 1.0,而 False 转换成 0 | 0.0
  • 转换成字符串,"True" "False"

类型转换

  • python 运行过程中数据类型是不能进行隐式转换的
  • python 在编写时是不会进行类型检查的

转字符串

函数:str(x)

  • 任何类型数据都可以转换为字符串
  • 数字转字符串:如果数字值特别大,转换的字符串可能是科学计数法

转整数

函数:int(x)

  • 字符串转整数:字符串只能是整数表示形式,不能有任何数字以外其他字符,即使小数点也不可以
  • 浮点数转整数:将截断小数部分

转浮点数

函数:float(x)

  • 字符串转浮点数:字符串只能是整数形式或小数形式(可以有小数点),不能包含其他字符
  • 整数转浮点数:则整数变成浮点数小数部位为0

转布尔值

  • None 可以隐式转换为 False

类型用法

切片

  • 只能操作序列数据类型数据
  • 从指定下标开始,到指定下标前的元素,作为一个新序列类型数据返回
  • 不会修改原序列数据
  • 序列[start:end:step]
    • strat:
      • 开始下标
      • 不传(默认):从 0 开始
    • end:
      • 结束下标(不包含)
      • 不传(默认):到最后一个元素为止【包含】
    • step:步长
      • 控制开始和结束方向
      • 控制元素相隔个数
      • 不传:默认为 1
      • 负数:表示从后往前
        • start 不传:从最后一个元素开始
        • end 不传:到 0 下标为止
1
2
3
4
5
6
7
lis = [1,2,3,4,5,6]   # [1,2,3,4,5,6]
lis2 = lis[1:4] # [2,3,4]
lis3 = lis[0:5:2] # [1,3,5]
lis4 = lis[:] # [1,2,3,4,5,6] (可以作为克隆序列数据)
lis5 = lis[::-1] # [6,5,4,3,2,1] (反转序列数据)
lis6 = lis[3:1:-1] # [4,3,2]
lis7 = lis[1:3:-1] # [] (方向从后向前,因此 start 应该大于 end)

列表(list)


特性
  • 有序的数据容器
    • 通过下标索引获取元素
    • 从前往后:0 ~ n
    • 从后往前:-n ~ -1
  • 可以进行增删改查等操作
  • 列表可以嵌套
  • 空列表
    • []
    • list()
1
2
3
4
5
6
7
[元素1, 元素2, 元素3]
name = [元素1, 元素2, 元素3]
name2 = [] # 空列表
name3 = list() # 空列表
a = name[0] # 元素1
b = name[-1] # 元素3
c = name[1][2] # 获取嵌套列表的元素

常用方法
查询某元素下标

列表.index(元素)

  • 功能:查找元素在列表中的下标,如果找不到报错
  • 参数1:要在列表中查找的元素
  • 返回值:元素所在下标
1
2
3
lis = [1,2,3,4,5]
i = lis.index(5)
print(i) # 4
修改指定下标元素

列表[下标] = 值

  • 功能:对列表指定下标的元素重新赋值
1
2
3
lis = [1,2,3,4,5]
lis[1] = "a"
print(lis) # [1,"a",3,4,5]
插入元素

列表.insert(下标,元素)

  • 功能:在指定下标位置,插入元素。只能插入一个元素
  • 参数1:指定位置的下标
  • 参数2:要插入的元素
  • 返回值:None
1
2
3
lis = [1,2,3,4,5]
lis.insert(1,"a")
print(lis) # [1, 'a', 2, 3, 4, 5]
列表末尾添加一个元素

列表.append(元素)

  • 功能:在列表末尾追加一个元素。只能追加一个元素
  • 参数1:追加的元素
  • 返回值:None
1
2
lis = [1,2,3,4,5]
lis.append("a","b") # [1, 2, 3, 4, 5, 'a']
列表末尾添加多个元素

列表.extend(可迭代对象)

  • 功能:将其他可迭代对象中的元素,全部插入到列表的末尾
  • 参数1:其他可迭代对象
  • 返回值:None
1
2
3
4
my_list = [1, 2, 3]
my_dict = {'a': 4, 'b': 5, 'c': 6}
my_list.extend(my_dict)
print(my_list) # [1, 2, 3, 'a', 'b', 'c']
删除元素

del 列表[下标]

  • 功能:删除列表指定下标的元素
  • 参数1:要删除的元素下标
  • 返回值:没有返回值,不能赋值给变量(赋值给变量会报语法错误)
1
2
lis = [1,2,3,4]
del lis[2] # [1,2,4]

列表.pop(下标)

  • 功能:删除列表指定下标的元素,并返回这个元素
  • 参数1:要删除的元素下标
  • 返回值:删除的元素
1
2
3
lis = [1,2,3,4]
lis2 = lis.pop(2)
print(lis,lis2) # [1, 2, 4] 3

列表.remove(元素)

  • 功能:在列表中从前向后匹配指定元素,删除第一次匹配到的元素
  • 参数1:要删除的元素
  • 返回值:None
1
2
3
lis = [1,2,3,4]
lis2 = lis.remove(2)
print(lis,lis2) # [1, 3, 4] None

列表.clear( )

  • 功能:清空列表所有元素
  • 返回值:None
1
2
3
lis = [1,2,3,4]
lis2 = lis.clear()
print(lis,lis2) # [] None
统计某元素在列表的数量

列表.count(元素)

  • 功能:统计元素在列表中的数量
  • 参数1:要统计的元素
  • 返回值:元素数量 <class int>
1
2
3
lis = [1,2,3,4,2]
lis2 = lis.count(2)
print(lis,lis2,type(lis2)) # [1, 2, 3, 4, 2] 2 <class 'int'>

元组

特性
  • 有序的数据容器
    • 通过下标索引获取元素
    • 从前往后:0 ~ n
    • 从后往前:-n ~ -1
  • 元组一旦定义完成,元素就无法修改
    • 但是,元组元素(非元组)的元素是可以修改的
  • 元组可以嵌套
  • 元组只有一个元素,则元素后必须带上逗号 ('a',)
  • 空元组
    • ()
    • tuple()
1
2
3
4
5
6
7
8
(元素1, 元素2, 元素3)
name = (元素1, 元素2, 元素3)
name2 = () # 定义空元组
name3 = tuple() # 定义空元组
name4 = (元素1,) # 只有一个元素,必读带上逗号 ,
a = name[0] # 元素1
b = name[-1] # 元素3
c = name[1][2] # 获取嵌套元组的元素

常用方法

查询某元素下标

元组.index(元素)

  • 功能:查找元素在元组中的下标,如果找不到报错
  • 参数1:要在元组中查找的元素
  • 返回值:元素所在下标
1
2
3
lis = (1,2,3,4,5)
i = lis.index(5)
print(i) # 4

统计某元素在元组的数量

元组.count(元素)

  • 功能:统计元素在元组中的数量
  • 参数1:要统计的元素
  • 返回值:元素数量 <class int>
1
2
3
lis = (1,2,3,4,2)
lis2 = lis.count(2)
print(lis,lis2,type(lis2)) # (1, 2, 3, 4, 2) 2 <class 'int'>

集合

特性
  • 无序的数据容器
    • 不支持下标索引访问
  • 存储不重复的元素
  • 可以修改集合
  • 虽然集合是无序的,但是当您打印或显示集合时,它可能会以排序的方式显示。这只是一种显示方式,在内部,集合中的元素仍然是无序的
  • 空集合
    • set()
1
2
3
{1,2,3,"a","b","c","a"}
name = {1,2,3,"a","b","c","a"}
name2 = set() # 定义空集合
常用方法
添加元素

集合.add(元素)

  • 功能:将一个元素添加到集合
  • 参数1:要添加的元素
  • 返回值:None
1
2
3
name = { 1,2,3,"a" }
name.add("b")
print(name) # {1,2,3,"a","b"}

移除指定元素

集合.remove(元素)

  • 功能:将一个元素从集合中移除
  • 参数1:要移除的元素
  • 返回值:None
1
2
3
name = { 1,2,3,"a" }
name.remove("a")
print(name) # {1,2,3}

清空集合

集合.clear()

  • 功能:清空集合所有元素
  • 返回值:None
1
2
3
name = { 1,2,3,"a" }
name.clear()
print(name) # set()

取两个集合的差集

集合1.difference(集合2)

  • 功能:取出集合1中有,而集合2中没有的元素,作为新集合返回
    • 两个原集合不变
  • 参数1:用于比较的集合
  • 返回值:新集合
1
2
3
4
name = { 1,2,3,"a" }
name2 = { 1,2,4,"b" }
name3 = name.difference(name2)
print(name3) # { 3,"a" }

移除两个集合都存在的元素

集合1.difference_update(集合2)

  • 功能:在集合1中,移除和集合2相同的元素
    • 会修改集合1
    • difference 方法 相比
      • 相同点:得到差集
      • 不同点:一个是生成新集合,一个是在原集合上修改
  • 参数1:用于比较的集合
  • 返回值:None
1
2
3
4
name = { 1,2,3,"a" }
name2 = { 1,2,4,"b" }
name3 = name.difference_update(name2)
print(name) # { 3,"a" }

合并集合

集合1.union(集合2)

  • 功能:将集合1和集合2合并成一个新集合
    • 不会修改原集合
  • 参数1:用于合并的集合
  • 返回值:新集合
1
2
3
4
name = { 1,2,3,"a" }
name2 = { 1,2,4,"b" }
name3 = name.union(name2)
print(name3) # { 1,2,3,4,"a","b" }

字典

特性
  • 无序的数据容器
    • 不支持下标索引访问
  • 通过 key 查找对应 value 的数据结构
  • key value 的组合叫键值对,一组键值对就是字典的一个元素。
  • key 是唯一的
  • keyvalue 可以是任意类型数据
    • key 如果是字符串值不能写成关键字形式
    • key 不可以是字典
  • 使用 for循环 迭代时,取到的是元素的 key
  • 字典可以嵌套
  • 空字典
    • {}
    • dict()
1
2
3
4
5
6
7
{"小明":16,"小红":18}
name = {"小明":16,"小红":18}
name2 = {} # 定义空字典
name3 = dict() # 定义空字典
name4 = {"小明":16,"小红":{"语文":96,"数学",99}}
print(name4["小明"]) # 16
print(name4["小红"]["语文"]) # 96

常用方法
添加字典

字典[new_key] = value

1
2
3
name = {"小明":16}
name["小红"] = 18
print(name) # {"小明":16,"小红":18}
修改元素

字典[old_key] = value

1
2
3
name = {"小明":16}
name["小明"] = 18
print(name) # {"小明":18}
删除元素

字典.pop(key)

  • 功能:根据 key 删除指定键值对
  • 参数1:要删除的键值对 key
  • 返回值:删除的键值对的 value
1
2
3
4
name = {"小明":16,"小红":18}
name2 = name.pop("小明")
print(name) # {'小红': 18}
print(name2) # 16
清空字典

字典.clear()

  • 功能:清空字典所有元素
  • 返回值:None
1
2
3
name = { "小明":16 }
name.clear()
print(name) # {}
获取全部 key

字典.keys()

  • 功能:获取字典中所有键值对的 key
  • 返回值:<class 'dict_keys'> 类型的可迭代数据
1
2
3
name = { "小明":16,"小红":18 }
name2 = name.keys()
print(name2) # dict_keys(['小明', '小红'])

语句


if 语句

如果达到某个条件执行代码块内容,否则执行其他代码块内容

必要条件

  • if 关键词
  • else 关键词
  • elif 关键词
  • 条件(返回布尔值的表达式)
  • : 标识符
  • 代码块缩进(同一代码块中应该有相同缩进)

特性

  • 可以进行嵌套
1
2
if true:
print("if 语句中的执行内容")
1
2
3
4
if true:
print("满足条件执行的语句")
else:
print("不满足条件执行的语句")
1
2
3
4
5
6
7
8
age = 18

if age < 10:
print("小于10执行")
elif age == 10:
print("等于10执行")
else:
print("其他情况执行")
1
2
3
4
if true:
print("第一层")
if true:
print("第二层")

循环语句


while 语句

达到条件执行代码块内容,代码块执行完毕重新判断条件,如果条件依旧返回 ture,继续执行代码块内容。直到条件返回 false 将不再执行代码块内容

必要条件

  • while 关键词
  • 条件(返回布尔值的表达式)
  • : 标识符
  • 代码块缩进(同一代码块中应该有相同缩进)

特性

  • 可以进行嵌套
1
2
3
4
5
a = 0

while a <= 10:
print(f"执行第{a}次")
a+=1

for 语句

  • 对序列类型数据中每个元素进行遍历,每次都执行代码块内容
  • 不能指定循环条件,循环次数只能由元素个数决定

必要条件

  • for 关键词
  • in 关键词
  • 临时变量
  • 序列类型数据
  • : 标识符
  • 代码块缩进(同一代码块中应该有相同缩进)

特性

  • 临时变量规范要求在循环体中有效,但非强制性。虽然有警告提示,但是依旧在循环外部可以获取
  • 如果要按照规范在循环体外获取变量,应该提前定义
1
2
3
# 常规用法
for a in "abcde":
print(a)
1
2
3
4
5
# 循环之外可以获取变量,虽然会有警告,但是不报错
for a in "abcde":
print(a)

print(a)
1
2
3
4
5
6
7
8
9
10
11
# 遍历指定次数
for i in range(5):
print(i)

"""
0
1
2
3
4
"""

退出循环

  • 通过 continuebreak 控制退出循环
  • 适用于 whilefor 循环语句

continue

  • 停止本次循环体后续代码的执行,进入下次循环
  • 只能控制当前所在循环语句,不影响父循环语句
1
2
3
4
5
6
7
8
9
10
11
for i in range(5):
if i == 3:
continue
print(i)

"""
0
1
2
4
"""

break

  • 终止循环语句的循环操作
  • 只能终止当前所在循环语句,不影响父循环语句
1
2
3
4
5
6
7
8
9
10
for i in range(5):
if i == 3:
break
print(i)

"""
0
1
2
"""

函数

组织好的,可重复使用的,用来实现特定功能的代码段


函数和方法区别

函数和方法都是用来封装一段可重用代码的方式。它们的区别在于定义和调用方式。

  • 函数是独立定义的,可以直接调用。它通常用来完成某个特定的功能,可以接受参数并返回结果。
  • 方法是定义在类中的函数,通常用来操作类或实例的属性和方法。方法只能通过类或实例来调用,第一个参数通常是 self(指向实例本身)或 cls(指向类本身)。

简单来说,方法是类中定义的函数,它与类或实例相关联。

定义

必要条件

  • def
  • 函数名
  • 小括号( )
  • 参数
  • :
  • return
1
2
3
def 函数名 ( 传入参数 ):
函数体
return 返回值

注意事项

  • 必须先定义函数
  • 然后才能调用函数
  • 函数定义必须在调用之前

参数

注意事项

  • 函数定义中的参数,称为形式参数(形参),它是个关键字不是数据
  • 函数调用中的参数,称为实际参数(实参),它是个具体数据
  • 函数可以定义任意多个参数
  • 形参实参 数量必须保持一致,否则报错(包含默认参数)
  • 函数本身可以作为参数进行传递

参数的分类

位置参数
  • 形参实参 必须保持数量和顺序一一对应
  • 如果 形参实参 数量不一致,会报错
  • 如果 形参实参 顺序不一致,形参变量将接收对应位置实参数据
1
2
3
4
5
def fn(x,y):
print(f"形参x对应实参{x}") # 2
print(f"形参y对应实参{y}") # 3

fn(2,3)
关键字参数
  • 形参实参 数量必须保持一致,否则报错
  • 使用键值对的方式向 形参 传递 实参
  • key 为对应 形参关键字value 为传入 实参数据
  • 参数顺序可以随意
  • 位置参数+关键字参数混合使用
    • 第一个参数必须是位置参数
    • 匹配形参顺序的位置参数结束后,才可以使用关键字参数
1
2
3
4
5
6
7
8
def fn(w,x,y,z):
print(f"形参w对应实参{w}") # 1
print(f"形参x对应实参{x}") # 4
print(f"形参y对应实参{y}") # 3
print(f"形参z对应实参{z}") # 2

fn(z=2,x=4,y=3,w=1) # 关键字参数不用匹配顺序
fn(1,4,z=2,y=3) # 位置参数顺序结束后,才可以使用关键字参数
默认参数
  • 指定了默认值的形参,在实参传递时可以不用传入对应位置实参
  • 默认形参后面不可以跟普通形参
1
2
3
4
5
6
7
def fn(w,x,y=5):
print(f"形参w对应实参{w}") # 1
print(f"形参x对应实参{x}") # 4
print(f"形参y对应实参{y}") # 5

fn(1,4)
fn(x=4,w=1)
位置不定长参数
  • 使用位置参数形式传入不确定个数的实参
  • 后面只能跟默认形参(只能通过关键词参数传入实参)
  • 通过一个形参,接收不定长的参数,且形参前有一个星号 *
  • 形参是以 元组 形式接收实参数据
1
2
3
4
def fn( *args ):
print(f"不定长参数:{args}") # (1,4,"a",5,"b")

fn(1,4,"a",5,"b")
关键字不定长参数
  • 使用关键字参数形式传入不确定个数的实参
  • 后面不能跟任何形参
  • 通过一个形参,接收不定长的参数,且形参前有两个星号 **
  • 形参是以 字典 形式接收实参数据
1
2
3
4
def fn( **args ):
print(f"不定长参数:{args}") # {'a':1,'b':"bbb"}

fn(a=1,b="bb")
不定长参数和其他参数混用
  • 与普通形参混用,不定长参数只能位于最后
  • 与默认形参混用
    • 不定长参数在前:默认形参的值永远只能是默认值
    • 默认形参在前:默认形成惨的值

返回值

函数调用后返回的值

注意事项

  • 关键字 return 返回结果
  • 定义了 return 和返回值,之后的代码都不执行
  • 如果没有定义返回值,则默认返回值为 None
1
2
3
4
5
def fn (x,y):
return x+y

r = fn(5,6)
print(r) # 11
1
2
3
4
5
6
7
8
9
10
def fn1 ():
print(12)
r = f1()
print(r) # None

def fn2 ():
print(12)
return
r = f1()
print(r) # None

多返回值

  • 函数可以同时返回多个值
  • 多个值使用逗号隔开
  • 同时定义多个变量按顺序进行接收
1
2
3
4
5
6
7
8
def fn():
return 1,"name",True # 同时返回三个值

x,y,z = fn() # 使用三个变量按顺序接收

print(x) # 1
print(y) # "name"
print(z) # True

匿名函数

  • 通过 lambda 关键字进行定义
  • 语法:
    • 有参:lambda 参数1, 参数2: 表达式 (一行代码)(参数不能使用小括号包裹)
    • 无参:lambda: 表达式 (一行代码)
  • 函数体表达式就是匿名函数的返回值,不需要使用 return
  • 可以用变量进行接收
  • 可以作为实参时直接定义使用
  • 匿名函数的定义只能在一行完成,多行函数体必须使用 def
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 匿名函数赋值给变量
my_function = lambda: "Hello World"
print(my_function())

# 匿名函数用作参数
my_function = lambda x,y: x+y
def fn(ff,x,y):
print(ff(x,y))
fn(my_function,1,2) # 3

# 实参直接使用匿名函数定义
def fn(ff,x,y):
print(ff(x,y))
fn(lambda x,y:x+y,1,2) # 3

闭包

  1. 父函数中定义了子函数
  2. 并且将子函数作为返回值返回
  3. 结合变量作用域的限制
    • 子函数可以访问父函数中定义的变量
    • 子函数调用父函数定义变量,需要先使用 nonlocal 关键词定义,否则直接使用变量将是新建同名变量
  4. 函数调用时将生成一个新的变量对象,因此每次调用父函数,父函数其内部的变量和值都是新的且独立的
  • 因此可以通过调用父函数,生成一个独立变量,并用返回的子函数来操作这个独立变量。实现不通过定义全局变量的情况下,相同函数可以处理不同独立的数据
1
2
3
4
5
6
7
8
9
10
def fu_fn(age):
def zi_fn(add):
nonlocal age # 子函数中调用夫函数中的变量,需要先用 nonlocal 定义,否则是定义一个新变量
age += add
return age
return zi_fn

x = fu_fn(16)
print(x(1)) # 17
print(x(2)) # 19

装饰器

  • 实现方式就是通过闭包
  • 作用是在调用同一个函数时,可以获取具有额外不同功能的新函数(效果如同给同一函数增加了不同功能)
    • 基础实现
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      def zsq(fn):
      def fhz():
      print("开始执行装饰器函数")
      fn()
      print("执行结束装饰器函数")
      return fhz

      def zjgn():
      print("执行新增功能")

      test = zsq(zjgn)

      test()
      """
      开始执行装饰器函数
      执行新增功能
      执行结束装饰器函数
      """
    • 语法糖
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      def zsq(fn):
      def fhz():
      print("开始执行装饰器函数")
      fn()
      print("执行结束装饰器函数")
      return fhz

      @zsq
      def zjgn():
      print("执行不同功能1111111")


      zjgn()
      """
      开始执行装饰器函数
      执行不同功能1111111
      执行结束装饰器函数
      """

递归

  • 递归就是函数或方法体中自己调用自己
  • 注意退出条件,否则是无限递归
  • 注意返回值要传递到外层

设计模式

单例模式

  • 不管在任何地方,都希望获取的是同一个对象
  • 实现方式:
    1. 创建一个模块
      1. 模块中定义一个类
      2. 通过这个类实例化一个对象并赋值给一个变量
    2. 其他模块中引入这个模块的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# tools 模块
class strTools:
pass

toolObj = strTools()

# test1 模块
from tools import toolObj

tool_1 = toolObj
tool_2 = toolObj

# test2 模块
from tools import toolObj

tool_3 = toolObj
tool_4 = toolObj

"""
相同/不同模块中 tool_1、tool_2、tool_3、tool_4 都是同一个对象
"""

工厂模式

  • 定义一个函数/方法,通过调用这个函数/方法,根据传入不同实参,返回不同的实例对象
  • 对于需要获取不同类型对象时,方便管理和维护
    • 如果多处通过某个类实例化,如果初始化时参数发生改变,那么这些地方都需要修改实参,但是通过工厂模式创建的对象,只需要修改工厂中创建对象的代码即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person:
pass

class Teacher(Person):
pass

class Student(Person):
pass

# 定义工厂
class PersonFactory:
def get_person(self,p_type):
if p_type == "t":
return Teacher()
elif p_type == "s":
return Student()

pf = PersonFactory()
teacher = pf.get_person("t") # 调用方法时根据传入参数返回不同对象
student = pf.get_person("s") # 调用方法时根据传入参数返回不同对象

函数说明文档

  • 对函数的解释说明
  • 配合开发工具可以在调用函数时进行函数代码提示
  • 函数体首部使用多行注释进行定义函数说明文档
1
2
3
4
5
6
7
8
9
def fn (x,y):
"""
函数说明
:param x: 参数x的说明
:param y: 参数y的说明
:return: 返回值的说明
"""
函数体
return 返回值

异常

注意事项

  • 异常就是程序运行过程中出现的错误
  • 对异常的捕获可以在出现异常时提供解决代码
  • 未捕获和处理的异常将阻止代码继续执行
  • 异常是可以在函数间传递的,如果 A 函数体内部调用别的 B 函数,B 函数中抛出的异常没有被捕获处理,则 A 函数中依旧可以捕获和处理此异常,以此类推
  • try:用来捕获异常
  • except:用来处理捕获的异常
  • else:定义当没有捕获到异常时执行的代码
  • finally:定义不管是否捕获到异常,都会执行的代码

捕获处理异常

捕获任意异常

1
2
3
4
5
6
7
8
9
10
11
12
try:
f = open("../../test.txt","r",encoding="UTF-8") # 文件不存在抛出异常,被捕获
except:
print("捕获异常进行处理")
f = open("../../test.txt","w",encoding="UTF-8") # 使用 w 模式打开文件

try:
print(name)
1/0
except Exception as e:
print("Exception 是所有异常类型的父类,所以捕获这个异常类型就是捕获任意类型异常")
print("捕获到的异常对象是:",e)

捕获指定异常

只捕获和处理指定类型的异常,其他类型异常将不会被捕获和处理

1
2
3
4
5
6
try:
print(name)
1/0 # 此处抛出的异常将不会被捕获,会在控制台显示,并阻止代码继续执行
except NameError as e:
print("只捕获和处理变量未定义的异常")
print("捕获到的异常对象是:",e)

捕获多个异常

1
2
3
4
5
6
try:
print(name)
1/0
except (NameError,ZeroDivisionError) as e:
print("只捕获和处理变量未定义和除以0的异常")
print("捕获到的异常对象是:",e)

没有捕获到异常的处理

  • 当没有捕获到异常,使用 else: 来定义将会执行的代码
  • 此选项可以定义,也可以不定义
1
2
3
4
5
6
try:
print("此处并没有抛出异常")
except:
print("没有捕获到异常,所以没有执行异常处理相关代码")
else:
print("没有捕获到异常,执行此处代码")

必定执行的代码

  • 不管是否捕获到异常,使用 finally 定义的代码都将执行
  • 此选项可以定义,也可以不定义
1
2
3
4
5
6
7
8
try:
print("此处并没有抛出异常")
except:
print("没有捕获到异常,所以没有执行异常处理相关代码")
else:
print("没有捕获到异常,执行此处代码")
finally:
print("不管是否捕获到异常此处代码都将执行")

类的定义

  • 通过 class 关键字定义一个类
  • 必要字符
    • class
    • 类名
    • :
1
2
3
4
class Student:
name = None
gender = None
age = None

实例化对象

  • 通过类名加上小括号进行实例化
1
2
3
4
5
6
class Student:
name = None
gender = None
age = None

stu_1 = Student() # 实例化一个对象

构造方法

  • 用于创建实例对象时初始化实例对象的属性值
  • 实例化对象时会自动运行
  • 通过关键字 __init__ 定义的函数(属于魔术方法)
  • 需要 self 接收实例对象
1
2
3
4
5
6
7
8
9
class Student:
name = None
def __init__(self,name,age):
self.name = name
self.age = age

stu_1 = Student("小明",18) # 实例化一个对象,并初始化对象属性
print(stu_1.name) # 小明
print(stu_1.age) # 18

成员

类成员

  • 类成员是属于类本身的,包括 类属性类方法
  • 类属性
    • 定义在类中的变量
    • 类属性是属于类本身的
    • 可以通过类名访问
    • 可以通过实例对象访问
  • 类方法
    • 定义在类中的函数
    • 需要装饰器 @classmethod 定义为类方法
    • 类方法是属于类本身的
    • 可以通过类名访问
    • 可以通过实例对象访问
    • 方法的第一个形参是类本身
      • 必须声明此形参,否则调用方法时报错(调用方法会自动传入此实参)
      • 约定成俗的命名 cls,也可以使用别的名称
      • 只有通过 cls 才能在方法中访问类的其他类成员
      • 通过类调用方法时,不需要传入第一个形参 cls 对应的实参,此参数是默认自动传入的
1
2
3
4
5
6
7
8
9
10
11
class Student:
# 定义类属性
name = "小明"

# 定义类方法
@classmethod
def say(cls):
print(f"类属性name值是:{cls.name}")

print(Student.name) # 访问类属性 小明
Student.say() # 访问类方法 类属性name值是:小明

实例成员

  • 实例成员是属于实例对象的,包括 实例属性实例方法
  • 实例属性
    • 定义在类中的变量
    • 实例属性是属于实例对象的
    • 只能通过实例对象访问
  • 实例方法
    • 定义在类中的函数
    • 实例方法是属于实例对象的
    • 只能通过实例对象访问
    • 方法的第一个形参是实例对象本身
      • 必须声明此形参,否则调用方法时报错(调用方法会自动传入此实参)
      • 约定成俗的命名 self,也可以使用别的名称
      • 只有通过 self 才能在方法中访问实例对象的其他成员
      • 通过实例对象调用方法时,不需要传入第一个形参 self 对应的实参,此参数是默认自动传入的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Student:
# 此属性可以称为类属性,也可称为实例属性
# 由调用方式决定
name = "小明"

# 构造函数中定义实例属性
def __init__(self):
self.age = 16

# 定义实例方法
def say(self):
print(f"实例属性name值是:{self.name}")
print(f"实例属性age值是:{self.age}")

stu_1 = Student() # 实例化对象

print(stu_1.name) # 访问实例属性 小明
stu_1.say() # 访问实例方法 实例属性name值是:小明
# 实例属性age值是:16

私有成员

  • 类成员 实例成员 都可以设置为私有的
  • 私有成员只能在类中被访问,无法在类外部访问
  • 在成员名称在前面加上 __ 即为私有成员
  • Python并不真正支持私有成员,它只是通过名称改写(name mangling)来实现一种类似于私有成员的效果
  • 使用改写后的名称格式 _classname__private_member,也可以在类外部调用私有成员
1
2
3
4
5
6
7
8
9
10
11
class Student:
def __init__(self,name,age):
self.name = name
self.__age = age # 定义私有成员

def getage(self):
return self.__age # 私有成员在类内部可以访问

stu = Student("小明",16)
print(stu.__age) # 会报错,私有属性在类外部无法访问(除了改写名称)
print(stu.getage()) # 16

魔术方法

  • python 类中内置的方法叫做 魔术方法,使用两个 __ 定义的方法都是 魔术方法
  • 类或实例 执行特定操作时,Python会自动调用相应的魔术方法

实例转换字符串

__str__

  • 当使用 str() 函数转换对象为字符串时,将调用此方法
  • 默认情况是返回内存地址
1
2
3
4
5
6
7
8
9
10
11
class Student:
def __init__(self,name,age):
self.name = name
self.age = age

# 魔术方法
def __str__(self):
return f"name={self.name},age={self.age}"

stu = Student("小明",16)
print(str(stu)) # "name=小明,age=16"

实例 > < 比较

__lt__

  • 当使用 小于号或大于号 对两个此类型实例进行比较时,将调用此方法
  • 默认情况会报错,无法进行比较。实现了此方法就可以对两个此对象进行比较
  • 形参需要第二个参数,比较时的另一个实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Student:
def __init__(self,name,age):
self.name = name
self.age = age

# 魔术方法
def __lt__(self,other):
return self.age < other.age

stu1 = Student("小明",16)
stu2 = Student("小红",18)

print(stu1 < stu2) # True
print(stu1 > stu2) # False

实例 >= <= 比较

__le__

  • 当使用 小于等于号或大于等于号 对两个此类型实例进行比较时,将调用此方法
  • 默认情况会报错,无法进行比较。实现了此方法就可以对两个此对象进行比较
  • 形参需要第二个参数,比较时的另一个实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Student:
def __init__(self,name,age):
self.name = name
self.age = age

# 魔术方法
def __le__(self,other):
return self.age <= other.age

stu1 = Student("小明",16)
stu2 = Student("小红",18)

print(stu1 <= stu2) # True
print(stu1 >= stu2) # False

实例 == 比较

__eq__

  • 当使用 等于号 对两个此类型实例进行比较时,将调用此方法
  • 默认情况比较的是内存地址
  • 形参需要第二个参数,比较时的另一个实例
1
2
3
4
5
6
7
8
9
10
11
12
13
class Student:
def __init__(self,name,age):
self.name = name
self.age = age

# 魔术方法
def __eq__(self,other):
return self.age == other.age

stu1 = Student("小明",16)
stu2 = Student("小红",16)

print(stu1 == stu2) # True

继承

  • 一个类(子类)可以继承另一个类(父类)的成员(包括属性和方法)
  • 类可以进行 单继承多继承
  • class 关键字后面使用 () 中定义要继承的父类,多个父类用 , 隔开
  • 继承的多个父类有相同的成员,子类获取的成员按照 () 中从左到右的优先级获取,最左侧优先级最高
  • 子类可以重写父类的成员
  • 子类重写父类成员,但是还想访问父类成员
    • 父类名.成员
    • super().成员
  • 子类没有需要添加成员,使用 pass 关键词表示空内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class f_A:
name = "A"
age = 16
def aa(self):
print("aaa")

class f_B:
name = "B"
sex = "男"
def bb(self):
print("bbb")

class z_C(f_A,f_B): # 同时继承 f_A f_B
sex = "女"
def cc(self):
print("ccc")

c = z_C() # 实例化子类对象
print(c.name) # "A" (继承优先级从左到右,左边优先级最高)
print(c.age) # 16
print(c.sex) # "女" (子类重写父类成员)
c.bb() # "bbb"

多态

  • 不同的类中定义相同的方法,这些方法可以根据对象的实际类型来执行不同的操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""
Dog 和 Cat 类都有 make_sound 方法,
所以我们可以将它们的实例传递给 make_animal_sound 函数,
并根据对象的实际类型来执行不同的操作。
这就是多态
"""

class Dog:
def make_sound(self):
print("Woof!")

class Cat:
def make_sound(self):
print("Meow!")

def make_animal_sound(animal):
animal.make_sound()

dog = Dog()
cat = Cat()

make_animal_sound(dog) # Woof!
make_animal_sound(cat) # Meow!

抽象类/抽象方法

  • 抽象方法:没有具体实现的方法 (pass)
  • 包含抽象方法的类就叫抽象方法
  • 多用于做顶层设计,以便子类做具体实现,配合多态实现不同操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Student:
def saodi(self):
pass

class a(Student):
def saodi(self):
print("用扫把")

class b(Student):
def saodi(self):
print("用吸尘器")

def saodi(obj):
obj.saodi()

aa = a()
bb = b()

saodi(aa) # 用扫把
saodi(bb) # 用吸尘器

正则表达式

匹配方式

  1. 引入 re 模块 import re
  2. 调用相关方法进行匹配
    1. re.match
      • 功能:对原字符串的开头进行匹配
      • 参数1:匹配字符(正则)
      • 参数2:原字符串
      • 返回值:如果开头有要匹配的字符,则返回一个match对象,否则返回None
    2. re.search
      • 功能:对原字符串的所有内容进行匹配,返回第一个匹配到的内容
      • 参数1:匹配字符(正则)
      • 参数2:原字符串
      • 返回值:如果匹配到一个字符串,则返回一个match对象,否则返回None
    3. re.findall
      • 功能:对字符串的所有内容进行匹配,返回所有匹配到的内容
      • 参数1:匹配字符(正则)
      • 参数2:原字符串
      • 返回值:
        • 如果匹配到字符串,则返回一个列表
        • 元素为匹配到的每个字符串
        • 否则返回一个空列表
        • (如果匹配字符为正则,且包含分组,则返回值为包含一个元组的列表,元组每个元素为分组匹配到的内容)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import re

string = "pythonabcdefpythonghij"
matobj = re.match("python",string)
matobj.span() # (0, 6) #获取匹配到内容的下标范围(元组:不包括第二个元素)
matobj.group() # python #返回匹配到的内容


string2 = "abcdefpythonghij"
matobj = re.search("python",string2)
matobj.span() # (6, 12) #获取匹配到内容的下标范围(元组:不包括第二个元素)
matobj.group() # python #返回匹配到的内容


string3 = "pythonabcdefpythonghij"
matobj = re.findall("python",string3) # ["python","python"]
string4 = "abcdef"
matobj = re.findall("python",string4) # []

正则规则

re 模块的方法中书写正则,正则是一个字符串,在字符串前带上 r 标识符,表示字符串中 \ 不是转义字符 r"\d"

1
2
3
import re

re.match(r"\d","abcde123")
1
2
3
# 邮箱正则

r"^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$"

元字符匹配

  • .:匹配任意一个字符(除了 \n )\. 表示一个普通的 .
  • []:匹配 [] 中列举的字符
  • \d:匹配数字,即 0-9
  • \D:匹配非数字
  • \s:匹配空白,即 空格 tab键
  • \S:匹配非空白
  • \w:匹配单词字符,即 a-z A-Z 0-9 _
  • \W:匹配非单词字符

数量匹配

  • *:匹配前一个规则的字符出现,0 ~ 无数次
  • +:匹配前一个规则的字符出现,1 ~ 无数次
  • ?:匹配前一个规则的字符出现,0 或 1 次
  • {m}:匹配前一个规则的字符出现,m 次
  • {m,}:匹配前一个规则的字符出现,m ~ 无数次
  • {m,n}:匹配前一个规则的字符出现,m ~ n 次

边界匹配

  • ^:匹配字符串行开头
  • $:匹配字符串行结尾
  • \b:匹配一个单词边界
  • \B:匹配非单词边界

分组匹配

  • |:匹配左右任意一个表达式
  • ():将括号中字符作为一个分组

类型注解

注意事项

  • PyCharm 等开发工具对代码做类型推断协助做代码提示
  • 只是一种文档工具,用于指示变量、函数参数和函数返回值的预期类型
  • 类型注解并不强制执行类型检查,也不会影响程序的运行(即使标记和实际不符也不会报错)

变量类型注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 整数
x: int = 1

# 浮点数
y: float = 1.0

# 布尔值
z: bool = True

# 字符串
s: str = "hello"

# 列表
lst: list = [1,2,3,"a","b"]
lst: list[int] = [1, 2, 3]

# 元组
tup: tuple = (1,"hello",True)
tup: tuple[int, str] = (1, "hello")

# 集合
st: set = {1, 2, 3, "a"}
st: set[int] = {1, 2, 3}

# 字典
dct: dict = {"a": 1, "b": True}
dct: dict[str, int] = {"a": 1, "b": 2}

# 可选类型(可以是int或None)
opt: Optional[int] = None

# 联合类型(可以是int或str)
uni: Union[int, str] = 1

类对象类型注解

1
2
3
4
5
class Student:
pass

# 类对象类型注解
stu: Student = Student()

函数方法类型注解

1
2
3
4
5
def 函数名 ( 形参:类型, 形参:类型, 形参:类型, ... 形参:类型 ) -> 返回值类型:
pass

def Student(name:str, age:int) -> str:
return f"姓名:{name},年龄:{age}"

Union 联合类型注解

  • from typing import Union 引入 Union
  • 表示值是多个类型中的某种类型
1
2
3
from typing import Union

my_list: list[Union[str,int]] = [1,2,"a","b"]

Optional 联合类型注解

  • from typing import Optional 引入 Optional
  • 表示一个值可以是给定类型,也可以是 None
1
2
3
from typing import Optional

my_list: list[Optional[str,int]] = [1,2,"a",None]

注释类型注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 整数
x = 1 # type: int

# 浮点数
y = 1.0 # type: float

# 布尔值
z = True # type: bool

# 元组
tup = (1, "hello") # type: tuple[int, str]

# 集合
st = {1, 2, 3} # type: set

常用函数


判断数据类型

查询的是数据的类型,即使参数是变量也是查看变量存储的数据类型

type(字面量/变量)

返回值为 <class 'type'> 类型的数据


输出

print( ) 函数

向控制台输出内容

  • 参数:end=”” 表示不会换行(默认会换行即 end=”\n”)
1
2
print("xxx","yyy")
print("xxx","yyy",end="")

输入

input( ) 函数

  • 获取键盘输入的数据
  • 获取的数据可以传给变量
  • 可以传入参数,用于在输入前显示提示信息
  • 不管输入任何数据,获取的都是字符串类型
1
2
3
name = input("请输入姓名")

print("输入的姓名:",name)

数字序列

range( ) 函数

传入数字,生成一个由数字组成的序列类型(可迭代对象,而不是列表类型)

  • range(m):0 ~ m-1(默认步长1)
  • range(n,m):n ~ m-1(默认步长1)
  • range(n,m,step):n ~ m-1(每个元素相隔 step)
1
2
3
range(5)  # [0,1,2,3,4]
range(2,5) # [2,3,4]
range(2,10,2) # [2,4,6,8]

返回对象的长度

len( 标准类型 ) 函数

自定义类通过实现 __len__ 方法来让该类的实例支持 len 函数

  • 功能:返回对象的长度
  • 参数1:必须是一个具有 __len__ 方法的标准数据类型,否则抛出异常 (数据容器类型)
    • 字符串:返回字符串中字符的个数
    • 列表:返回列表中元素的个数
    • 元组:返回元组中元素的个数
    • 字典:返回字典中键值对的个数
    • 集合:返回集合中元素的个数

返回最大元素

max( 可迭代对象 ) 函数

  • 功能:返回可迭代对象中最大值的元素
  • 参数1:可迭代对象数据
    • 字符串:返回字符串中的最大字符
    • 列表:返回列表中的最大项
    • 元组:返回元组中的最大项
    • 字典:返回字典中 key 的最大值
    • 集合:返回集合中的最大项

返回最小元素

min( 可迭代对象 ) 函数

  • 功能:返回可迭代对象中最小值的元素
  • 参数1:可迭代对象数据
    • 字符串:返回字符串中的最小字符
    • 列表:返回列表中的最小项
    • 元组:返回元组中的最小项
    • 字典:返回字典中 key 的最小值
    • 集合:返回集合中的最小项

转换为列表对象

list(可迭代对象)

  • 可以创建空列表对象
  • 也可以将其他可迭代对象转换成列表
    • 字符串:字符串每个字符作为列表的一个元素
    • 列表:不变
    • 元组() 换成 []
    • 字典:所有的 key 组成的列表
    • 集合{} 换成 []
1
2
3
4
5
6
7
8
9
10
11
d1 = "abcd"
d2 = [1,2,3,4]
d3 = (1,2,3,4)
d4 = {"key1":1,"key2":2}
d5 = {1,2,3,4}

list(d1) # ["a","b","c","d"]
list(d2) # [1,2,3,4]
list(d3) # [1,2,3,4]
list(d4) # ["key1","key2"]
list(d5) # [1,2,3,4]

转换为元组对象

tuple(可迭代对象)

  • 可以创建空元组对象
  • 也可以将其他可迭代对象转换成元组
    • 字符串:字符串每个字符作为元组的一个元素
    • 列表[] 换成 ()
    • 元组:不变
    • 字典:所有的 key 组成的元组
    • 集合{} 换成 ()
1
2
3
4
5
6
7
8
9
10
11
d1 = "abcd"
d2 = [1,2,3,4]
d3 = (1,2,3,4)
d4 = {"key1":1,"key2":2}
d5 = {1,2,3,4}

tuple(d1) # ("a","b","c","d")
tuple(d2) # (1,2,3,4)
tuple(d3) # (1,2,3,4)
tuple(d4) # ("key1","key2")
tuple(d5) # (1,2,3,4)

指定值转换为字符串

str(可迭代对象)

  • 将其他可迭代对象转换成字符串
    • 字符串:不变
    • 列表[,,,] 的字符串形式
    • 元组(,,,) 的字符串形式
    • 字典{key:value} 的字符串形式
    • 集合{,,,} 的字符串形式
1
2
3
4
5
6
7
8
9
10
11
d1 = "abcd"
d2 = [1,2,3,4]
d3 = (1,2,3,4)
d4 = {"key1":1,"key2":2}
d5 = {1,2,3,4}

str(d1) # '("a","b","c","d")'
str(d2) # '(1,2,3,4)'
str(d3) # '(1,2,3,4)'
str(d4) # '("key1","key2")'
str(d5) # '(1,2,3,4)'

转换为集合对象

set(可迭代对象)

  • 将其他可迭代对象转换成集合(元素将去重)
    • 字符串:字符串每个字符作为集合的一个元素
    • 列表[] 换成 {}
    • 元组() 换成 {}
    • 字典:所有的 key 组成的集合
    • 集合:不变
1
2
3
4
5
6
7
8
9
10
11
d1 = "abcd"
d2 = [1,2,3,4]
d3 = (1,2,3,4)
d4 = {"key1":1,"key2":2}
d5 = {1,2,3,4}

set(d1) # '("a","b","c","d")'
set(d2) # '(1,2,3,4)'
set(d3) # '(1,2,3,4)'
set(d4) # '("key1","key2")'
set(d5) # '(1,2,3,4)'

转换为字典

非键值对数据无法转换成字典,因此其他 数据容器 类型的数据无法转换成字典。如果调用 dict() 转换会报错


排序

sorted(可迭代对象,[reverse=True])

  • 功能:将可迭代对象的元素进行排序。
    • 不修改原数据,生成一个新列表
  • 参数1:可迭代对象数据
    • 字符串:字符串每个字符排序好并作为列表的元素
    • 列表:元素排序好的新列表
    • 元组:元素排序好的新列表
    • 字典:所有的 key 进行排列并作为列表的元素
    • 集合:元素排序好的新列表
  • 参数2:可选项参数。传入 reverse=True 则反向排序
  • 返回值:排序好的新列表
1
2
3
4
5
6
7
8
9
10
11
12
d1 = "dbca"
d2 = [3,4,2,1]
d3 = (3,4,2,1)
d4 = {"key2":1,"key1":2}
d5 = {3,4,2,1}

sorted(d1) # ["a","b","c","d"]
sorted(d2) # [1,2,3,4]
sorted(d3) # [1,2,3,4]
sorted(d4) # ["key1","key2"]
sorted(d5) # [1,2,3,4]
sorted(d5,reverse=True) # [4,3,2,1]

json 转换

  • 导入 json 模块 import json
  • 列表字典json 进行相互转换(两者可以相互嵌套)
  • 在 python 中 json 就是 列表字典 的字符串形式

列表字典 转换成 json

json.dumps(列表|字典,ensure_ascii=false)

  • 如果不设置 ensure_ascii=False 参数,生成的 json 里中文将转换成 ASCII 码
1
2
3
import json
data = [1,3,4,"a","b"]
js = json.dumps(data)

json 转换成 列表字典

json.loads(列表字符串|字典字符串)

1
2
3
import json
data = '{"a":1,"b":2}'
js = json.loads(data)

模块

模块概念

  • 模块就是一个 python 文件,以 .py 结尾
  • 每个模块都可以实现一个功能,可以认为一个模块就是一个工具包

导入

  • 引入模块不需要 .py 后缀
  • 同时导入同名功能,后调用的功能会覆盖前面的功能
  • 当模块导入时,模块中的代码会自动执行
    • 设置模块中指定代码,在导入时不执行但是运行当前模块时执行
      1
      2
      3
      4
      5
      6
      7
      8
      9
      def test(a,b):
      return a+b

      """
      当直接执行当前文件时,if 内代码将会执行。
      当作为模块被引入时,if 内代码将不会执行。
      """
      if __name__ == "__main__":
      test(1,2)
    • 通过 * 导入模块中所有功能时,筛选可以导入的功能
      1
      2
      3
      4
      5
      6
      7
      8
      # 通过 * 导入模块中功能时,只会导入 test_a 功能
      __all__ == ["test_a"]

      def test_a(a,b):
      return a+b

      def test_b(a,b):
      return a*b

[from 模块名] import [ 模块 | 类 | 变量 | 函数 | * ][ as 别名 ]

1
2
3
4
5
6
7
8
9
import 模块名   # 导入整个模块

import 模块名 as 别名 # 导入模块定义别名

from 模块名 import 类, 变量, 方法等 # 导入具体某功能

from 模块名 import * # 导入模块下所有功能

from 模块名 import 功能名 as 别名 # 导入的功能定义别名

使用

1
2
3
4
5
6
7
8
9
10
11
import 模块名
模块名.[ 方法 | 变量 ] # 导入模块-使用

from 模块名 import 功能名
功能名() # 导入功能-使用

import 模块名 as 别名
别名.[ 方法 | 变量 ] # 导入模块-别名-使用

from 模块名 import 功能名 as 别名
别名() # 导入功能-别名-使用

自定义模块

  1. 新建一个 Python 文件
  2. 其他 python 文件直接引入调用即可
1
2
3
4
5
6
7
# test.py
def fn(a,b)
print(a+b)

# test2.py
import test
test.fn(1,2)

包的概念

  • 包就是一个文件夹
  • 包含一个 __init__.py 文件
    • 有这个文件,文件夹就是个包,没有这个文件,文件夹就是个普通文件夹
    • __init__.py 文件内容可以是空,但是此文件必须存在
  • 该文件夹包含多个模块文件,,所以包就是一堆同类型功能模块的集合体

创建包

  1. 右键项目
  2. 新建
  3. Python Package

导入包

  • 导入包其实就是导入包中的模块(模块中功能),与导入模块语法相同,只是在模块前加上包名
  • 通过 * 导入包中所有模块时,筛选可以导入的模块
    1
    2
    3
    4
    5
    6
    """
    在 __init__.py 文件中定义 __all__ 变量
    让通过 * 导入包中所有模块时,筛选可以导入到的模块
    """
    __all__ == ["my_module2"]

1
2
3
4
import 包名.模块名              # 导入包下的指定模块
from 包名 import 模块名 # 导入包下的指定模块
from 包名 import * # 导入包下所有模块
from 包名.模块名 import 功能名 # 导入包下指定模块的功能

第三方包

第三方包概念

  • python 中内置程序 pip 就是包管理器

安装第三方包

  1. 命令:pip install 包名
  2. Pycharm:
    1. Pycharm 右下角 interpreter setting(解析器设置)
    2. 可以看到已安装包
    3. 可以添加删除包

修改网络镜像

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称

判断第三方包是否安装

直接引入包 import 包名称 不报错即为成功安装


多线程

进程、线程概念

  • 进程:
    • 就是一个程序
    • 运行在操作系统上,那么这个程序就称为一个运行进程
  • 线程:
    • 线程是归于进程的
    • 一个进程可以开启多个线程
    • 用于执行不同工作
    • 是进程的实际工作最小单位
  • 内存空间
    • 进程:进程之间有各自的内存空间,相互独立
    • 线程:线程之间是内存共享的
  • 并行执行
    • 指同一时间做不同的工作
    • 多个进程同时运行,称为 多任务并行执行
    • 一个进程中多线程同时运行,称为 多线程并行执行

多线程编程

  1. 引入 threading 模块的 Thread
  2. 通过 Thread 类实例化对象
    • 每个 Thread 对象代表一个线程
    • 实例化对象时,根据传入不同参数设置各线程功能
  3. Thread 对象调用 start() 方法启动线程

实例化对象时构造参数

  • 通过关键词参数进行传递
1
2
3
4
5
6
7
8
9
from threading import Thread

thread_obj1 = Thread([group, [, target [, name [, args [, kwargs]]]]])

- group:暂时无用,未来功能的预留参数
- target:需要执行的回调函数
- args:以元组的方式给回调函数传参(每个元素对应回调函数的一个形参。按照位置进行传参)
- kwargs:以字典的方式给回调函数传参(每个元素的 key 对应回调函数的一个形参,key 和形参名称要一致。按照关键字方式进行传参)
- name:线程名,一般不用设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from threading import Thread
import time

def fn1(param): # 对应元组第一个元素
index = 0
while index < 5:
print(param)
index += 1
time.sleep(1)

def fn2(masg): # 形参标识符等于字典 key 值
index = 0
while index < 5:
print(masg)
index += 1
time.sleep(1)

th1 = Thread(target=fn1, args=("111111",))
th2 = Thread(target=fn2, kwargs={"masg": "222222"})

th1.start()
th2.start()

"""
111111
222222
111111
222222
222222
111111
111111
222222
111111
222222
"""

文件操作

文件操分为三步:

  1. 打开文件
  2. 读取/修改文件
  3. 关闭文件

打开文件

open(name,mode,encoding)

  • 功能:打开指定文件,即获取文件对象,之后就可以对文件对象进行相关操作了
  • 参数 name:字符串 要打开文件的文件路径的,包含文件名和后缀
  • 参数 mode:字符串 设置打开文件的模式(访问模式):只读、写入、追加
    1. r
      • 这是默认模式
      • 只读模式 打开文件
      • 文件指针将在文件开头
    2. w
      • 写入模式 打开文件
      • 如果文件存在则打开文件,原有内容会被删除,指针位于空文件开头
      • 如果文件不存在则根据 name 创建空文件
    3. a
      • 追加模式 打开文件
      • 如果文件存在则打开文件,指针位于文件内容最后位置
      • 如果文件不存在则根据 name 创建空文件
  • 参数 encoding:字符串 编码格式(以什么编码方式打开文件)
    • 此参数位置不是形参第三位,所以必须使用 关键字参数 形式传递实参
  • 返回值:返回文件对象
1
f = open("../../test.txt","r",encoding="UTF-8")

读取文件

注意事项

  • 只能对通过 只读模式 打开的文件内容进行读取
  • 通过文件对象的 read 相关方法读取文件内容
  • 读取的内容包括转义字符换行、空格等
  • 根据指针记录读到位置
    • 通过 read 相关方法读取文件内容,指针会根据读取的内容进行变动。文件对象会记录当前指针所在位置,之后再继续调用 read 相关方法读取文件内容,将从当前位置接着开始

读取方法

所有内容或指定个数字符

文件对象.read(num)

  • 功能:读取文件中的所有数据,或读取文件 num 指定个数的字符
  • 参数1:
    • num:数值 读取文件中 num 指定个数的字符(包括转义字符换行、空格等)
    • 无参:读取文件中的所有内容
  • 返回值:字符串类型的文件内容
1
2
3
4
f = open("test - 副本.txt","r",encoding="UTF-8")
print(f.read()) # 所有内容
print(f.read(3)) # 鹅鹅鹅
print(type(f.read())) # <class 'str'>

读取一行

文件对象.readline()

  • 功能:读取指针当前所在行
  • 返回值:当前行内容的字符串
1
2
3
f = open("test - 副本.txt","r",encoding="UTF-8")
print(f.readline()) # 鹅鹅鹅
print(f.readline()) # 曲项向天歌

每行组成列表

文件对象.readlines()

  • 功能:读取文件中所有行,返回一个列表,列表每个元素就是一行内容
  • 返回值:列表,元素是每一行内容的字符串
1
2
f = open("test - 副本.txt","r",encoding="UTF-8")
print(f.readlines()) # ['鹅鹅鹅\n', '曲项向天歌\n', '白毛浮绿水\n', '红掌拨清波']

循环读取每一行

  • 使用 for 循环语句遍历 文件对象
  • 每执行依次获取的都是一行内容
1
2
3
f = open("test - 副本.txt","r",encoding="UTF-8")
for item in f:
print(item) # 每次打印一行内容

写入文件

  • 文件内容写入,只能操作通过 w(覆盖)a(追加) 模式打开的文件对象
  • 通过 文件对象.write("输入内容") 写入内容
    • 写入的内容只保存再内存的 文件对象 中并没有保存在硬盘
  • 通过 文件对象.flush() 将内存中的数据保存到硬盘中,如果没有调用 flush() 方法,文件内容将不会改变(除了 w 模式,此模式打开文件时候文件内容就被清除了)
    • 可以不调用 flush() 直接调用 文件对象.close() 方法,close() 方法也自带将内存内容保存到硬盘功能
1
2
3
4
f = open("test - 副本.txt","w",encoding="UTF-8")
f.write("hello world") # 文件内容从 “咏鹅” 变成了 “hello world”
f.flush() # 保存到硬盘
f.close() # 关闭文件
1
2
3
f = open("test - 副本.txt","a",encoding="UTF-8")
f.write("hello world") # 文件内容 “咏鹅” 结尾多了一句 “hello world”
f.close() # 保存到硬盘并且关闭文件

关闭文件

注意事项

  • 文件如果不进行关闭将一直处于占用状态
  • 文件对象.close() 自带 文件对象.flush() 功能,将写入模式内存中数据保存到硬盘

手动关闭

文件对象.close()

1
2
3
f = open("test - 副本.txt","r",encoding="UTF-8")
print(f.readlines())
f.close() # 关闭文件

自动关闭

with open(name,mode,encoding) as 变量名:

通过此写法的代码体中进行相关读取操作,当代码体中所有代码执行完毕,将自动关闭文件

  • 变量名:就是打开文件返回的文件对象
1
2
3
4
5
# 当两个读取方式都结束后,自动关闭文件
with open("test - 副本.txt","r",encoding="UTF-8") as f:
print(f.readlines()) # ['鹅鹅鹅\n', '曲项向天歌\n', '白毛浮绿水\n', '红掌拨清波']
for item in f:
print(itme) # 不会打印任何内容,因为上述读取指针已经达到内容尾部

MySQL数据库操作

  1. 安装第三方库 pymysql
    • pip install pymysql
  2. 引入 Connection
  3. 实例化 Connection,获取链接对象(构建到MySql数据库的链接)
  4. 链接对象调用 cursor() 方法获取 游标对象
  5. 链接对象调用 select_db("xxx"),选择数据库
  6. 游标对象调用 execute("xxxx"),执行sql语句
    • 执行了查询语句后,游标对象调用 fetchall() 方法获取到的数据
    • 执行了插入语句后,链接对象调用 commit() 方法提交插入
  7. 链接对象调用 close(),关闭 mysql 链接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pymysql import Connection

# 获取到 mysql 数据库的链接对象
conn = Connection(
host="localhost", # 主机名(IP地址)
port=3306, # 端口号
user="root", # 账户名
password="123456", # 密码
autocommit=True # 设置自动提交(插入数据后不需要手动提交)
)

# 获取游标对象
cursor = conn.cursor()

# 选择数据库
conn.select_db("test") # 选择 test 数据库

# 使用游标对象,执行sql语句
cursor.execute("create table test_pymysql(id int, info varchar(255))") # 创建表 test_pymysql

# 如果执行了【查询】语句,游标对象再执行 fetchall() 方法获取查询数据
cursor.execute("select * from student")
results = cursor.fetchall() # 以元组形式返回查询的数据

# 如果执行了【插入】语句,链接对象再执行 commit() 方法提交插入
cursor.execute("insert into student values(10001, '周杰伦', 31, '男')") # 插入数据
conn.commit() # 提交数据

# 关闭数据库链接
conn.close()