编码
一个字节byte 是8位bit
字符是由字节构成的。
utf8中:z=1byte=8bit=2`8二进制(0-255位)
不同编码,一个字符所占的字节不一样
ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间
utf-8编码中,一个英文字符等于一个字节,一个中文(含繁体)等于三个字节
Unicode编码中,一个英文等于两个字节,一个中文(含繁体)等于两个字节。
终端命令
盘符:
重定向 即 转到其他位置:cd>文件名,把路径放进去
rd 删除空目录
rd 删除 不管是否为空的目录,会询问
del 删除文件
echo 内容 >文件名 创建一个放入内容的文件
ren 旧文件名 新文件名 重命名文件名
cls 清屏
Pycharm中python快捷键
单行注释 # XXXX (选中注释内容,ctrl+/ 快捷键).
多行注释 三个双引号 ‘’ 或单引号 ’ 框起来.
快速重复 ctrl+D
格式 = 两边加空格 ctrl+alt+L
向上或向下移动一行 alt+shift+向上/向下箭头
向上或向下移动一段代码块 ctrl+shift+向上/向下箭头
查看代码运行过程 指向对象(内存地址) http://www.pythontutor.com/
导入非Python标准库的类型:Alt+enter
一、Python 简介
-
Python 由荷兰人 Guido van RossIM 吉多 范 罗苏姆发明.
-
Python 的特点:是 一种解释性语言;是交互式语言;是面向对象语言;是初学者的语言;是跨平台的.
二、基础内容
1.命名规则
只能是数字、字母和下划线;开头不能是数字或空格;不能是Python的关键字;严格区分大小写.
2.命名方式
a.变量名、函数名和文件名全小写,使用下划线连接,如:stu_name.
b.命名做到 顾名思义.
c.尽量避免和系统内置函数和类以及模块重名.
d.首字母大写用于类的命名.(大驼峰命名法).
注:汉字可以作为变量名,不建议用.
3. 数据类型
string、list 和 tuple 都属于 sequence(序列)
列表 list[ ] 用来存储多个数据,属于可变数据类型
元组 tuple( ) 用来存储多个数据,属于不可变数据类型
字典 dict{ } 用来存储多个数据 ,属于可变数据类型
集合 set{ } 用来存储多个数据,无序
4.变量的类型
字符串 str 单引号或双引号 属于不可变数据类型
整型 int 是数字
浮点型 float 小数型
布尔型 bool Ture False
复数型 complex
5.变量的使用
常量 字母要大写,用于区分变量
定义多个变量,初始值一样 n1=n2=n3=22
定义多个变量,初始值不一样 n1,n2,n3,=11,33,99 左右变量个数保持一致
变量的意义:对于重复使用的数据,可以定义为变量,可以提高代码的维护效率。
6.变量的删除
del 变量名
7.获取变量类型
type (变量名)
print(type (变量名))
#类型转换
str(xx) 转换为字符串类型 (字符串属于不可变数据类型)
int(xx) 转换为整型
float(xx) 转换为浮点型
8.输出语句
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
# sep:间隔符 输出值之间以定义的方式 间隔,默认是空格。
# end:输出完内容后,以什么方式结尾,默认是换行。
# file=sys.stdout:默认输出到控制台
# file = open("file1.text","w") 打开并写入到文件file1.text,w是写入的意思
# flash = True 打开文件刷新,提高文件读写速度
9.输入语句
#无论用户输入什么内容,接收的内容永远是字符串类型.
input(xx)
10.不同进制
#二进制:0b
a = 0b10
print(a)
2
# bin()
#八进制:0o
a = 0o10
print(a)
8
# oct()
#十进制:默认
#十六进制:0x
a = 0x10
print(a)
16 #1*16的1次方+0*16的0次方
# hex()
11.算术运算符
# +-*/
# ** 幂运算
# // 整除
# % (取余)取模运算
# 字符串和字符串之间只支持加法运算符,拼接两个字符串
print('hello'+'world')
helloworld
# 字符串和数字只支持乘法运算符,会将字符串重复多次
print('world'*3)
worldworldworld
12.赋值运算符
a += 1 # a+1之后再赋值给a
a -= 1 # a-1之后再赋值给a
a *= 1 # a*1之后再赋值给a
a /= 1 # a/1之后再赋值给a
a //= 1 # a//1之后再赋值给a
a %= 1 # a%1之后再赋值给a
a **= 1 # a**1之后再赋值给a
# * 表示可变长度
x,*y,z = 1,2,3,4,5,6
print(x,y,z)
1 [2, 3, 4, 5] 6
# 元组的赋值
a = 2,3 # a为元组 (2,3)
# 交换两个变量的值,使用第三个变量
a=1
b=2
c=a
a=b
b=c
2 1
# 交换两个变量的值,使用加减法交换(必须同时支持加减法)
a=a+b
b=a-b
a=a-b
2 1
# 交换两个变量的值
a,b=b,a
2 1
12.比较运算符
# 数字和字符串做 == 运算结果是false,除了 == 以外的逻辑运算时,会直接报错。
# 如果是两个字符串进行比较,会将每个字符都转换成对应的编码,然后逐一进行对比。
In [1]: str1='a'
In [2]: str2='ABC'
# 将字符转换成为对应的编码 a对应的编码是97,A对应的编码是65
In [3]: str1 > str2
Out[3]: True
# 内置函数 ord(字符) 查看该字符的对应编码
# chr(编码) 查看编码对应的字符
14.逻辑运算符
# 与and 或or 非not
# 逻辑 与and 运算的短路问题 :
# 只要遇到false,结果就是false,就会停止,取第一个为false的值
# 0的布尔值为false
# 如果所有运算数都是True,输出最后一个值
# 逻辑 或or 运算的短路问题 :
# 只要遇到true,结果就是true,就会停止,取第一个为true的值
# 如果所有运算数都是false,输出最后一个值
#不管与 还是 或 为真为假 有值可取 就取第一个遇见的值
15.位运算
&:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0
|:只要对应的二个二进位有一个为1时,结果位就为1
^:当两对应的二进位相异时,结果为1
~:对数据的每个二进制位取反,即把1变为0,把0变为1 。~x 类似于 -x-1
<<:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0
>>:右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数
负数二进制:python没办法表示,因为整数的长度是可变的,最高位不定
三.条件判断
1.if 语句 格式
if 要判断的条件:
条件成立时,要做的事情
2.if else 语句 格式
if 条件:
满足条件时的操作
else:
不满足条件时的操作
3.if… elif… elif… else 语句 格式
if xxx1:
事情1
elif xxx2:
事情2
elif xxx3:
事情3
else
# elif必须和if一起使用,否则出错 else 一般用在最后,即所有条件都不满足时使用
4. if 语句 嵌套
if i == 1:
if j == 2:
if y == 3:
print('3')
5.注意事项
# 在Python中允许类似于 5<a<10 的写法,这种写法在很多编程语言里都是不允许的,需要使用逻辑与运算符进行连接。
a = 10
1<a<20 # True
11<a<20 # False
# 三元运算符
# 格式:变量 = 值1 if 条件 else 值2 当条件成立时把 值1 赋值给变量,条件不成立时把 值2 赋值给变量,其实就是对if...else 语句的一种简写。
a = 10
b = 30
if a > b:
c = a
else:
c = b
print('a和b两个数的较大值是%d'%c)
# 简写
a = 10
b = 30
c = a if a>b else b
print('a和b两个数的较大值是%d'%c)
6.自动类型转换
**提示:**在Python中,转换成为布尔值时,只有 0,"",'',None,(),{},[]
会被转换成为False,其他都会被转换成为True。
四.循环语句
1. while 循环
while 判断条件:
代码块
# while...else...
count = 0
while count < 5:
print (count, " 小于 5")
count = count + 1
else:
print (count, " 大于或等于 5")
2.for 循环
# for in 循环后面是 可迭代对象
sites = ["Baidu", "Google","Runoob","Taobao"]
for site in sites:
if site == "Runoob":
print("菜鸟教程!")
break
print("循环数据 " + site)
else:
print("没有循环数据!")
print("完成循环!"
break :# 跳出循环体,结束了
continue:# 跳出循环块中的剩余语句,开始新的循环
五.字符串:不可变数据类型
1.字符串常见操作
字符串的常见操作包括:
# 获取长度:len
# 查找内容:find,index,rfind,rindex
#判断:
startswith,endswith,
isalpha, 判断是否是字符
isdigit, 判断是否是数字
isalnum, 判断是否定是数字字母组合,文字也会返回True
isspace
计算出现次数:count
替换内容:replace
# 切割字符串:
split:默认根据 空格 进行切割
rsplit(从右边切),
splitlines,
partition,
rpartition(从右边切,将字符串分为3部分,以元组的形式存)
# 修改大小写:capitalize,title,upper(所有变为大写),lower(所有变为小写)
# 空格处理:
ljust(字符串不够指定的位数,默认用空格补齐),
rjust(字符串不够指定的位数,默认用空格补齐),
center(字符串不够指定的位数,字符两边默认用空格补齐),
lstrip(去除字符串左边的指定字符,默认是空格),
rstrip(去除字符串右边的指定字符,默认是空格),strip(去除字符串两边的指定字符,默认是空格)
# 字符串拼接:join (将列表拼接为字符串)
# 用'a'拼接(h a x a m a d a q)
print('a'.join('hxmdq'))
#haxamadaq 把hxmd一个个取出,并在后面添加字符a. 最后的 q 保留,没有加 a
print('a'.join(['hi','hello','good'])) #hi a hello a good
txt = '_'
# 用'_' 拼接
print(txt.join(['hi','hello','good'])) #hi_hello_good
print(txt.join(('good','hi','hello'))) #good_hi_hello
# 调用方法格式
str.方法名()
注意:在Python中,字符串是不可变的!所有的字符串相关方法,都不会改变原有的字符串,都是返回一个结果,在这个新的返回值里,保留了执行后的结果!
2.字符串格式化
# 1. 使用%占位符:% s 字符串占位符,% d 整数占位符,% f 浮点占位符;
%(变量名1,变量名2,...)
# ("姓名:%s","职位:%s","公司地址:%s" % (name, job, address))
# % 0 nd 不够n位 用 0 补齐
# % .n f 小数点后保留 n 位
# %% 表示一个普通的占位符
# % o/x 以8进制/16进制输出
# % c 将字符对应的字符编码输出
name = 'chris'
job = '讲师'
address = '上海市'
print('--------------------------------------')
print("姓名:%s","职位:%s","公司地址:%s" % (name, job, address))
print('-------------------------------------')
# 输出
--------------------------------------
姓名:chris,职位:讲师,公司地址:上海市
-------------------------------------
# 2. 使用字符串的format方法
name = 'zhangsan'
age = 18
print('我的名字是{},我今年{}岁'.format(name,age))
print('我的名字是{1},我今年{0}岁'.format(age,name))
print('{:03}'.format(8)) #008
print('{:.3}'.format(32.2222)) #32.2
print('{:.3f}'.format(32.2222)) #32.222
# 3. 使用 f 格式化字符串
print(f'我是{name:.2f}\n我今年{age}岁') # 保留两位小数
# 我是zhangsan
# 我今年18岁
# 4.字符和编码的相互转化
# chr(获取编码对应的字符) 和 ord(获取字符对应的编码) 只对字符有效,无法使用于字符串
# 字符串的编码encode
字符串.encode(编码方式)
# 解码 decode
字符串.decode(编码方式)
六.列表
1.列表 list[] :容器,存放数据;(内容)可变数据类型
2.可存储的数据类型
- 列表可以存储任意类型的数据。一个列表可以同时存储不同的数据。通常情况下,一个列表保存的数据是相同的类型。
- 不同的数据类型在操作时,允许的方式是不同的。
- 支持 加法+ (两个列表合并) 和 乘法* (将列表内容重复n次)
3.列表支持下标和切片
和字符串类似:从0 开始计数
list[3]: 取下标为3的数据,即第四个数据
list[3:7]:含3 不含7
4.列表的增删改查
append / extend / insert:
clear / remove / pop:
index -索引
1>.添加元素
-
list.appent(“天蓬元帅”) #在列表后面 添加元素
# 直接使用append方法将字典添加到列表中,如果更改字典中的数据,那么列表中的内容也会发生改变,这是因为dict在Python里是object,不属于primitive type(即int、float、string、None、bool)。这意味着你一般操控的是一个指向object(对象)的指针,而非object本身。下面是改善方法:使用copy() info = {} inf = [] for j in range(3): info['sid'] = s[j][0] info['name'] = s[j][1] info['score'] = s[j][2] j += 1 inf.append(info.copy()) # inf.append(info) 字典的内容改变,列表的内容也会改变 print(info) print(inf)
# 在列表末尾,追加另一个序列的多个值 list.extend(["天蓬元帅","嫦娥","哪吒"]) list = list + ["",""] #列表支持加法运算,可直接加元素 list.insert(5,"哮天犬") #在指定位置 插入元素
2>.删除数据
list.clear() #用来清空列表
list.remove("哮天犬") #删除指定数据
list.pop(5) #删除指定下标上的元素
del list[2] #删除指定下标上的元素
3>.修改元素
-
list[5] = “如来佛祖” #直接使用下标修改指定下标上的元素
-
i = list.index(“七仙女”) #根据元素找对应位置
-
list[list.index(“七仙女”)] = “寿星公” #修改指定元素为某元素
5.遍历列表:拿列表中的每一个元素
monsters = ["","","","","","","","",""]
i = 0
while i < len(monsters):
print ( f '下标为{ i } 的元素是{monsters[ i ] } ‘ )
i += 1
# 本质是调用可迭代对象的迭代器的next方法,不断获取下一个数据
for m in monsters:
print( m )
# 带下标的遍历
j = 0
for m in monsters:
print ( f '下标为{ j } 的元素是{monsters[ m ] } ‘ )
j += 1
# 用来将一个可迭代对象添加序号。带下标的循环可以用enumerate
for j, m in enumerate(monsters):
print ( f '下标为{ j } 的元素是{monsters[m ] } ‘ )
nums = [6, 5, 3, 1, 8, 7, 2, 4]
# 1.sum ave
# sum = 0
# for i in nums:
# sum += i
# ave = sum/len(nums)
# print(sum,ave)
# 2.求最大数和最小数以及位置
m_max = nums[0] #假设第0个数是最大数
max_index = 0 #假设最大数的下标
m_min = nums[0] #假设第0个数是最小数
min_index = 0 #假设最小数的下标
for i,m in enumerate(nums):
if m_max < m:
m_max = m
max_index = i
if m_min > m:
m_min = m
min_index = i
print(f'最大数是{m_max},下标是{max_index}\n最小数是{m_min},下标是{min_index}\n')
6.列表排序:冒泡排序???
7.列表中的排序和列表的翻转
list.sort() # 可以直接调用sort方法排序,默认是升序
list.sort(reverse=Ture) # 添加参数reverse=Ture,降序排列
list.reverse() # 翻转 直接修改原有列表
new_list = list[::-1] # 翻转 不修改原有列表
# 列表中嵌套字典 按字典的值排序,使用sorted函数
s = '01#张三#60-02#李四#90-03#王五#70'.split('-')
for i in range(3):
s[i] = s[i].split('#')
print(s) # 将字符串中按符号分割,
info = {}
inf = []
for j in range(3): # 遍历列表,将列表中的内容以字典的形式存起来,
info['sid'] = s[j][0]
info['name'] = s[j][1]
info['score'] = s[j][2]
j += 1
inf.append(info.copy()) # dict内容改变时 列表中的内容 也会改变 用copy 解决这个问题
# 按照列表中嵌套的字典的值进行排序,使用内置函数sorted,reverse = True 表示按照降序排列
inf_sort = sorted(inf, key=lambda e: e['score'], reverse=True)
print(inf_sort)
# sorted(列表名, key = lambda e:e['要排序的值'])) 默认是升序
七. 元组tuple()
1. 不可变数据类型
# 不可增删改元组的数据
a = (1,2,3,4)
b = (5,6,7)
a.index(2) # 返回指定元素的下标
print(a+b) # 元组相加,返回新的元组
八.字典dict{}
1.基本使用
字典用来保存多个数据,是可变的数据类型(列表也是)
格式:dict{ key : value,… }
# 字典的 Key 必须是不可变的数据类型(字符串,整型,布尔值,元组() )
# 字典的 value 可以是任意类型,可以重复
# 字典的 key 重复出现 后一个出现的值会覆盖前一个值
# 字典是一个无序的容器
# 只能通过 key 获取指定的 value
d.key() # 获取键
d.values() # 获取值
d.get(key) # 返回键对应的值
# dict.items()
d = {'age': '2', 'name': 'jane', 'sex': 'm'}
print(d.items())
# 输出
dict_items([('age', '2'), ('name', 'jane'), ('sex', 'm')])
# 列表嵌套元组[(key,value),...]
2.增删改查
# update :添加到指定字典dict里的字典。
d1={'place':'上海'}
d.update(d1)
# clear 清空 字典内容
# pop 根据 键删除对应的值
# popitem 删除最后一对键值对
3.字典遍历
# 取出 健为 k 的值 person[ k ]
for k in person.key:
print(person[ k ])
4.字典的函数
# dict.fromkeys() 函数
# 用于创建一个新字典,以序列 seq 中元素做字典的键,value 为字典所有键对应的初始值
seq = ('name', 'age', 'sex')
dict = dict.fromkeys(seq)
print ("新的字典为 : %s" % str(dict))
dict = dict.fromkeys(seq, 10)
print ("新的字典为 : %s" % str(dict))
新的字典为 : {'age': None, 'name': None, 'sex': None}
新的字典为 : {'age': 10, 'name': 10, 'sex': 10}
九.集合set()
1.格式:x = { ‘name’,5,True} 或 set(‘name’,5,True)
-
与字典的区别:字典是通过键值对保存数据,集合是保存单个的值
-
与列表、元组的区别:
-
集合保存的数据是无序的,存入的数据跟输出的顺序不同,不能通过下标获取数据
-
集合不保存重复的数据,有重复的数据会自动去重
-
2.定义空集合:b = set( )
十.函数的使用
1.函数的参数
1.缺省参数:
位置参数:
关键字参数:通过变量赋值
*args :可变位置参数
**kwargs:可变关键字参数
global :全局变量。在函数内部修改全局变量
变量相关的内置函数:
globals 和 locals 和 vars
globals:用来获取所有的全局变量
locals:用来获取当前作用域的变量
vars:如果不传递参数,基本等价于locals。如果传入参数,会列出对象的属性
2.函数参数 高级
2.函数的返回值
3.函数的文档注释
4.变量的作用域
5.可变类型和不可变类型
可变数据类型 不建议 作为函数的参数使用;一定要使用,一定要默认为None
6.递归函数的使用
# 递归 就是 函数自己 调用 自己
# 递归一定要留好出口(停止的条件)
7.匿名函数
1.匿名函数的使用
# 用 lambda 关键词 创建小型匿名函数。
# 格式:lambda 参数列表: 运算表达式
2.使用场景
8.把函数当做参数使用
9.常用内置函数
- sorted:用来将一个 无序列表进行排序
num = (2,4,3,6,7,8)
x = sorted(nums) #sorted 内置函数 不会改变原有的数据,而是生成一个新的有序的列表
sorted 语法:
sorted(iterable, key=None, reverse=False)
参数说明:
iterable -- 可迭代对象。
key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
返回值
返回重新排序的列表。
s = '01#张三#60-02#李四#90-03#王五#70'.split('-')
for i in range(3):
s[i] = s[i].split('#')
print(s)
info = {}
inf = []
for j in range(3):
info['sid'] = s[j][0]
info['name'] = s[j][1]
info['score'] = s[j][2]
j += 1
inf.append(info.copy()) # dict内容改变时 列表中的内容 也会改变 用copy 解决这个问题
inf_sort = sorted(inf, key=lambda e: e['score'], reverse=True)
print(inf_sort)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-15cSkwUM-1628010512909)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210126110710374.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CxiD2yZo-1628010512911)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210126110805016.png)]
- map(f,list) 函数
#map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回
10.高阶函数
1.函数可以作为另一个函数的返回值
2.函数也可以做为另一个函数的返回值
11.函数嵌套函数
12.装饰器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8s469xfi-1628010512912)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210126142708048.png)]
13. 其他内置函数
# 数学相关
1.abs:求绝对值
2.divmod:得到一个元组,第一个是商,第二个是余数
max / min / sum
pow(2,10,5):幂运算2的10次方模于5
round(3,1415892,2):四舍五入,保留指定位数
# 可迭代对象相关
1.all:判断一个可迭代对象的所有元素转为布尔值后 是否全是True
2.any:
iter :用来获取一个可迭代对象的迭代器
next :获取计算器的下一个数据
len:用来计算可迭代的长度
3.enumerate(可迭代对象,要返回的对象的索引的开始位置) :枚举,
x=[a,b,n,l,m]
enumerate(x,2)
返回:
2,a
3,b
4,n
5,l
6,m
#转换相关的
1.ascii():获取字符(串)的Unicode编码
2.ord():只能获取单个字符的Unicode编码
3.chr():获取编码对应的字符
4.bin / oct / hex / :转化为相应的进制
# 判断相关的
1.callable():判断一个对象是否能被调用
2.isinstance():判断一个对象是否是由指定类或它的子类创建的
3.issubclass():用来判断一个类是
# 操作对象相关的方法
# 未归类
dir():列出一个对象所有的方法和属性
eval():用来执行字符串里的python代码
repr():
exit():用来结束整个程序
quit():用来结束整个程序
globals():用来获取全局变量
locals():用来获取当前作用域里的变量
vars:不传参等于locals;传一个对象,会以字典的形式列出对象的所有属性
hash():
open():打开一个文件
十一. 内置模块
定义:遵守了命名规则的 py 文件就是一个模块
import xxx
1. import random # 生成随机数
常见方法
random.random # 生成[ 0, 1 ) 的随机浮点数
random.randrange (a,b) # 生成 [ a,b ) 的随机整数
random.randint(a,b) # 生成 [ a,b ] 的随机整数
random.uniform(a, b) # 生成 [ a,b ] 的随机浮点数
random.choice( 序列 ) # 从序列(一堆有序的数据)里随机取出一个元素
random.choices ( 序列 , k=5 ) # 在序列里选择 K 个数据,允许重复
random.sample( 序列 , 3) # 从序列里随机取出指定个数的元素,不允许重复
random.shuffle ( 序列 ) # 让序列重新排序
2. import math
math.fabs(-100) # 取绝对值
math.factorial(5) # 计算阶乘 0的阶乘为1
math.ceil(34.01) #向上取整
math.floor(34.98) # 向下取整
math.pi # π的值,约等于 3.141592653589793
math.pow(2, 10) # 2的10次方 求幂运算
math.sqrt(4) # 开平方
math.sin(math.pi / 6) # 正弦值 用弧度
math.cos(math.pi / 3) # 余弦值
math.tan(math.pi / 2) # 正切值
3. os (operation system)模块
Windows => nt = newtechnology 和 (类)Unix => posix
os.name # 有两个值 nt 和 posix
os.sep # windows 里用 \ ,非windows 用 /
# 在 winsows里,文件路径用 / ,或者 \\ 或者 r'D:\千锋课程\4.Python'
os.getcwd() # 获取当前的工作目录,即当前python脚本工作的目录
os.listdir() # 列出指定目录里的所有文件和文件夹
os.chdir() # 切换路径.
# os.chdir('../') 返回上一级
os.rename() # 重命名文件
os.remove() #删除文件
os.mkdir() # 新建文件夹
os.rmdir() # 删除空文件夹
os.removedirs() # 删除空文件夹
os.path.exisit() # 用来判断文件或文件夹是否存在,存在返回True,不存在返回False
os.path.isdir() #用来判断路径对应的是否是个文件夹,存在返回True,不存在返回False
os.path.isfile() #用来判断路径对应的是否是个文件,存在返回True,不存在返回False
os.path.splitext(path) # 用来将指定路径进行分隔,可以获取到文件的后缀名
s
os.path.join(path,file_name) #拼接文件路径
os.path.abspath(file_name) # 获取文件的绝对路径
# 递归 在函数内部调用函数本身
4. import time
time.time() # 获取从1970-01-01 00:00:00 UTC 到现在时间的秒数
time.strftime("%Y-%m-%d %H:%M:%S") # 按照指定格式输出当前日期时间
# 输出结果为
# 2021-01-28 19:04:51
time.strptime(f,格式) # 按照指定格式输出
# 输出结果 类型是 类 :<class 'time.struct_time'>
time.struct_time(tm_year=2021, tm_mon=9, tm_mday=10, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=253, tm_isdst=-1)
# 该方法 表示 day1 是今年的第几天
day1.tm_yday
time.asctime() #Mon Apr 15 20:03:23 2019
time.ctime() # Mon Apr 15 20:03:23 2019
time.sleep() # 暂停程序多少秒
5. import datetime
# 获取当前时间
print(datetime.datetime.now())
#当前 时间日期的 指定年份2020年
print(datetime.datetime.now().replace(year=2020))
#当前 年份 的指定 日期时间
print(datetime.datetime(year=now.year, month=9,day=10,hour=0,minute=0,second=0))
#当前日期时间的 下一周的时间
# 与datetime.datetime.now() 相差一周的日期时间
print(datetime.datetime.now()+datetime.timedelta(weeks=1)) # 一周后的此时此刻 2021-02-10 20:19:17.540412
print(datetime.timedelta(weeks=1)) # 7 days, 0:00:00
# 当前时间与 要比较的时间 t 之间的天数days,秒数seconds,
now_time = datetime.datetime.now()
t = datetime.datetime(2021, 9, 10)
d = (t-now_time).days
s = (t-now_time).seconds
6.浅拷贝与深拷贝
copy:浅拷贝 ,修改copy后的数据,不影响原来的数据。只是拷贝内容,地址不一样。如果数据中 有 其他子列表或者其他嵌套,数据是指向该地址的,修改 其他子列表或者其他嵌套 的数据,原数据与copy后的数据内容都会改变。
deepcopy:深拷贝,所有的数据都是新的,指向新的地址,包括数据中其他子列表或者其他嵌套。修改 其他子列表或者其他嵌套 的数据,原数据不会改变
7. String模块
# ascii_letters:是生成所有字母,从a-z和A-Z
# digits:是生成所有数字0-9.
十二. 文件操作
1. 参数说明:
open(文件路径,打开方式,编码方式)
# 文件路径:相对路径,绝对路径
# 1. 相对路径:相对当前正在编辑的文件所在的文件夹
# ../:返回上一级
# ./:表示当前目录,是可以省略不写的
# 2. 绝对路径:
#第一种 加 r : r 'D:\千锋课程\4.Python\Day09-常见模块&文件操作\02-代码'
#第二种 加 \ : 'D:\\千锋课程\\4.Python\\Day09-常见模块&文件操作\\02-代码'
#指定打开文件的方式:r,w,a
# 文件的编码方式:encoding = utf8 / gbk / ...
2. 文件操作:打开、写入、追加、编码
#文件的打开方式:文本形式 和 二进制
# t :默认是以纯文本形式打开
# b :以二进制的形式打开文件
以下是以 字符 来操作文件内容:
# r / r+:以只读方式打开文件 / 以读写方式打开文件,文件的指针即光标会放在文件开头,如果文件不存在就会报错
# w / w+:以只写方式打开文件 / 以读写方式打开文件,如果文件存在会替换掉;如果文件不存在就会新建文件
# a / a+:以追加方式打开文件 / 以读写方式打开文件,文件存在的话,文件的指针即光标会放在文件结尾;如如果文件不存在就会新建文件
以下是以 字节 来操作文件内容: ----一些文件必须用这种模式,比如 图片 音视频文件等
# rb / rb+ 以二进制形式打开文件用于只读 / 读写,文件的指针即光标会放在文件开头,如果文件不存在就会报错
# wb / wb+:以二进制形式打开文件用于只写 / 读写,如果文件存在会替换掉;如果文件不存在就会新建文件
# ab / ab+:以二进制形式打开文件用于追加 / 读写,文件存在的话,文件的指针即光标会放在文件结尾;如如果文件不存在就会新建文件
# 以二进制方式操作文件时,不用设置文件的编码方式
# 1.打开文件,如果不指定打开方式,默认是只读的形式打开
#r
f1 = open('text.txt','r') # 以只读的形式打开
# w
f2 = open('text.txt','w') # 以写入的形式打开。只能写,不能读取。
f2.write() # 如果文件不存在,会创建新文件。会覆盖之前的内容。
# a
f3 = open('te','a') # 以追加的方式打开文件
f3.write() # 如果文件不存在,会创建新文件。
# 2.操作文件(读或写)
content = f.read() # 如果文件不存在,会报错。
content = f.read(10)
# read(n) 若以字节的形式打开文件, n 是读取字符的个数
# 若以二进制打开文件,n 是读取的是字节的大小,单位是字节
f.readline() # 读取一行数据
f.readlines() # 读取所有行数据,把每一行数据当做元素存放在列表中,不会重复读取
f.write()
# 加 \n 换行,没有 \n 会在同一行显示数据
f.writelines('你好\n你好\n你好\n') #按行写入文件。可写入列表,写入列表时,列表每一个元素当做一行
加 \n 输出如下:
你好
你好
你好
你好
# 3.关闭文件
f.close()
# encoding 编码方式
f1 = open('text.txt','r',encoding = utf8)
# csv
3. 文件备份
4. 将文件写入到内存
python 提供了 StringIO 和ByteIO 两个类,将字符串和二进制数据写入到内存中
# Python 提供了 tringIO,BytesIO
from io import StringIO,BytesIO
#创建一个StringIO对象
sio = StringIO()
# 写
sio.write("hello")
sio.write('bye')
print(sio)
# 获取写入的数据 getvalue
data = sio.getvalue()
print(data)
#写入二进制数据
bio =BytesIO()
bio.write('hello'.encode('utf-8') )
# 获取数据 getvalue
data = bio.getvalue()
print(data) # 二进制形式输出
print(data.decode('utf-8'))
5. 异常处理
try: # 如果输入内容不满足条件 不报错,直接走except
b = float(input('请输入一个小数'))
print(b*2)
# except 可以给出多个
except Exception as e:
print('输入的不合法')
except Exception as e:
print('输入的不合法')
# Exception 指的错误类型:typeerror....
except TypeError as e:
print('数据类型错误')
6. .序列化 反序列化
1.序列化:
将Python里的对象(比如列表、字典等)变成 二进制 或者 字符串(字节数据) 进行存储或者传输(跨平台或者跨语言)过程
2.反序列化:
将字符串或者二进制,加载成Python对象来使用的过程
3.两个模块用来实现数据的序列化和反序列化。
json模块:将对象转换成为字符串,可以跨平台传输。只有json里识别的数据类型才能被转换成json字符串
pickle模块:将对象转换成为二进制,不可以跨平台
4.json模块 将对象转换成为字符串将对象转换成为字符串
- dumps / dump
json.dumps:输出结果为字符串,可以包括字符串,必须用双引号括起来。
json.dump:等价于 dumps + file.write( )
import json
name = ['lihanhan','mmkek','danaa']
# dumps 将对象转换成为字符串,不具备将数据写入到文件的功能
file = open('msg.txt')
x = json.dumps(name)
print(x)
# 输出:["lihanhan", "mmkek", "danaa"]
# dump 将对象转换成为字符串的同时,指定一f.个文件对象,把转换后的字符串写入到这个文件里
file = open('msg.txt','w')
y = json.dump(name,file)
print(y)
file.close()
- loads / load
json.loads( ):将字符串输出结果为Python对象,可以包括字符串,必须用双引号括起来。
json.load:等价于 loads + file.write( )
#
5.pickle模块:将对象转换成为二进制
十三. 面对对象基础
1. 面向对象 和 面对过程(C语言)
-
面向过程:关注点在于怎么做
- 把完成某一个需求的 所有步骤 从头到尾 逐步实现
- 根据开发需求,将某些 功能独立 的代码 封装 成一个又一个 函数
- 最后完成的代码,就是顺序地调用 不同的函数
-
面向对象:面向对象编程的关注点在于谁来做
相比较函数,面向对象是更大的封装,根据职责在 一个对象中封装多个方法
- 在完成某一个需求前,首先确定职责 —— 要做的事情(方法)
- 根据 职责 确定不同的 对象,在对象内部封装不同的方法(多个)
- 最后完成的代码,就是顺序地调用不同对象的相应方法。
# 面向对象的三大特点:
1.封装
2.继承
3.多态
2. 类 / 对象 / 方法
1. 定义
- 类:是对一群具有相同特征或者行为 的事物的一个统称。由 对象和方法组成
- 特征:即是 对象。
- 行为:即是 方法
2. 类和对象的关系
对象:是类的实例。由哪一个类创建出来的 对象,就拥有在哪一个类中定义的属性和方法。是内存里的一段内存空间。
- 类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象。
- 使用同一个类,能够创建出很多对象。
- 类中定义了什么属性和方法,对象中就有什么属性和方法。
- 不同对象对应的属性值也会不同。
例如:定义了一个狗类,这个狗类有以下属性:
品种 颜色 性别 名字
4. 类的设计
在程序开发中,要设计一个类,通常需要满足一下三个要素:
-
类名 这类事物的名字,安照大驼峰命名法(每个单词的首字母大写)起名。
-
属性 这类事物具有什么样的特征。
-
方法 这类事物具有什么样的行为。
5. 类的格式和 self
class 类名:
def __init__(self,对象属性):#初始化方法
pass
def 方法1(self,参数列表):
pass
def 方法2(self,参数列表):
pass
# self:形参的作用,占位。通常 是写 self.
6. 魔术方法:
Python 的类里提供的,两个下划线开始,两个下划线结束的方法,就是魔法方法
创建对象后,python解释器默认调用__init__()
方法,初始化方法
而当删除对象时,python解释器也会默认调用一个方法,这个方法为__del__()
方法。
1. 构造方法:init
__init__()
:构造方法,设置对象的属性
class Person:
def __init__(self, name, weight):
self.weight = weight
self.name = name
注意:
__init__()
方法在创建对象时,会默认被调用,同时设置对象属性,不需要手动的调用这个方法。
__init__()
方法里的self参数,在创建对象时不需要传递参数,python解释器会把创建好的对象引用直接赋值给self
在类的内部,可以使用self来使用属性和调用方法;在类的外部,需要使用对象名来使用属性和调用方法。
如果有多个对象,每个对象的属性是各自保存的,都有各自独立的地址。
方法是所有对象共享的,只占用一份内存空间,方法被调用时会通过self来判断是哪个对象调用了实例方法。
2. str
__str__()
:我们在打印一个对象时,可能需要列出这个对象的所有属性。
class Cat:
def __init__(self,name,color):
self.name = name
self.color = color
tom = Cat('Tom','white')
# 使用 print 方法打印对象时,会调用对象的 __str__ 方法,默认会打印类名和对象的地址名
print(tom) # <__main__.Cat object at 0x0000021BE3B9C940>
# 没有找到str时 调用repr
# 我们在打印一个对象时,可能需要列出这个对象的所有属性
# 选择重写__str__方法
class Student:
def __init__(self,name,score):
self.name = name
self.score = score
def __str__(self):
return '姓名是:{},成绩是{}分'.format(self.name,self.score)
s = Student('lisi',95)
print(s) # 姓名是:lisi,成绩是95分
3. 析构方法:del
__del__
方法:析构方法,当对象被销毁时调用的方法.
7. 身份运算符
is:身份运算符 is 来判断两个实例对象是否完全是一个对象。判断的是两个对象所在的内存地址 即 id 是否一致
- 判断两个对象 相等
法1:判断内存地址(id),用 is 判断
法2:判断值是否相等:== 本质上是调用对象的 eq 方法
做等于运算时会调用 eq方法, 如果没有eq方法,默认比较内存地址
做不等于运算时会调用ne方法, 如果没有ne方法找eq方法,都没有,就报错
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
p1 = Person('张三',18)
p2 = Person('张三',18)
print(p1 == p2) # False
- 判断两个对象不等
法:调用 gt 方法 / lt 方法
做大于>运算时会调用 gt 方法, 如果没有gt方法,会找lt方法取反;如果没有lt会报错
做大于>运算时会调用 gt 方法, 如果没有gt方法,会找lt方法取反;如果没有lt会报错
十四. 面对对象 高级
1. 私有属性和方法
在实际开发中,对象的某些属性或者方法可能只希望在对象的内部使用,而不希望在外部被访问到,这时就可以定义私有属性和私有方法。
定义方法:在定义属性或方法时,在属性名或者方法名前增加两个下划线__
,定义的就是私有属性或方法。
注:两个下划线 开始的变量是私有变量,不能通过对象名访问,只能在类的函数里使用 self 变量访问
访问私有变量:法1 ----- 可以使用定义get
和set
方法这种方式来实现。
# get_私有变量名:获取私有变量
# set_私有变量名:修改私有变量
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
self.__money = 2000 # 使用 __ 修饰的属性,是私有属性
def __shopping(self, cost):
print('还剩下%d元'%self.__money)
def test(self):
self.__shopping(200) # __shopping私有方法只能在对象内部使用
# 在外部访问私有属性或方法
print(p._Person__money) # 使用对象名._类名__私有属性名 可以直接访问对象的私有属性
p._Person__shopping(100) # 使用对象名._类名__函数名 可以直接调用对象的私有方法
2. property的使用
3. 实例属性、类属性
1.实例属性:对象的属性。每个对象单独保存的属性。
定义在 init 里面的属性是 实例属性
2.Person 类也是对象,我们称之为 类对象 。
定义在 init 外面的属性是 类属性;所有的实例对象都能访问。
注:1. 类属性不能通过实例对象来修改。只能通过类对象来修改。2. 尽量避免类属性和实例属性同名。如果有同名实例属性,实例对象会优先访问实例属性,如果没有实例属性,会新添加实例属性。
4. 类方法 和 静态方法
- 如果一个方法没有用到实例对象和类对象,self参数可以省略。同时需要把这个方法标记为静态方法------@staticmethod。静态方法不需要使用带实例属性,可以通过实例对象和 类对象调用
- 如果一个方法只用到了类属性,可以将这个方法设置为类方法------@classmethod
- 调用 实例方法、类方法、静态方法
# 实例方法
# 类方法
# 静态方法
5. 继承:属性和方法
# 父类 基类:
class Person(object): # 默认最大的父类
pass
# 子类:
class Student(父类): # 继承父类的方法
pass
继承方式
# 1. 支持多重继承:object---->>Person---->>Student
# 如果子类自己 有的方法,父类也有,会调用自己的,用来对父类进行重写,即方法重写
#如果子类自己 没有的方法就调用父类的
# 2. 多继承: __mro__ 方法查询调用的父类顺序
class Student(父类1,父类2):
pass
6. 多态
7. new方法 与 单例设计模式
# 调用__new__ 方法申请内存地址 ,再调用 init 方法填入参数
# 单例设计模式:重写 new 方法,保证创建对象时,对象都是唯一的。即保证内存地址(对象)是唯一的
8. 其他魔法方法
# 内置属性和方法
十五 . 异常概念
1. 系统已定义异常
try: # 如果输入内容不满足条件 不报错,直接走except
b = float(input('请输入一个小数'))
print(b*2)
# except 可以给出多个
except (IOError,NameError):
print('输入的不合法')
except Exception as e:
print('输入的不合法')
except Exception as e:
print('输入的不合法')
# Exception 指的错误类型:typeerror....
except TypeError as e:
print('数据类型错误')
else:
print('没有异常')
try...except...finally...
# 在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally。 比如文件关闭,释放锁,把数据库连接返还给连接池等。
# finally 不管发生什么都会执行finally后面的语句
2. 自定义异常
class LengthError(Exception):
pass
s = input('请输入 --> ')
if len(s) < 3:
# raise 引发一个自定义的异常
raise ShortInputException(len(s), 3)
3. with关键字
# 在进入with代码块时,会自动调用__enter__方法
# 在退出时,自动调用__exit__方法
# 没有处理异常的功能
4. 上下文管理器------with
with语句实质上是一个上下文管理器,with语句后的对象都会有__enter__()和__exit__()方法。
在进入到上下文时,会自动调用__enter__()方法;
程序正常执行完成,或者出现异常中断的时候,都会调用__exit__()方法。
十六 . 模块和包
1. 模块
一个模块就是一个包
import 模块名
from 模块名 import 功能名
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名
2. 自定义模块
# 当你导入一个模块,Python解析器按照搜索路径来查找 py 文件,也就是说我们的 py 文件必须在模块搜索路径的某一个文件夹里。也就是说有自己搜索的路径文件及文件夹
# 所以在习惯上,我们会把自己写的代码放到同一个项目文件夹。
dir(s) # dir 显示出 s 所有的方法和属性
3. __all__
4. __name__
5. 包的使用
一个包即是 含有名字为–init–的 py 文件 的文件夹
十七.迭代器 和 生成器
1. 迭代器
# 判断 num 是否是可迭代对象(Iterable)
isinstance(num,Iterable)
# 判断 num 是否是Person类的实例对象
isinstance(num,Person)
# 使用iter、next 方法 需手动调用
b = iter(a) # 获取对象 a 的迭代器 b
next(a) # 调用 迭代器 b 的 next方法
print(next(a)) # 获取返回的结果,一个print就是一个返回值,相当于for in循环一次
# 自定义 range类
class Range(object):
def __init__(self, end, start, step=1):
if start is not None:
end, start = start, end # 交换值
if start is None:
start = 0
if step == 0:
raise ValueError('Range() arg 3 must not be zero')
self.end = end
self.start = start
self.step = step
def __iter__(self): # 重写__iter__方法
return self
def __next__(self):
if self.start<self.end and self.step<0:
raise StopIteration
x = self.start
self.start += self.step
if self.start <= self.end:
return x
else:
raise StopIteration
# for in 循环的本质是不断调用 next方法
r = Range(1, 5)
for i in r:
print(i)
# 手动调用,几个print就是输出几个返回值
n = iter(m)
print(next(n))
print(next(n))
print(next(n)) # 3个print相当于for in循环了3次
2.生成器
# 生成器是一种特殊的迭代器,结构和函数结构一样
# 生成器的迭代器就是它自己
def number_generator(n):
print('hello')
i = 0
while i < n:
print('呵呵呵')
i += 1
# return i
yield i # 使用关键字 yield 遇见就停止
print('嘿嘿嘿')
# 调用 生成器函数的时候,并没有执行这个函数
G = number_generator(10)
print(G) # 函数里使用 yield 关键字,得到的结果是一个生成器
print('-' * 30)
# 当调用 next 方法,获取下一个数据的时候,才会执行生成器里的代码
# 遇到 关键字 yield 就将 yield 的结果返回,程序停止
x1 = next(G) # G是生成器 也是迭代器,可直接调用 next方法,省略了iteration的使用
print(f'x1的值是{x1}')
# 再一次调用 next 会在上次停留的位置继续执行
x2 = next(G)
print(f'x2的是{x2}')
x3 = next(G)
十八.网络编程
# 使用UDB发送消息
# 使用socket 实现网络连接
import socket
# 创建一个基于UDP连接的socket
send_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
send_socket.close()
# socket函数里面,family 用来指定scoket 的连接方式,通常使用AF_INET,用来建立一个基于网络连接的socket
# type 指定scoket连接的类型,可选 DGRAM ==> UDP STREAM ==> TCP
with socket.socket(socket.AF_INET,socket.SOCK_DGRAM) as s:
# sendto 发送数据,需要两个参数
# data:发送的数据,需要是二进制
# address:要发送到哪个地址,需要的是一个元组
# 元组里又需要两个元素,第0个是IP地址,第1个是端口号
s.sendto('good morning'.encode('utf8'),('10.11.54.110',8080))
# recvfrom 接收消息
# data = s.recvfrom(1024) # 1024 指定接受的字节大小
# print(data) # 接收到的数据类型是一个元组
data, (ip,port) = s.recvfrom(1024) # 将接收到的数据拆包
print(f'接收到了来自{ip}:{port}的消息,内容是{data.decode("utf8")
# UDB聊天
import socket
ip = '10.11.54.110'
port = 8080
msg = input('请输入您要发送的数据:').encode('utf8')
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 如果想要主动的让别人发送消息 必须绑定端口号
s.bind(('10.11.54.88', 8888))
s.sendto(msg,(ip,port))
data ,(s_ip,s_port) = s.recvfrom(1024)
print(f'接收到了来自{s_ip}:{s_port}的消息,内容是:{data.decode("utf8")}')
十九.正则表达式
1.正则表达式
# 正则表达式 是一种特殊的字符序列,通常被用来检索、替换那些符合某个模式(规则)的文本。
# 正则表达式语法
re.match(pattern,string,flags=0)
# pattern:匹配的正则表达式
# string:要匹配的字符串
# flags:标志位,用于规定正则表达式的匹配方式,如:是否匹配大小写,多行匹配
re.search(r'\d', 'abe43e')
# r'\d':匹配字符串'abe43e'中的 \d(数字),'abe43e':要匹配的字符串
# 在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用re模块。 re 模块使 Python 语言拥有全部的正则表达式功能。
improt re
2.正则查找
# 查找方法 match\fullmatch\search\findall\finditer
# 得到的是 re.Match 类型的对像
improt re
# match 只从字符串开头开始匹配 ,只匹配开头,匹配不到返回 None
# re.match(r'H', 'Hello') 查找字符 H
print(re.match(r'H', 'Hello')) # <re.Match object; span=(0, 1), match='H'>
print(re.match(r'e', 'Hello')) # None
# fullmatch 使用正则规则从头开始对整个字符串全部进行匹配
print(re.fullmatch(r'ab\d+', 'ab128cd')) # None 不全是\d,还有字母
print(re.fullmatch(r'ab\d+', 'ab2342130')) # <re.Match object; span=(0, 9), match='ab2342130'>
# search 扫描整个字符串,并返回第一个成功匹配的字符,只匹配一次;找不到就返回 None
# + 表示 该字符有一个或者多个
print(re.search(r'\d', 'abe43e')) # 只匹配一次 数字(\d:表示数字)
print(re.search(r'\d+', 'abe43e')) # 一次或者多次匹配 数字
# finditer 会将字符串里所有匹配到的结果都查询到,得到的结果是一个迭代器 x
# 迭代器 x 里每个元素 又是 一个 re.Match 类型的对象!!!
x = re.finditer(r'3\d+', 'ab128cd347820ef3214ab34x')
for i in x:
print(i)
"""
结果:
<re.Match object; span=(7, 13), match='347820'>
<re.Match object; span=(15, 19), match='3214'>
<re.Match object; span=(21, 23), match='34'>
"""
# findall 得到的结果是一个列表
# 这个列表里保存的是匹配到的结果字符串!!!
word = 'ab128cd347820ef3214ab34x'
y = re.findall(r'3\d+', word)
print(y) # ['347820', '3214', '34']
3. re.Match类型
x = re.search(r'\d+', 'ab98cd34uxm') # x 是一个re.Match 类型的对象
# 用dir(x)获取对象的属性和方法
print(x1.end()) # 获取匹配到的字符串的结束下标
print(x1.endpos) # 整个字符串的长度(最大下标+1)
print(x1.span()) # 得到的结果是一个元组,表示匹配到的字符串的开始(包含)和结束(不包含)下标
print(x1.string) # 查找的完整的字符串
# 使用 group 来获取匹配到的结果字符串!!!
print(x1.group()) # 98 得到的结果是匹配到的字符串!!!
# x1.group() 拿到所有子分组匹配到的字符串组成的一个元组
4.正则表达式里的group
# 正则表达式使用 () 用来进行分组
# (?P<test>b\d+) (c\d+) ,加()是将匹配到的结果分组
# (?P<test>b\d+) 将匹配的 b\d+ 起一个组名
x2 = re.search(r'(b\d+)(c\d+)(?P<zuming>d\d+)e\d+', 'a10b2453c5896d717e123') # 分为 4 个分组
print(x2) # <re.Match object; span=(3, 21), match='b2453c5896d717e123'>
# 'group', 'groups', 'lastgroup', 'groupdict'
# 如果是 0 个分组, 0 可以省略 group(0) <==> group()
print(x2.group(0)) # b2453c5896d717
print(x2.group(1)) # b2453
print(x2.group(2)) # c5896
print(x2.group(3)) # d717
# 最后匹配的一个分组的组名
print(x2.lastgroup) # zuming
# groupdict 是以字典的形式保存有组名的分组数据
print(x2.groupdict()) # {'zuming':'d717'}
print(x2.groupdict()['zuming']) # d717
5. re.compile 的介绍
import re
# 1.和2.的结果一样
# 1.
print(re.search(r'm\d+', 'ab322wm234dasdd'))
# <re.Match object; span=(6, 10), match='m234'>
#2.
pattern = re.compile(r'm\d+')
print(pattern.search('ab322wm234dasdd')) # <re.Match object; span=(6, 10), match='m234'>
6.正则修饰符
# 正则表达式语法
re.match(pattern,string,flags=0)
# flags 是正则修饰符,对正则规则有不同的含义
# re.I ==> 让正则修饰符忽略大小写
print(re.search(r'd', 'gooDokXhi')) # None
print(re.search(r'd', 'goodDokXhi', re.I)) # <re.Match object; span=(3, 4), match='D'>
# re.S ==> 让 '.' 匹配包括换行的任意字符
print(re.findall(r'.', 'a\n1_*/({+')) # 无换行 ['a', '1', '_', '*', '/', '(', '{', '+']
print(re.findall(r'.', 'a\n1_*/({+', re.S)) # 有换行 ['a', '\n', '1', '_', '*', '/', '(', '{', '+']
7.正则匹配规则
# 正则匹配规则
# 1. 数字和字母表示它本身,
# 2. \ 有特殊含义 ,用来做转义
# 3. 大多数字母前面加 \ 转义后,会有特殊含义(重点)
\n 换行 \r回车 \t制表符
\s 匹配空白字符(空格回车tab键,看不到的) \S非空白字符
\d 数字 \D非数字
\w 数字字母和下划线 _ \W非数字字母下划线
# 4. 绝大多数标点符号都有特殊含义(重点|难点)
'.': 匹配 除了 \n 以外的任意字符
'+': 所匹配字符 的出现次数至少为1,一次或多次
# 5. 如果想要表示标点符号本身,需要使用 \ 转义字符
'\.':表示 . 本身
8.符号和标点的特殊含义
import re
# ?:表示字符最多出现一次;让贪婪模式转换成为非贪婪模式 <==> {,1}
print(re.search(r'go?d', 'goood')) # 匹配o最多出现一次,这个结果是 None
# {}: 用来限定字符出现的次数
# {n}:表示字符出现n次
# {,n}:表示字符最多出现n次(包含n次)
# {m,n}:表示字符串出现m(包含)到n(包含)次
# {n,}:表示字符至少出现n次
print(re.search(r'a\d{3}x', 'a519x'))
print(re.search(r'a\d{,3}x', 'ax'))
print(re.search(r'a\d{3,5}x', 'a25367x'))
print(re.search(r'a\d{3,}x', 'a1546x'))
"""
结果:
# <re.Match object; span=(0, 5), match='a519x'>
# <re.Match object; span=(0, 2), match='ax'>
# <re.Match object; span=(0, 7), match='a25367x'>
# <re.Match object; span=(0, 6), match='a1546x'>
"""
# () 用来分组
print(re.search(r'b\d+(c\d+)d\d+', 'a34b12c45d78').group(1))
# 得到的第一个分组是 'c45'
# [] 用来表示区间范围 \d ==>[0-9] \w ==> [0-9a-zA-Z_]
print(re.search(r'x[1-5]+p', 'dskx347pix12312p'))
print(re.search(r's[a-d]+j', 'ewisxyajioesabcj'))
print(re.search(r'p[a-d0-3]+x', 'dpac21x'))
"""
结果:
<re.Match object; span=(9, 16), match='x12312p'>
<re.Match object; span=(11, 16), match='sabcj'>
<re.Match object; span=(1, 7), match='pac21x'>
"""
print(re.findall(r'u[352a]x', 'u3xiu5xpu2xouax'))
# 结果:['u3x', 'u5x', 'u2x', 'uax']
# | 用来表示可选值,和 [] 有区别,通常配合 () 使用
x = re.finditer(r'u(3|5|2|a)x', 'u3xiu5xpu2xouax') # 单个字符时,更加推荐使用 [352a]
for i in x:
print(i.group())
"""
结果:
u3x
u5x
u2x
uax
"""
print(re.findall(r'u[23674]x', 'u23xiu67xlu34x')) # 结果为:None
y = re.finditer(r'u(23|67|34)x', 'u23xiu67xlu34x')
for i in y:
print(i.group())
"""
结果:
u23x
u67x
u34x
"""
# ^ 表示以指定的字符开始; 放在 [] 里,表示取反
print(re.search(r'^st', 'amstp')) # 等价于 re.match(r'st','amstp')
print(re.findall(r'a[^1-5]+x', 'a123xdklsa789xauidsx')) # 匹配1-5之外的数字
# 结果:['a789xauidsx']
# $ 表示以指定的字符结束
print(re.search(r'mp$', 'xdkadskjsmp'))
# 同时使用 ^ 和 $ 等价于 fullmatch
print(re.search(r'^a\d+m$', 'ua94mt'))
print(re.search(r'a\d+m', 'ua94mt'))
print(re.fullmatch(r'a\d+m', 'ua94mt'))
9. 正则替换
# re.sub(pattern,repl,string,count=0)
"""
参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
"""
import re
a = 'a45b7d23x95'
# 将字符串中的数字替换为 T
print(re.sub(r'\d+', 'T', a)) # aTbTdTxT
# 利用lambda函数 将数字扩大2倍
print(re.sub(r'\d+', lambda x: str(int(x.group()) * 2), a))
# 结果:a90b14d46x190
# 定义函数 将数字扩大2倍
def test(x):
data = x.group()
return str(int(data) * 2)
# 结果:a90b14d46x190
10.贪婪模式和非贪婪模式
贪婪模式:匹配尽可能多的字符
非贪婪则相反,总是尝试匹配尽可能少的字符
在*,?,+,{m,n}后面 加上 ? 使贪婪变成非贪婪。
<re.Match object; span=(0, 5), match=‘a519x’>
<re.Match object; span=(0, 2), match=‘ax’>
<re.Match object; span=(0, 7), match=‘a25367x’>
<re.Match object; span=(0, 6), match=‘a1546x’>
“”"
```python
# () 用来分组
print(re.search(r'b\d+(c\d+)d\d+', 'a34b12c45d78').group(1))
# 得到的第一个分组是 'c45'
# [] 用来表示区间范围 \d ==>[0-9] \w ==> [0-9a-zA-Z_]
print(re.search(r'x[1-5]+p', 'dskx347pix12312p'))
print(re.search(r's[a-d]+j', 'ewisxyajioesabcj'))
print(re.search(r'p[a-d0-3]+x', 'dpac21x'))
"""
结果:
<re.Match object; span=(9, 16), match='x12312p'>
<re.Match object; span=(11, 16), match='sabcj'>
<re.Match object; span=(1, 7), match='pac21x'>
"""
print(re.findall(r'u[352a]x', 'u3xiu5xpu2xouax'))
# 结果:['u3x', 'u5x', 'u2x', 'uax']
# | 用来表示可选值,和 [] 有区别,通常配合 () 使用
x = re.finditer(r'u(3|5|2|a)x', 'u3xiu5xpu2xouax') # 单个字符时,更加推荐使用 [352a]
for i in x:
print(i.group())
"""
结果:
u3x
u5x
u2x
uax
"""
print(re.findall(r'u[23674]x', 'u23xiu67xlu34x')) # 结果为:None
y = re.finditer(r'u(23|67|34)x', 'u23xiu67xlu34x')
for i in y:
print(i.group())
"""
结果:
u23x
u67x
u34x
"""
# ^ 表示以指定的字符开始; 放在 [] 里,表示取反
print(re.search(r'^st', 'amstp')) # 等价于 re.match(r'st','amstp')
print(re.findall(r'a[^1-5]+x', 'a123xdklsa789xauidsx')) # 匹配1-5之外的数字
# 结果:['a789xauidsx']
# $ 表示以指定的字符结束
print(re.search(r'mp$', 'xdkadskjsmp'))
# 同时使用 ^ 和 $ 等价于 fullmatch
print(re.search(r'^a\d+m$', 'ua94mt'))
print(re.search(r'a\d+m', 'ua94mt'))
print(re.fullmatch(r'a\d+m', 'ua94mt'))
9. 正则替换
# re.sub(pattern,repl,string,count=0)
"""
参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
"""
import re
a = 'a45b7d23x95'
# 将字符串中的数字替换为 T
print(re.sub(r'\d+', 'T', a)) # aTbTdTxT
# 利用lambda函数 将数字扩大2倍
print(re.sub(r'\d+', lambda x: str(int(x.group()) * 2), a))
# 结果:a90b14d46x190
# 定义函数 将数字扩大2倍
def test(x):
data = x.group()
return str(int(data) * 2)
# 结果:a90b14d46x190
10.贪婪模式和非贪婪模式
贪婪模式:匹配尽可能多的字符
非贪婪则相反,总是尝试匹配尽可能少的字符
在*,?,+,{m,n}后面 加上 ? 使贪婪变成非贪婪。