Python模块、迭代器、正则表达式
一、Python模块
在我们编程的时候,先创建一个 .py 文件,这个文件就称之为 一个模块 Module。
使用模块的优点:
模块化编程,多文件编程
1.模块的使用
import语句
想要B.py文件中,使用A.py文件,只需要在B.py文件中使用关键字import导入即可。
import A
# 若A是一个包的话,可以这样写
import A.函数名
from ···import···语句
在python中,导入一个模块/文件通常使用关键字import,若是只想导入一个模块某个属性或方法,我们可以使用 from ... import ...语句。
语法格式
from 模块名/包名 import 属性名, 函数名
二、包
随着模块数目的增多,把所有模块不加区分地放到一起就显得非常不合理了,于是Python为我们提供了一种把模块组织到一起的方法,即创建一个包。
因为包是模块,所以包的使用和普通模块的使用方式是一样的。
1.定义
模块 就是 一个 .py 文件
包 就是一个包含 __init__.py文件的 文件夹,文件夹中可以包含子包或者模块。
创建包的目的不是为了运行,而是为了被导入使用,包的本质就是模块,因此可以将包当做模块来导入。
包是不能像普通模块那样被执行代码,所以包提供了一个__init__.py文件,导入包就会执行__init__.py文件,这也是__init__.py文件存在的意义。
2.导入自定义包
导入自定义的包,必须确保包在Python的搜索路径中 ,Python在导入包时会查找特定的目录列表,这个列表通常包括:
- 当前脚本所在的目录。
- 环境变量PYTHONPATH中指定的目录。
-
- 找到包的绝对路径
- 鼠标右键电脑,选择属性,选择高级系统设置
- 在用户变量或环境变量中找到 PYTHONPATH 【若没有就在环境变量中新建,有就编辑】
- 将包的路径粘贴进去,多个路径之间用 英文分号隔开
- 点击 确定 确定 确定
- 退出pycharm,再次打开pycharm,通过sys.path查看是否能搜索到这个包
- 然后就开始使用这个自定义包吧
- Python安装目录中的库目录,如Lib/site-packages。
为了确保你的自定义包可以被导入,你需要确保它的目录在上述列表中的一个。最常见的方法是将你的包放在当前脚本所在的目录或一个子目录中,或者将包的目录添加到PYTHONPATH环境变量中。
3.Python常用标准库
Python 标准库非常庞大,所提供的模块涉及范围十分广泛,使用标准库我们可以让您轻松地完成各种任务。
下面是一些Python3中常用的标准库。
模块名称 | 模块描述 |
os | os 模块提供了许多与操作系统交互的函数,例如创建、移动和删除文件和目录,以及访问环境变量等。 |
sys | sys 模块提供了与 Python 解释器和系统相关的功能,例如解释器的版本和路径,以及与 stdin、stdout 和 stderr 相关的信息。 |
time | time 模块提供了处理时间的函数,例如获取当前时间、格式化日期和时间、计时等。 |
datetime | datetime 模块提供了更高级的日期和时间处理函数,例如处理时区、计算时间差、计算日期差等。 |
math | math 模块提供了数学函数,例如三角函数、对数函数、指数函数、常数等。 |
json | json 模块提供了 JSON 编码和解码函数,可以将 Python 对象转换为 JSON 格式,并从 JSON 格式中解析出 Python 对象。 |
numpy | 一个用于维度数组计算的库 |
opencv | 一个用于计算机视觉的库 |
matplotlib | 一个用于数据可视化的库(绘图) |
scikit-learn | 一个用于机器学习的库 |
tensorflow | 一个用于深度学习的库 |
threading | 一个用于设置多线程的库 |
三、迭代器
迭代是python访问集合中元素的一种方式,迭代器是一个可以记住遍历的位置的对象。
举例:
使用map()函数,将一个函数作用于一个序列中的所有元素,并返回一个迭代器——对迭代器可以再次转换成list tuple set等等等
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不能后退。
迭代器有两个基本的方法:iter() 和 next()。
s = "ABCD"
print(type(s))
# iter() 方法 把序列转换成 迭代器
iter1 = iter(s)
print(type(iter1))
# next() 方法 获取迭代器的下一个元素 【只能往前不能后退】
try:
while True:
print(next(iter1))
except StopIteration:
print("迭代已结束")
list1 = [1, 2, 3, 4, 5]
it1 = iter(list1)
print(next(it1))
print(next(it1))
for i in it1:
print(i)
1.创建一个迭代器
把一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next() 。
- iter() 方法返回一个特殊的迭代器对象,这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
- next() 方法会返回下一个迭代器对象。
# 创建一个返回数字的迭代器,起始值为10,逐步递增10
# 也就是说起始值是10,步长值为10
class MyNum:
def __iter__(self):
self.a = 10
return self
def __next__(self):
x = self.a
self.a += 10
return x
# 实例化对象
my_class = MyNum()
my_iter = iter(my_class)
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))
四、生成器
在python中,使用了 yield 的函数就被称为——生成器。
yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
与普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单的理解【生成器就是一个迭代器】。
每次使用yield语句生产一个值之后,函数都将暂停执行【内存释放出来】,等待再次唤醒。
yield语句和return语句的差别就在于yield语句返回的是可迭代对象,而return返回的是不可迭代对象。
每次调用生成器的next()方法或者使用for或while循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇见yield语句。
def creat1(n):
while n>0:
yield n
n -= 1
create_iter = creat1(5)
print(next(create_iter))
for i in create_iter:
print(i)
生成器的优势是它们是按需生成值,避免一次性生成大量数据并占用大量内存,此外生成器还可以与其他迭代工具(如for循环)无缝衔接配合使用,提供了更加简洁和高效的迭代方式。
五、正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。re模块使 Python 语言拥有全部的正则表达式功能。
s = "C:\\a\\b\\c"
print(s)
# 正则表达式中遇见 \ 为转义字符,自动转义
# 若在前面加 r 说明是原生字符串,不转义
s1 = r"C:\\a\\b\\c"
print(s1)
1 re.match函数
re.match 是从字符串的起始位置匹配一个模式,匹配不成功就返回None。
语法格式:re.match(pattern, string, flags=0)
参数:
pattern 需要匹配的正则表达式
string 匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式,
如:是否区分大小写,多行匹配等
若匹配到了数据,就可以使用group(num) 或 groups() 来提取数据了。
group(num=0) 匹配整个字符串,可以设置参数
groups() 返回一个元组,包含所有小组字符串的元组
import re
# match从开始位置匹配
ret = re.match('abc', "abc world abc")
print(ret.group())
2 re.search函数
re.search 扫描整个字符串并返回第一个成功匹配的字符串。
import re
s1 = 'abc world abc'
s2 = 'hello abc world abc hahaha'
# search扫描整个字符串,返回第一个匹配的结果
set = re.search('abc', s2)
print(set, set.group())
3 re.findall函数
re.findall 匹配整个字符串,返回string中所有与pattern相匹配的全部子串,返回形式为数组
import re
s1 = 'abc world abc'
s2 = 'hello abc world abc hahaha'
# findall 扫描整个字符串,返回所有匹配的结果
fet = re.findall('abc', s2)
print(fet)
4 matchr、search、findall的区别
- re.match 从首字母匹配,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None。
- re.search 匹配整个字符串,直到找到一个对应匹配【若有多个,也只返回第一个】。
- re.findall 返回匹配到的所有子串。
5 正则表达式修饰符 - 可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
re.I | 使匹配对大小写不敏感。 |
re.L | 做本地化识别(locale-aware)匹配。 |
re.M | 多行匹配,影响 ^ 和 $。 |
re.S | 使 . 匹配包括换行在内的所有字符。 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B。 |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
import re
s = 'Good good study, Day day up'
ret = re.findall('good', s, re.I)
print(ret)
6 正则表达式模式
模式字符串使用特殊的语法来表示一个正则表达式。
- 字母和数字表示他们自身。
- 一个正则表达式模式中的字母和数字匹配同样的字符串。
- 多数字母和数字前加一个反斜杠时会拥有不同的含义。
- 标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
- 反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。
import re
s = '__ 888 abc 666 &&&&&'
ret1 = re.findall('.', s)
ret2 = re.findall('[h6]', s)
ret3 = re.findall(r'\d', s)
ret4 = re.findall(r'\D', s)
ret5 = re.findall(r'\w', s)
ret6 = re.findall(r'\W', s)
print(ret6)
import re
#匹配出一个字符串第一个字母为大写字符,后面都是小写字母并且这些小写字母可有可无
def fun1(s:str):
ret = re.match(r'[A-Z][a-z]*', s)
if ret:
print(ret.group())
else:
print("匹配不成功")
s = 'Abcd777'
fun1(s)
#匹配变量名是否有效
def fun2(name:str):
ret = re.match(r'[A-Za-z_]+[\w]*', name)
if ret:
print(ret.group())
else:
print("变量命名不合法")
name = '_a '
fun2(name)
#匹配出6位密码,可以是大小写英文字母、数字、下划线
#匹配出,8到20位的密码,可以是大小写英文字母、数字、下划线
def fun3(pwd:str):
ret = re.match(r'\w{8,20}', pwd)
if ret:
print(ret.group())
else:
print("密码不正确")
fun3('12345')
import re
#匹配163.com的邮箱地址
# 以^确定开头
# 通过$来确定末尾
myemail = 'abcdefg@163.com'
ret = re.match(r'^\w{4,20}@163\.com$', myemail)
print(ret.group())
import re
#匹配出163、126、qq邮箱
myemail = '2042856895@qq.com'
ret = re.match(r'^\w{4,20}@(163|126|qq)\.com$', myemail)
print(ret.group())
#匹配出<html><h1>www.bawei.com</h1></html>
ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", "<html><h1>www.hqyj.com</h1></html>")
print(ret.group())
#匹配出<html><h1>www.bawei.com</h1></html>
ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.hqyj.com</h1></html>")
print(ret.group())
7 注意贪婪和非贪婪
贪婪是尝试匹配尽可能多的字符。
非贪婪是尝试匹配尽可能少的字符。
解决方式:非贪婪操作符”?”,用在"*","+","?"的后面,要求正则匹配的越少越好。
import re
s = 'abbcdef123456'
ret = re.match(r'\w+', s)
print(ret.group())
# 输出结果:abbcdef123456
ret = re.match(r'\w+?', s)
print(ret.group())
# 输出结果:a
8 re.split函数
功能是分割
import re
s = 'user:zhangsan pwd:888666'
ret = re.split(r':| ', s)
print(ret)
9 re.sub函数
功能是替换
import re
s = 'i am zhangsan, i am 18 year, i like eat'
ret = re.sub(r"i", "I", s)
print(ret)