Python笔记

Alt+a微信截图 Ctrl+Alt+aQQ截屏 Win+shift+s电脑截屏

脚本开发

通过代码程序自动完成

基础语法

内置函数(方法)

python中已经存在的函数

max()
min()
len()
sorted()  # 临时排序,不操作源数据,内置参数reverse = False

变量

  • 变量区分大小写
  • 由字母、数字下划线组成,数字不能开头
  • 内置函数和关键字不能作为变量名
  • 紫色的是内置函数,黄色的内置函数
  • python3之后可以用中文表示变量名,但是不规范

>>>

默认的python提示符,往往会显示于能以交互方式在解释器里执行的样例代码之前。

...

输入特殊代码时默认的 Python 提示符,特殊代码包括缩进的代码块,左右成对分隔符(圆括号、方括号、花括号或三重引号等)之内,或是在指定一个装饰器之后。

字面量

在代码中,被写下来的的固定的值,称之为字面量

注:type()语句可以查看变量存储的数据类型

注释

行注释:以 # 开头,直到该物理行结束。注释可以在行开头,或空白符与代码之后,但不能在字符串里面。字符串中的 # 号就是 # 号。
多行注释:以一对三个双引号引起来""" """
单词多行注释:Alt+#(pc用Ctrl+/)

数据转换

语句(函数) 说明
int(x) 将x转换为一个整数
float(x) 将x转换为一个浮点数
str(x) 将对象 x 转换为字符串
  • 类型转换使用相应类型的内置函数即可
  • 整型和浮点型不为0时转为bool都为True
  • 字符串只要不为空转为bool都为True
  • 字符串转整型字符串元素必须是整型,转浮点型字符串整型浮点型都可以

python对象

  • 身份:对象的唯一标识,可使用内建函数id()得到
  • 类型:对象类型决定对象操作,使用type()函数
    • print(type())输出:<class '???'>
  • 值:对象的数据值,若对象支持更新操作,则可修改

类型

  • 标准类型:整型、布尔型(True==1)、长整型、浮点型、复数型、字符串、列表、元组(前五种属于数值类型)
  • 其他内建类型:类型、Null对象(None)、文件、集合/固定集合、函数/方法、模块、类

布尔值是False

None、False、所有值为0的数、0、0.0、0.0+0.0j(复数)、""(空字符串)、[](空列表)、()(空元组)

模型

  • 存储模型
  • 更新模型
  • 访问模型:直接存取(对于非容器类型)、顺序(字符串、列表、元组)和映射(字典)

python用作计算器

  • 解释器像一个简单的计算器:你可以输入一个表达式,它将给出结果值。 表达式语法很直观:运算符 +, -, * 和 / 可被用来执行算术运算;圆括号 (()) 可被用来进行分组。
>>>2 + 2
4
>>>50 - 5*6
20
>>>(50 - 5*6) / 4
5.0
>>>8 / 5  # 除法运算总是返回一个浮点数
1.6
  • 除法运算(/)总是返回浮点数。 如果要做 floor division (向下取整除法)得到一个整数结果你可以使用 // 运算符;要计算余数你可以使用%
  • Python 用 ** 运算符计算乘方:2 ** 7 #2的7次方
    • 幂运算的优先级高于乘除
  • 如果变量未定义(即,未赋值),使用该变量会提示错误
  • Python 全面支持浮点数;混合类型运算数的运算会把整数转换为浮点数
  • 交互模式下,上次输出的表达式会赋给变量_。最好把该变量当作只读类型。不要为它显式赋值,否则会创建一个同名独立局部变量,该变量会用它的魔法行为屏蔽内置变量。
  • 复合赋值运算符:+= -= /= *= %= **= //=
高精度模块(需要导入)
  • import decimal或者from decimal import Decimal
  • 使用:num = decimal.Decimal(''或str())
  • 或者:num = Decimal('')/Decimal('')
    • 必须使用字符串

字符串

  • 可以用成对的单引号('')或双引号("")标示
  • 要标示引号等特殊符号,需要用到转义字符,加一个\
  • 这两种引号唯一的区别是,不需要在单引号里转义双引号 " (但此时必须把单引号转义成 ' ),反之亦然
  • 如果不希望前置 \ 的字符转义成特殊字符,可以使用原始字符串,在引号前添加 r 即可
    • print('C:\some\name')->print(r'C:\some\name')
    • 原始字符串还有一个微妙的限制:一个原始字符串不能以奇数个 \ 字符结束
  • 字符串文字可以跨越多行。一种方法是使用三重引号:"""..."""'''...''' 。行尾会自动包含在字符串中,但可以通过在行尾添加 \ 来避免这种情况。( 即首尾都会有换行符)在下面的示例中,不包含首行换行符
print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")
  • 字符串可以用+合并(粘到一起,只能拼接字符串),也可以用*重复
  • 相邻的两个或多个 字符串字面值 (引号标注的字符)会自动合并。如'py''thon'->'python'
    • 拼接分隔开的长字符串时,这个功能特别实用
    • 不能用于变量或表达式
  • 字符串支持== 索引 ==(下标访问),第一个字符的索引是 0。单字符没有专用的类型,就是长度为一的字符串
    • 索引还支持负数,用负数索引时,从右边开始计数
    • 注意,-0 和 0 一样,因此,负数索引从 -1 开始
  • 除了索引操作,还支持切片。 索引用来获取单个字符,而切片允许你获取子字符串
    • 例如:word[0:2] # 从 0 号位 (含) 到 2 号位 (不含) 的字符
    • 切片索引的默认值很有用;省略开始索引时,默认值为 0,省略结束索引时,默认为到字符串的结尾。如:`word[:2] word[4:]
    • 注意,输出结果包含切片开始,但不包含切片结束。因此,s[:i] + s[i:]总是等于s
    • 索引越界会报错,但是,切片会自动处理越界索引
    • 也可以通过负数位置从右到左进行切片,注意此时·步长一定要为负数
    • Python 字符串不能修改,是 immutable 的。因此,为字符串中某个索引位置赋值会报错
    • 切片还有第三个参数步长,例如:`li[1:4:2]
  • 内置函数 len() 返回字符串的长度
    • s = 'supercalifragilisticexpialidocious' len(s)
字符串格式化

通过%s占位符,完成字符串和变量的快速拼接(和c差不多),%s不只是字符串能用,整数和浮点数类型也能用,除此之外还有$d和%f

格式化的精度控制
  • 可以使用辅助符号"m.n"来控制数据的宽度和精度
    • m,控制宽度,要求是数字,如果设置的宽度小于数字自身,则不生效
    • .n,控制小数点精度,要求是数字,会进行小数的四舍五入
字符串快速格式化(fomat拼接法)

语法:

  1. f"内容{变量:[][][]}"的格式来快速格式化(简写法)
  2. "{:[填充][长度][格式][%](有百分号会以百分号形式输出)}xxx{}xxx{}xxx".format([填充][长度][格式](没有冒号可以不写)name(0位置),sex(1位置),age(2位置))大括号中放空则按顺序,也可填数字,数字与变量的位置对应
    注:这种写法不做精度控制,不理会类型
{:^(居中对齐)}.format
{:<10(左对齐)}.format
{:*>10(右对齐)}.format

join拼接(只能拼接字符串)

例如:test="****".join([name,sex,age])

  • 每两个变量之间都会有一个****,不是说有逗号就有比如[n1,n1,]
  • 列表与字符串的相互转换
# 列表转换为字符串
li1 = ['a','b','c']
st1 = ''.jion(li)
# 字符串转换列表
st2 = 'abc'
li2 = list(st2)
# 不能用str()将列表转换为字符串的原因:
li3 = ['a','b','c']
st3 = str(li3)  print(st3)
>>>   "['a','b','c']" 

数据输入

  • 使用input()语句可以从键盘获取输入,该函数永远返回字符串类型
  • 注:无论键盘输入什么类型的数据,获取到的数据永远都是字符串类型或数字类型,记得进行类型转换

逻辑运算

->表示输出结果

print(5>3)-># True
print(5<3)-># False
# and 关键字
print(5>3 and 5<3)-># False
# 逻辑短路
print(5<3 and "hello"+5)# and后面这段有问题,但由于5<3条件已经判断为否,计算机不会再看后面,所以不会报错
# or 关键字的逻辑短路
print(5==5 or "hello"+5)
# not 关键字:取反
# 例如结果为True取反后为False
print(not True)-># False
print(not 5<3)-> # True

多重赋值与循环体缩进

# 斐波那契数列:
# 前两项之和即下一项的值
a, b = 0, 1
#变量 a 和 b 同时获得新值 0 和 1 。
while a < 10:
    print(a)
    a, b = b, a+b
    #缩进是 Python 组织语句的方式。在交互式命令行里,得为每个缩进的行输入空格(或制表符)。使用文本编辑器可以实现更复杂的输入方式;所有像样的文本编辑器都支持自动缩进。交互式输入复合语句时,要在最后输入空白行表示完成(因为解析器不知道哪一行代码是代码块的最后一行)。注意,同一块语句的每一行的缩进相同。
    # 四个空格或一个tab键

i = 256*256
print('The value of i is', i)
The value of i is 65536

a, b = 0, 1
while a < 1000:
    print(a, end=',')
    a, b = b, a+b
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,

注:

  • print()输出的字符串不带引号
  • **- 的优先级更高, 所以 -3**2 会被解释成 -(3**2)

print()语句

print(a, end=',')
print("*****",end="\n")等价于print("*****")
print(a,b)# a和b打印在同一行,且二者之间会有一个空格
# 原因:print()默认存在sep(分隔符)参数和end(结束符)参数,即:
print(sep=' ',end='\n')
# sep和end都要更改的时候end一定要在sep后面
# 同时要打印的数据必须在sep和end的前面

默认print语句输出内容会自动换行,关键字参数 end 可以取消输出后面的换行(end=""), 或用另一个字符串结尾

控制流工具

while语句

if语句

  • 归属于if判断的代码语句块,需在前方填充4个空格缩进
  • Python通过缩进判断代码块的归属关系。
x = int(input("Please enter an integer: "))

if x < 0:
    x = 0
    print('Negative changed to zero')
elif x == 0:
    print('Zero')
elif x == 1:
    print('Single')
else:
    print('More')
三目运算
# 条件为真时执行 if 条件判断 else 条件为假时执行
print("ok") if True else print("no")

# 三目运算表示多重判断
print("100") if score==100 else print("90") if score>=90 else print("80") if score>=80 else print("0") 
# 真1 if 条件判断1 else 真2 if 条件判断2 else ...

for语句

Python 的 for 语句与 C 或 Pascal 中的不同。Python 的 for 语句不迭代算术递增数值,或是给予用户定义迭代步骤和结束条件的能力(如 C),而是在列表或字符串等任意序列的元素上迭代,按它们在序列中出现的顺序

  • 例如
for xxx in 可迭代对象
# 循环次数根据可迭代对象的长度有关
# 度量一些字符串:
words = ['cat', 'window', 'defenestrate']
for w in words:
    print(w, len(w))
  • for 循环遍历列表中的每个元素,将其赋值给变量 w。
  • w 是一个变量,它持有一个指向字符串对象的引用。(相当于指针)在循环中,w 的值(即它所指向的字符串对象)并没有被改变,而是 w 本身这个变量的引用被改变了,指向了列表中的下一个字符串对象。
  • 变量 w 只是改变了它所指向的内存地址,即指向了列表中的下一个字符串对象。这就是为什么尽管字符串是不可变的,w 的值(即它所指向的字符串)在循环中看起来像是被改变了,实际上只是 w 这个变量的引用在改变。实际上就是字符串没改变变量改变了
  • 很难正确地在迭代多项集的同时修改多项集的内容。更简单的方法是迭代多项集的副本或者创建新的多项集
  • 例如:
# 创建示例多项集
users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}

# 策略:迭代一个副本
for user, status in users.copy().items():
    if status == 'inactive':
        del users[user]

# 策略:创建一个新多项集
active_users = {}
for user, status in users.items():
    if status == 'active':
        active_users[user] = status
循环语句使用

循环次数已知用for循环,未知用while循环

range()函数

  • 内置函数 range() 用于生成等差数列,这是个范围函数
  • 生成的序列绝不会包括给定的终止值;range(10) 生成 10 个值——长度为 10 的序列的所有合法索引。range 可以不从 0 开始,且可以按给定的步长递增(即使是负数步长)
for i in range(5):
    print(i)
0
1
2
3
4

list(range(5, 10))
[5, 6, 7, 8, 9]
list(range(0, 10, 3))
[0, 3, 6, 9]
list(range(-10, -100, -30))
[-10, -40, -70]
  • 要按索引迭代序列,可以组合使用 range() 和 len():
a = ['Mary', 'had', 'a', 'little', 'lamb']
for i in range(len(a)):
    print(i, a[i])
  • 也可以使用enumerate()函数
    • enumerate() 返回的迭代器的 next() 方法返回一个元组,里面包含一个计数值(从 start 开始,默认为 0)和通过迭代 iterable 获得的值。
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
  • range() 返回的对象在很多方面和列表的行为一样,但其实它和列表不一样。该对象只有在被迭代时才一个一个地返回所期望的列表项,并没有真正生成过一个含有全部项的列表,从而节省了空间
  • 这种对象称为可迭代对象 iterable,适合作为需要获取一系列值的函数或程序构件的参数。for 语句就是这样的程序构件;以可迭代对象作为参数的函数例如 sum()如sum(range(10))

break 和 continue 语句

  • break 语句将跳出最近的一层 for 或 while 循环
  • continue 语句将跳出当次循环,直接进入下一循环判断

循环的 else 子句

  • 在 for 或 while 循环中 break 语句可能对应一个 else 子句。 如果循环在未执行 break 的情况下结束,else 子句将会执行。
  • 在 for 循环中,else 子句会在循环结束其他最后一次迭代之后,即未执行 break 的情况下被执行。
  • 在 while 循环中,它会在循环条件变为假值后执行。
  • 在这两类循环中,当在循环被 break 终结时 else 子句 不会 被执行。 当然,其他提前结束循环的方式,如 return 或是引发异常,也会跳过 else 子句的执行。
for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, 'equals', x, '*', n//x)
            break
    else:
        # 循环到底未找到一个因数
        print(n, 'is a prime number')

pass语句

#pass 语句不执行任何动作。语法上需要一个语句,但程序毋需执行任何动作时,可以使用该语句
while True:
    pass  # 无限等待键盘中断 (Ctrl+C)

#常用于创建一个最小的类
class MyEmptyClass:
    pass

#pass 还可用作函数或条件语句体的占位符,让你保持在更抽象的层次进行思考。pass 会被默默地忽略
def initlog(*args):
    pass   # 记得实现这个!

match语句

match 语句接受一个表达式并把它的值与一个或多个 case 块给出的一系列模式进行比较。这表面上像 C、Java 或 JavaScript(以及许多其他程序设计语言)中的 switch 语句,但其实它更像 Rust 或 Haskell 中的模式匹配。只有第一个匹配的模式会被执行,并且它还可以提取值的组成部分(序列的元素或对象的属性)赋给变量。

  • 最简单的形式是将一个主语值与一个或多个字面值进行比较
def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"
  • 注意最后一个代码块:“变量名”_被作为 通配符 并必定会匹配成功。如果没有 case 匹配成功,则不会执行任何分支。
  • 可以用 | (“或”)将多个字面值组合到一个模式中
case 401 | 403 | 404:
    return "Not allowed"
  • 使用 global关键字 可以在函数内部声明变量为全局变量

python数据容器

一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素。 每一个元素,可以是任意类型的数据

list(列表)

  • Python 支持多种复合数据类型,可将不同值组合在一起。最常用的列表是用方括号标注,逗号分隔的一组值。列表可以包含不同类型的元素,但一般情况下,各个元素的类型相同
  • 列表还支持合并操作
  • 列表是 mutable 类型,其内容可以改变,容纳上限2**63-1
  • Python 中的简单赋值绝不会复制数据。 当你将一个列表赋值给一个变量时,该变量将引用现有的列表。你通过一个变量对列表所做的任何更改都会被引用它的所有其他变量看到。
使用方式 作用
list.append(元素) 向列表的尾部追加一个元素
list.extend(容器) 向数据容器的内容(无结构)依次取出,追加到列表尾部,简单来说就是向列表添加多个元素
list.insert(下标,元素) 在指定下标处,插入指定的元素
del list[下标] 删除列表指定下标元素
list.pop(下标) 删除列表指定下标元素(能得到返回值)(默认删除最后一个元素
list.remove(元素) 从前向后,删除此元素第一个匹配项
list.clear() 清空列表
list.count(元素) 统计此元素在列表中出现的次数
list.index(元素) 查找指定元素在列表的下标,找不到报错ValueError
len(列表) 统计容器内有多少元素
list.copy(列表) 生成一个新列表,但列表元素完全一致
list.sort() 排序,默认排正序,对源列表进行改动,没有返回值。排倒序:list.sort(reverse=True)
sorted(列表) 排序,默认排正序,有返回值,能用变量接收,不会对源列表进行改变。排倒序:sorted(列表,reverse=True)
list.reverse() 反转列表,没有返回值,对源列表进行改动

例如:

# 字面量
[元素1,元素2,...]

# 定义变量
squares(变量名称) = [1, 4, 9, 16, 25]
squares
[1, 4, 9, 16, 25]

# 定义空列表
变量名称 = []
变量名称 = list()

squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

sqares.append(216)
sqares
[1,4,9,16,25,216]

rgb = ["Red", "Green", "Blue"]
rgba = rgb
id(rgb) == id(rgba)  # 它们指向同一个对象
  • 切片操作返回包含请求元素的新列表。以下切片操作会返回列表的浅拷贝
correct_rgba = rgba[:]
correct_rgba[-1] = "Alpha"
correct_rgba
["Red", "Green", "Blue", "Alpha"]
rgba
["Red", "Green", "Blue", "Alph"]
  • 为切片赋值可以改变列表大小,甚至清空整个列表
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
# 替换一些值
letters[2:5] = ['C', 'D', 'E']
letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
# 现在移除它们
letters[2:5] = []
letters
['a', 'b', 'f', 'g']
# 通过用一个空列表替代所有元素来清空列表
letters[:] = []
letters
[]
* 为切片赋值可以改变列表大小,甚至清空整个列表
  • 内置函数 len() 也支持列表
  • 可以嵌套列表(创建包含其他列表的列表)
a = ['a', 'b', 'c']
n = [1, 2, 3]
x = [a, n]
x
[['a', 'b', 'c'], [1, 2, 3]]
x[0]
['a', 'b', 'c']
x[0][1]
'b'
列表的复制
  • list.copy()函数进行复制,生成一个新列表,但列表元素完全一致
li1 = ['a','b','c']
li2 = li.copy()
# 查看两个列表的身份标签看是不是同一个列表
print(id(li1),id(li2))
# 发现两个列表的身份标签不同
列表推导式
li = []
for i in range(1,101)
    li.append(i)
# 相当于下面的代码
li = [i for i in range(1,101)]
# 变成字符串类型
li = [str(i) for i in range(1,101)]
浅层复制与深层复制(还没搞懂)
  • 浅层复制:构造一个新的复合对象,然后(在尽可能的范围内)将原始对象中找到的对象的引用 插入其中
  • 深层复制:构造一个新的复合对象,然后,递归地将在原始对象里找到的对象的副本插入其中
  • 赋值指向的是同一个内存id

tuple(元组)

  • 元组支持下标索引 和切片
  • 基本语法:
# 定义元组字面量
(元素,元素,.......,元素)
# 定义元组变量
变量名称 = (元素,元素,.......,元素)
# 定义空元组
变量名称 = ()
变量名称 = tuple()
# 定义一个元素的元组:注意:此时必须带有逗号,否则不是元组类型
x = ('Hello', )
  • 元组的方法:
方法 作用
index() 查找某个数据,如果数据存在返回对应的下标,否则报错
count() 统计某个数据在当前元组出现的次数
len(元组) 统计元组内元素个数
  • 元组特点
# 不可以修改元组内容,否则会报错
t1 = (1,2,3)
t1[0] = 5
#可以修改元组内list的内容(修改元素、增加、删除、反转等)
t1 = (1,2,['ijia','asda'])
t1[2][1] = 'best'
# 元组转列表
li = list(t1)
# 元组拆包:
tu = ('this','that',5,True,[5,6,7])
a,b,c,d,e = tu
>>>a = 'this'
>>>b = 'that'
>>>c = 5
>>>d = that
>>>e = [5,6,7]
a,*b,c=tu
>>>a = 'this' b =['that',5,True] c=[5,6,7]
# 只能有一个*号,标注*的变量接收剩下所有的元素并组成一个列表

字符串

  • 字符串容器可以容纳的类型是单一的,只能是字符串类型
  • 字符串不可以修改,如果必须要修改,只能得到一个新的字符串,旧的字符串是无法修改
  • 字符串的方法
操作 说明
str[] 根据下标索引取出特定位置字符
str.index(str[,下标]) 默认查找给定字符的第一个匹配项的下标,第二个参数指定从第几个下标开始查询,元素不存在会报错
str.find(str[,下标]) 效果和参数与index方法相同,但元素如果不存在不会报错,而是返回-1
str.replace(str1,str2[,整数]) 将字符串内的全部字符串1,替换为字符串2。不会修改源字符串,而是得到一个新的,第三个参数表示str1被替换的个数,默认全部替换
str.split(str1) 切割,按照给定字符串str1,对字符串进行分隔。不会修改源字符串,而是得到一个新的列表,str1不会在这个列表中
str.strip() 或 str.strip(str) 移除首尾的空格和换行符或指定字符串。lstrip替换首部的,rstrip()替换尾部的
str.count(str) 统计字符串内某字符串的出现次数
len(str) 统计字符串的字符个数
str.upper() 转为大写
str.lower() 转为小写
str.swapcase() 大小写相互转换
str.isalpha() 判断方法,如果是纯字母返回True,否则返回False
str.isupper() 判断纯大写
str.islower() 判断纯小写
str.isdigit() 判断纯数字

注:字符串比较是相同位置一个元素一个元素比,如果比较出来就直接出结果

转义的深入
  • 通过一个反斜杠可以进行转义
  • 两个反斜杠可以取消转义
  • 也可以用r""取消转义
  • \b:删除符 \t:水平制表符
# r示例
print(r"this\nisthat")
# 同时使用快速格式化和取消转义
print(fr"xxxxxx")

序列的切片

  • 序列是指:内容连续、有序,可使用下标索引的一类数据容器
  • 列表、元组、字符串,均可以可以视为序列
  • 语法:序列[起始下标:结束下标:步长]
    • 表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列
    • 起始下标表示从何处开始,可以留空,留空视作从头开始
    • 结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
    • 步长表示,依次取元素的间隔
    • 步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)
  • 上面的列表有展示

set(集合)

  • 语法:
# 定义集合字面量
{element,element,......,element}
# 定义集合变量
变量名称 = {element,element,......,element}
# 定义空集合
变量名称 = set()
  • 集合的方法
操作 说明
set.add(element) 集合内添加一个元素
set.update({xxx,xxx}) 向集合内添加多个元素,放在集合中
set.remove(element) 移除集合内指定的元素
set.pop() 只能为空,从集合中默认删除第一个元素
del set 删除集合
set.clear() 将集合清空
set1 & set2 得到一个新集合,内含2个集合的交集
`set1 set2`
set1 - set2 得到一个新集合,内含2个集合的set1对于set2差集
set1.difference(set2) 得到一个新集合,内含2个集合的差集,原有的2个集合内容不变
set1.difference_update(set2) 在集合1中,删除集合2中存在的元素,集合1被修改,集合2不变
set1.union(set2) 得到1个新集合,内含2个集合的全部元素,原有的2个集合内容不变
len(set) 得到一个整数,记录了集合的元素数量
  • 集合特点:相较于列表、元组、字符串来说,不支持元素的重复(自带去重功能,元素具有唯一性)、并且内容无序(即输出无序)
  • 数据不能为可变类型的数据(列表、元组、字典)

dict(字典)

  • 语法:
# 定义字典字面量
{key:value, key:value, ...... ,key:value}
# 定义字典变量
my_dict = {'key':value, key:value, ...... ,key:value}  # key是任何一种数据类型,不是变量
my_dict = {key = value}  # key是变量
# 定义空字典
my_dict = {}
my_dict = dict()
  • 字典的方法
操作 说明
dict[key] 获取指定Key对应的Value值
dict[key] = value 添加或更新键值对
dict.get(key[,xxx]) 获取指定Key对应的Value值,如果键不存在就会报错,第二个参数是提示信息,如果填写了此时键不存在就不会报错,而是返回提示信息
dict.setdefault(key[,value]) 获取指定Key对应的Value值,如果不存在则返回None,如果填写了第二个参数则会在该字典中新增该键值对,并返回该键对应的值
dict.update({key:value[,key:value[,......]]}) 有则修改,无则新增
dict.pop(key) 取出Key对应的Value并在字典内删除此Key的键值对
dict.popitem() 默认从结尾删除
dict.clear() 清空字典
dict.copy() 生成一个新字典,但元素完全一样
dict.keys() 获取字典的全部Key,可用于for循环遍历字典
dict.valus() 获取字典的全部值
dict.items() 获取字典的所有键值对,键值对以元组的形式表现
len(dict) 计算字典内的元素数量
  • 字典特点
    • 键值对的Key和Value可以是任意类型(Key不可为字典)
    • 字典内Key不允许重复,重复添加等同于覆盖原有数据,即键是唯一的,且键不可变
    • 字典不可用下标索引,而是通过Key检索Value
    • 键值对以元组的方法表示

数据容器的通用操作

列表 元组 字符串 集合 字典
元素数量 支持多个 支持多个 支持多个 支持多个 支持多个
元素类型 任意 任意 仅字符 任意 Key:Value
Key:除字典外任意类型
Value:任意类型
下标索引 支持(序列类型) 支持 支持 不支持 不支持(散列类型)
重复元素 支持 支持 支持 不支持 不支持
可修改性 支持 不支持 不支持 支持 支持
数据有序
使用场景 可修改、可重复的一批数据记录场景 不可修改、可重复的一批数据记录场景 一串字符的记录场景 不可重复的数据记录场景 以Key检索Value的数据记录场景

容器通用功能:

功能 描述
通用for循环 遍历容器(字典是遍历key)
max() 容器内最大元素
min() 容器内最小元素
len() 容器元素个数
list() 转换为列表
tuple() 转换为元组
str() 转换为字符串
set() 转换为集合
sorted(序列,[reverse=Ture]) 排序,reverse=True表示降序
得到一个排好序的列表

函数简介

函数的定义:

# 函数封装/函数定义
def 函数名(传入参数)
    函数体
    return 返回值
def xxx()
    pass
    # pass 语句不执行任何动作。语法上需要一个语句,但程序毋需执行任何动作时,可以使用该语句,用于保证语法结构

注:如果函数没有使用return语句返回数据,会返回None这个字面量;在if判断中,None等同于False;定义变量,但暂时不需要变量有具体值,可以用None来代替

函数进阶

函数多返回值

def test_return():
    return 1,2 # return关键字还可以用于结束函数

x, y = test_return()
print(x)  print(y)
# 按照返回值的顺序,写对应顺序的多个变量接收即可 变量之间用逗号隔开

函数多种传参方式

位置参数

调用时根据函数定义的参数位置传参,传递的参数与定义的参数顺序和个数必须一致

def user_info(name,age,gender):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')

user_info('Tom',20,'男')
关键字参数

函数调用时通过“键=值”形式传递参数

def user_info(name,age,gender):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')

# 关键字传参:可以不按照固定顺序
user_info(age=20,gender='男',name='Tom')
# 可以和位置参数混用,位置参数必须在前,且匹配参数顺序
user_info('小明',age=20,gender='男')
缺省参数
  • 缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值
  • 函数调用时,如果为缺省参数传值则修改默认参数值, 否则使用这个默认值
    注:所有位置参数必须出现在默认参数前,包括函数定义和调用
def user_info(name,age,gender='男'):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')

uesr_info('Tom',20)
uner_info('Tom',18,'女')
不定长参数
  • 不定长参数也叫可变参数. 用于不确定调用的时候会传递多少个参数(不传参也可以)的场景
  • 不定长参数只能有一个
    不定长参数的类型:
    1、位置传递(元组不定长)
def user_info(*args)
    print(args)
# 传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
user_info('Tom')# ('Tom',)
user_info('Tom',18)# ('Tom',18)

2、关键字传递(字典不定长)

def user_info(**kwargs)
    print(kwargs)
# 参数是“键=值”形式的形式的情况下, 所有的“键=值”都会被kwargs接受, 同时会根据“键=值”组成字典
user_info(name='Tom',age=18,id=110)# {'name':'Tom','age':18,'id':110}

参数顺序

必备参数-->默认参数-->不定长元组-->不定长字典

def fun(x,y,m = 5,*args,**kwargs)
    pass
# 在前面三个参数都有输入的情况下再以键值对输入才能传输到kwargs不定长字典参数中

函数拆包(简化参数输入)

def fun(x,y,m = 5,*args,**kwargs)
    pass
tu = ("123",True,{"name":"xiaozhang"})
dic = {"name":xw,"sex":"nan"}
fun([1,2,3],"hello",999,*tu,**dic)

函数作用域

  • 分为全局变量、局部变量
  • 函数内部可以调用函数外部的变量,但不能修改,除非使用global关键字声明全局变量
  • 函数外部外部不能调用函数内部的变量,除非使用global关键字声明全局变量
  • 函数可以嵌套函数
  • nonlocal关键字:以该关键字声明变量可以修改外层函数内定义的局部变量,如果有多层需要每层进行一次声明

函数闭包

def fun:
    pass
# 调用函数
x = fun  # fun=x 函数本身
print(x)
>>><function fun at 0x......(函数的id标签)>
# at前面的内容就是当前函数体本身
x()  # 作用相当于fun()
# 闭包:外层函数返回内层函数的函数体
def fun1():
    def fun2():
        pass
    return fun2
f = fun1()  # f = fun2
# f() = fun2()

匿名函数

  • 函数的定义中
    • def关键字,可以定义带有名称的函数
    • lambda关键字,可以定义匿名函数(无名称)
      • 语法:lambda 传入参数:函数体(一行代码,也是返回的内容)
      • 传入参数表示匿名函数的形式参数,如lambda x,y:...表示接收两个形式参数
      • 函数体是函数的执行逻辑,只能写一行,无法写多行
  • 有名称的函数,可以基于名称重复使用。 无名称的匿名函数,只可临时使用一次
    使用示例:
def test(com):
    re=com(1,2)
    print(re)
test(lambda x,y:x+y)
# 或
test1 = lambda x,y:x+y
print(test(7,9))
map()函数
def fun():
    return x*10
li = [1,2,3,4]
map(fun,li) # 把列表里的每个元素依次传入fun函数作为参数值
# 若使用匿名函数简化
map(lambda x:x*10,li)
# filter()函数和map()函数使用方法和作用相同

函数递归

  • 函数调用自身,函数必须有出口
def fun(x):
    if x==1:
        return 1
    return x + fun=(x-1)

python文件操作

文件读取(使用时记得打开文件)

mode常用的三种基础访问模式:

模式 描述
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
操作 功能
文件对象 = open("file(文件路径)"," mode(状态参数)",encoding="xxx") 打开文件获得文件对象。
文件对象.read(num) 读取指定长度字节。不指定num读取文件全部,返回字符串
文件对象.readline() 读取一行,返回字符串
文件对象.readlines() 读取全部行,返回列表,每行一个元素
文件对象.write() 写入文件内容,写入字符串数据
文件对象.writelines() 写入文件内容,写入列表数据
文件对象.flush() 刷新保存
文件对象.close() 关闭保存
文件对象.seek(num) 调整位置,num的值为光标位置,从0开始
文件对象.tell() 查看光标位置
for line in 文件对象 for循环文件行,一次循环得到一行数据
with open() as f 通过with open语法打开文件,可以自动关闭

文件写入

# 打开文件
f = open('python.txt','w') 
# f 表示操作的文件本身,即文件对象
print(f)  # 查看
# 文件写入
f.wirte('Hello World') # 需要保存操作
# 文件读取
print(f.read())
# 内容刷新
f.flush
  • 直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
  • 当调用flush的时候,内容会真正写入文件
  • 这样做会频繁的操作硬盘,导致效率下降

文件路径

  • 绝对路径:从磁盘出发找文件,使用记得+r取消反斜杠转义实战开发使用较少
  • 相对路径:
    • 同层级:在相同文件夹中,直接(./文件名 or 文件名)
    • 上一级:每一级使用一次../,然后选择文件夹
    • 下一级:文件夹/
    • 通常上一级和下一级结合起来使用

文件的状态参数

  • r:读取权限,默认模式
  • w:写入权限,如果不存在这个文件就会创建该文件,且为清空后写入
  • a:写入权限,如果不存在这个文件就会创建该文件,为追加写入不会清空文件内容
  • +:辅助功能,r+/w+/a+表示既读又写
  • b:二进制文件操作,用于操作图片、视频、音乐等字节文件(以记事本打开是乱码),r、w、a用于操作字符文件
# 读取时光标从开头开始
f = open("test.txt","r+") # text.txt内容为123456789,会发生替换
f.write("hello")
f.flush()# 此时text.txt内容为hello6789
print(f.read())
>>>6789  # 因为光标此时在o后面
# 此时可以用seek()函数调整光标位置
# b状态参数示例
import requests  # 导入模拟浏览器的模块,里面有方法可以模拟浏览器发送请求
res = requests.get("URL")  # 发送GET请求
# res为请求得到的状态码如200/404  <Response [200]>
print(res.content)  # res.content:字节文件的二进制数据
f = open("test.mp4",'wb')
f.write(res.content)
f.close()
# 此时就获得了一个可观看的mp4文件,前提是URL指向的是这样的一个视频文件

文件的编码格式

  • utf8:万国码

文件夹操作

  • 需要导入os模块
# 创建文件夹
os.mkdir("xxx(文件夹名)")  # 如果文件夹已经存在,则会报错
# 删除文件夹
os.redir("2024(文件夹名)")  # 如果文件夹不存在也会报错
# 修改文件名(文件夹名)
os.rename("旧文件(夹)名","新文件(夹)名")
# 删除文件
os.remove("文件名")
# 路径拼接,也可以用字符串拼接
os.path.jion("文件夹名","文件名")  # 返回:文件夹名\文件名
# 查看当前文件路径
os.getcwd()
# 修改文件路径,注意,修改后操作都是在修改后的文件路径进行
os.chdir(path="(比如)../")
# 查看当前文件夹下的所有文件
os.listdir()  # 返回列表

成员运算符

  • in和``not in`,判断存在或不存在
li = [1,2,3,4]
print(3 in li)  # 返回True
print(3 not in li)  # 返回False

身份运算符

  • isis not
  • 比较的是id
a = 5
b = 5
print(a is b)
print(a is not b)

文件流与字节流

  • 文件流与字节流都是在内存中直接操作文件
  • 需要快速处理的时候使用
# 文件流
import io  # 创建临时文件
f = io.StringIO  # 创建临时字符文件
f.write('hello')
print(f.getvalue)  # 获得文件内容
# 字节流
f = io.BytesIO()  # 创建临时二进制文件
f.write(b"hello")  # b表示二进制

with关键字

  • 文件使用完需要关闭,不然会大量占据内存
# 为test.py创建一个别名file
with open('test.py','r',encoding = 'utf8') as file:
    # 会有缩进
    print(file.read())
    # 缩进代码执行完后会自动关闭文件

python异常、模块与包

异常的捕获

在可能发生异常的地方,进行捕获。当异常出现的时候,提供解决方式,而不是任由其导致程序无法运行。

try:
    可能要发生异常的语句
except[异常 as 别名:]
    出现异常的准备手段
[else:]
    未出现异常应做的事
[finally:]
    不管出不出现异常都会做的事
# 异常的种类多种多样,如果想要不管什么类型的异常都能捕获到,那么使用:except Exception as e:

python模块

模块(Module),是一个 Python 文件,以 .py 结尾. 模块能定义函数,类和变量,模块里也能包含可执行的代码,import用于导入模块
模块的导入方式(不需要后缀):

[from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名]
# import和from的区别:import可以直接导入模块
# from 包 import 模块
# from 模块 import 方法

常用的组合形式如:

  • import 模块名
  • from 模块名 import 类、变量、方法等
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名
    每个Python文件都可以作为一个模块,模块的名字就是文件的名字
    在实际开发中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果, 这个开发人员会自行在py文件中添加一些测试信息,但是在模块导入的时候都会自动执行test函数的调用
  • 解决方案:
def test(a,b)
    print(a+b)
# 只在当前文件调用该函数,其他导入的文件不符合该条件,则不执行test函数
if __name__ == '__main__':
    test(1,1)
  • 如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素
__all__ = ['test_A']
def test_A():
    print('A')
def test_B():
    print('B')
# 只能传输test_A函数

python包和python库

  • 从物理上看,包就是一个文件夹,存放很多py文件,在该文件夹下自动创建了一个 _ init _.py 文件,该文件夹可用于包含多个模块文件 从逻辑上看,包的本质依然是模块
  • 库和包一样,只是有专门用途时就把包称为操作xxx的库
    ~
  • 当我们的模块文件越来越多时,包可以帮助我们管理这些模块, 包的作用就是包含多个模块,但包的本质依然是模块
    导入包:
    1.import 包名.模块名 调用:包名.模块名.目标
    2.from 包名 import * 必须在__init__.py文件中添加__all__ = [],控制允许导入的模块列表

内建变量

  • name=="main"
if __name__ == "__main__"
    def fun:
        pass
# 使该方法私有,不可用于模块导入

面向对象和面向过程

  • python中万物皆对象
  • 面向对象:属性和行为上的封装,关注的是解决问题所需的对象
  • 面向过程:功能上的封装,关注的是解决问题的每一个步骤

面向对象

  • 抽象概念,具有相同行为或属性的统称
  • class:进行类的定义
  • 类里面的变量称为属性
  • 类里面定义的函数称为方法
成员方法

  • 在Python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法
# 函数
def add(x,y):
    return x+y
# 方法
class Student:
    def add(self,x,y):
        return x+y
  • self关键字 ,它是成员方法定义的时候,必须填写的,但是传参的时候可以忽略它
    • 它用来表示类对象自身的意思,self其实就是实例对象统称
    • 当我们使用类对象调用方法时,self会自动被python传入
    • 在方法内部,想要访问类的成员变量,必须使用self
    • 如果没有self,就不能用xx(实例).xxx(类)进行调用
  • 方法和函数功能一样, 有传入参数,有返回值,只是方法的使用格式不同:
# 函数的使用
num = add(1,2)
# 方法的使用
student = Student()
num = student.add(1,2)
构造方法
  • 基于类创建对象的语法:对象名 = 类名称()
  • python类可以使用:__init__()方法,称之为构造方法,又叫做初始化函数
  • 在创建类对象(构造类/实例化)的时候,会自动执行,并将传入参数自动传递给__init__方法使用
  • 类的构造函数__init__没有定义时,不能在创建实例时传递参数
class student:
    name = None
    age = None
    tel = None
def __init__(self,name,age,tel):
    self.name = name
    self.age = age
    self.tel = tel
    # 通过self指明的属性称为实例属性
    # 实例属性在类里面的所有方法都是可以调用的
    print("Student类创造了一个对象")
stu = student("Tom",31,16554665460)# stu称为实例对象
三大特性
  • 面向对象编程,是基于模板(类)去创建实体(对象),使用对象完成功能开发
  • 面向对象包含3大主要特性:封装 继承 多态
封装
  • 将现实世界事物在类中描述为属性和方法,即为封装
  • 现实事物有部分属性和行为是不公开对使用者开放的。同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了
    • 成员变量和成员方法的命名均以__作为开头即可
class phone:
    i=None
    p=None
    __curr = None  # 私有成员变量
    def __keep(...):  # 私有成员方法
        ...
# 私有成员无法被类对象使用,但可以被其他成员使用
    def call(self)
        if self.__curr>=1:
            self.__keep()
继承

将从父类那里继承(复制)来成员变量和成员方法(不含私有)

  • 单继承
class Phone:
    IMEI = None  # 序列号
    producer = None  # 厂商
    def call_by_4g(self):
        print('4g通话')
---->
class Phone2022:
    IMEI = None  # 序列号
    producer = None  # 厂商
    fase_id = True  # 面部识别
    def call_by_4g(self):
        print('4g通话')
    def call_by_5g(self):
        print('5g通话')
#  使用单继承实现:
class Phone2022(Phone):
    fase_id = True  # 面部识别
    def call_by_5g(self):
        print('5g通话')
  • 多继承
    • 多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级
    • pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
class Phone:
    IMEI = None  # 序列号
    producer = None  # 厂商
    def call_by_5g(self):
        print('5g通话')
class NFCReader:
    nfc_type = '第五代'
    producer = 'HM'
    def read_card(self):
        print('读取NFC卡')
    def write_card(self):
        print('写入NFC卡')、
class RemoteControl:
    rc_type = '红外遥控'
    def control(self):
        print('红外遥控开启')
class MyPhone(Phone,NFCReader,RemoteControl):
    pass

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B,C)
d = D(B,C)  # 出发点D,继承D=>B=>C=>A
# mro()查看继承顺序
print(D.mro())
# 发现有个object类,所有没有写父类继承的都默认继承这个类
  • 复写:子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。即在子类中重新定义同名的属性或方法即可
class Phone:
    IMEI = None  # 序列号
    producer = 'ITCAST'  # 厂商
    def call_by_5g(self):
        print('父类的5g通话')
class MyPhone(Phone):
    producer = 'ITHEIMA'  # 复写父类属性
    def call_by_5g(self):
        print('子类的5g通话')  # 复写父类方法
  • 一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员 如果需要使用被复写的父类的成员,需要特殊的调用方式:
# 方法一:调用父类成员
  # 使用成员变量:
  父类名.成员变量
  # 使用成员方法:
  父类名.成员方法(self)
# 法二:使用super()调用父类成员
  # 使用成员变量:
  super().成员变量
  # 使用成员方法:
  super().成员方法()

多态
  • 指的是完成某个行为时,使用不同的对象会得到不同的状态,多态常作用在继承关系上,即前提要有继承
  • 抽象类(接口):含有抽象方法的类称之为抽象类
  • 抽象方法:方法体是空实现的(pass)称之为抽象方法
  • 抽象类多用于做顶层设计(设计标准),以便子类做具体实现,要求子类必须复写(实现)父类的一些方法
  • 多态即多种形态,在继承的基础上定义新的方法或复写就是一种多态
魔术方法(魔法方法)
  • 双下划线开头和结尾
  • 类中默认存在的具有特殊功能的方法
class A:
    def __init__(self):  # 初始化方法
    def __str__(self):  # 输出魔术方法1,对输出结果进行改变,要配合print()s使用
        return 'xxx'
    
a = A()
print(a)
>>>xxx
a
>>><......>
# 如果使用输出魔法2,不需要配合print
def __repr__(self):
    return 'xxxxx'
a
>>>xxxxx
# 析构函数,实例对象被删除的时候执行,要放在编辑模式中才能执行
def  __del__(self)
    print('xxxx')
del a
>>>xxxx
内置函数
  • 类中已经存在的函数
class A:
    def __init__(self,name,age)
        self.name = name
        self.age = age
a = A('a',18)
# 获取属性值方法 getattr(实例对象,'属性名')
getattr(a,'name')
>>>'a'  # 等同于  .  方法
# 判断属性是否存在  hasattr(实例对象,'属性名')
hasattr(a,'name')
>>>True
# 删除属性  delattr(实例对象,'属性名')
# 设置属性  setattr(实例对象,'属性名','属性值'),如果存在则是修改,如果不存在则是新增

异常

报错分析

  • 报错信息比较复杂时先找最底下一行,如何分析行号最小的代码
# invalid syntax:语法无效
print(a)
'''
Traceback (most recent call last):
  File "C:\Users\Lenovo\Desktop\python\work.py", line 1, in <module>
    print(a)
NameError: name 'a' is not defined

File:报错文件
line:报错代码行号
module:报错代码
NameError:报错类型
name 'a' is not defined:报错信息
'''
open('z.txt')
'''
Traceback (most recent call last):
  File "C:\Users\Lenovo\Desktop\python\work.py", line 1, in <module>
    open('z.txt')
FileNotFoundError: [Errno 2] No such file or directory: 'z.txt'

FileNotFoundError:报错类型
'''

利用报错

  • try:针对不同的报错反馈出不同的结果
  • 用来debug
try:
    open('z.txt')  # 可能出现报错的代码
except Namerror(xxx):  # 如果是xxx类型报错,则执行缩进中的代码
    print('x')
except FileNotFoundErro:
    print('xx')
except Exception as e:  # Exception捕获所有其他报错,用变量e接收
    print(e)
else:  # 代码没有报错时执行
    print('正常')
finally:  # 不管代码有没有问题都会执行,要放在最后一个
    print('xxxxx')

主动报错(assert(断言))

  • assert是断言,和if判断类似,只是判断为False的时候会报错,直接抛出报错信息,中断代码执行
li = [4,5,6]
assert len(li)==4

装饰器

  • 本质就是函数,由闭包函数+回调函数组成
  • 在不改变函数本身的同时给函数加新功能
  • 使用装饰器:@后面加上装饰器的名称,解释器会认为你调用了这个函数,然后传了一个参数
  • @底下的函数的函数体传给装饰器的名称代表的函数,底下的函数的函数体变为空,由于闭包函数,返回内层函数,然后底下的函数获得了内层函数的函数体,此时它就拥有了原本的函数体+内层函数的函数体
def vari():  # 改为vari(f)
    # print(f),f拿到了使用装饰器的函数体,即f = cat
    def var():
        f()
        print('x')
    return var
@vari  # 会报错,因为vari(参数),缺少参数传入,而且vari缺少参数,
def cat:  # 此时cat保存的就是闭包函数的返回值,var函数体
    print('xxxx')
回调函数
  • 把一个函数作为另一个函数的参数
def fun():
    print('python')
def fun2(f):  # f = fun
    f()  # f() = fun()
fun2(fun)

正则

  • 正则表达式:【规则表达式】是一种通用的用来简介表达一组字符串的表达式,由需要匹配的正则表达式和一些特殊字符串组成,可以在字符串中匹配出需要查找的对象
  • 利用正则表达式可以方便快捷的匹配和筛选字符串,比如利用查找病毒的特征值来查找文本中的病毒
import re #正则模块
# findall('正则规则','字符串')  返回一个列表

正则的元字符

字符 作用
. 通配符,匹配任意字符
\ 正则转义
^ 脱字符匹配字符串的开始位置,在[]表示字符集合取反
` 字符
---- --------------------------------------
. 通配符,匹配任意字符
\ 正则转义
^ 脱字符匹配字符串的开始位置,在[]表示字符集合取反
匹配字符串的结束位置
{} 匹配次数,指定次数匹配
* 匹配0次或多次,匹配不成功就认为是匹配0个,返回空字符串,会在结束的时候返回一个额外的空字符串
+ 匹配1次或多次
? 匹配0次或1次
[] 字符集合
() 分组匹配
` `
st = '12345this \t \n . 78 9'
li = re.findall('.',st)
li
['1', '2', '3', '4', '5', 't', 'h', 'i', 's', ' ', '\t', ' ', ' ', '.', ' ', '7', '8', ' ', '9']
# \n匹配不到,findall认为这是两个字符串匹配,因此\n被过滤了
# re.S  看成一行字符串,匹配全部字符
li = re.findall('.',st.re.S)
li = re.findall('1.',st) # 表示匹配规则是1后面是任意内容
li
['12']
li = re.findall('1.8',st) # 表示匹配规则是1后面是任意内容,再后面是8
li = re.findall('\.',st) # 转义.,不让它发挥作用

st1 = 'hello world'
st2 = 'world hello'
li1 = re.findall('^hello',st1)  # 匹配成功
li2 = re.findall('^hello',st2)  # 匹配失败

# []字符集合,匹配的是一个范围是单个元素
li = re.findall('[0-9]',st)  # 匹配数字0-9
li = re.findall('[0-9a-z]',st)  # 匹配数字0-9,小写字母a-z
li = re.findall('[0-9a-zA-Z]',st)  # 匹配数字0-9,小写字母a-z,大写字母A-Z
# 注意:[]字符集合中加入^表示取反,如
li = re.findall('[^0-9]',st)
# 用[]字符集合,匹配字符串:
li = re.findall('[2][0][2][4]',st)

li = re.findall('2024|2025',st)  # 匹配2024或2025
# 相当于
li = re.findall('[2][0][2][4-5]',st)

st = 'this is python'
st = re.findall('i(s)',st)  # 匹配规则是is,但只返回s
st = re.findall('i(?:s)',st)  # 保留括号外面的
# 匹配1999-2020 1-12 1-31
li = re.findall('(?:1999|20[1-2][0-9]|2020)(?:0[1-9]|1[0-2])',st)

转义符

## \d:匹配数字
li = re.findall('\d\d',st)
# 相当于
li = re.findall('\d{2}',st) # 匹配字符串长度为2的数字
li = re.findall('\d{1,}',st) # 匹配一个或多个,无上限
# 相当于
li = re.findall('\d+',st)
li = re.findall('\d{0,1}',st) # 匹配0个到1个
## \D:取反,即数字外的所有内容都匹配
### 大写即为取反
## \s:匹配空白符:空格,水平制表符,换行符
## \w:匹配字母、数字、下划线、汉字
## \b:匹配单词边界,类似空格
st = 'this is python is good'
li = re.findall(r'\bis',st)  # 匹配要求是is的左边必须是一个单词边界即空出来的
# ps:在字符串中\b有特殊转义,要用r取消转义

贪婪模式和非贪婪模式

  • 贪婪模式:尽可能拿最多元素
  • 非贪婪模式:尽可能拿最少元素
st = '<div>Section 1</div><div>Section 2</div>'
# 贪婪模式
li = re.findall('<div>.*</div>',st)
# 非贪婪模式
li = re.findall('<div>.?</div>',st)

中文匹配

import re
st = 'hello 你好 world 世界'
li = re.findall('[\u4e00-\u9fa5]',st)  #中文的范围

正则方法

## sub方法
re.sub('[a-zA-Z]','6',st,5) 
# 第一个参数是要替换的内容,第二个参数是替换后的内容,第三个参数是要替换的字符串,第四个参数是要替换的个数,全部替换第四个参数可以不写
# sub(需要替换的元素,新元素,字符串,个数)
## split方法
re.split('[\u4e00-\u9fa5]',st)  # 遇到中文就进行一次切割
## findall 匹配所有符合要求的数据,返回列表
## search 匹配一个符合要求的数据,返回对象
## match 匹配一个符合要求的数据,返回对象,这个符合要求的数据必须在开头
st = '你hello 你好 world 世界'
re.match('[\u4e00-\u9fa5]',st)
print(li)
>>><re.Match object; span=(0, 1), match='你'>
# span是下标,match是匹配到的数据
st = 'hello 你好 world 世界'
re.search('[\u4e00-\u9fa5]',st)
print(li)
>>><re.Match object; span=(6, 7), match='你'>

## span()方法获取匹配到的元素下标
print(li.span())
## group()方法获取匹配到的元素下标
print(li.group())
posted @ 2024-12-14 19:21  micryfotctf  阅读(32)  评论(0)    收藏  举报