Python工程化语法
1.模块和包
用于将代码分割成模块和包来包装和分割代码
1.1模块module
Module 模块
1.1.1 基本概念
- 定义:模块是一个Python文件,每个 .py 文件就是一个模块。
- 作用:用于组织代码,避免代码重复,提高复用性。
- 使用:通过 import 语句导入模块中的内容。
1.1.2基本使用
-
定义一个模块
def odd(num): if num % 2==0: return True else: return False
-
导入一个模块
-
导入一个模块到当前程序
import 模块名 [as 模块新名字]
-
导入一个模块内部的部分属性到当前程序
from 模块名 import 模块属性名 [as 属性新名]
-
导入一个模块内部的全部属性到当前程序
from 模块名 import *
-
示例:
from module import odd as odd1
re=odd1(5)
print(re) #False
-
内部属性
两个全局变量,保存的数据就是字符串
__file__ 绑定模块的路径
__name__ 绑定模块的名称
-
如果是主模块则绑定 ‘main’
如果不是主模块则 绑定 xxx.py 中的 xxx 这个模块名import module print(f"|{__name__}|") #|__main__| print(f"|{__file__}|") #|c:\Users\au656\Documents\vscode(c++)\.vscode\模块与包.py|,保存的文件路径
-
模块module中
print(f"|{__name__}|")
-
-
常用用法
#判断是否为主模块来决定是否运行,不是则为子模块,from引进就可以了 if __name__=="__main__": 语句块
1.1.3模块分类
分为系统模块,第三方模块和自定义模块
1.1.3.1系统模块
内置的模块,提供基础功能,比如数学运算、文件操作、网络通信等。
-
常见模块
-
使用示例:
-
math模块:
#math import math if __name__=="__main__": print(math.pi) #3.141592653589793 print(math.sqrt(2)) #1.414213562373095
-
time模块
#time import time time.sleep(2) #让程序暂停2秒 print(time.time()) #1742626843.1191368 为1970年开始全世界统一到现在的时间,单位是ms print(time.localtime()) #time.struct_time(tm_year=2025, tm_mon=3, tm_mday=22, tm_hour=15, tm_min=13, tm_sec=55, tm_wday=5, tm_yday=81, tm_isdst=0) print(time.strftime("%y年%m月%d日%H时%M分%S秒",time.localtime())) #25年03月22日15时13分55秒
-
random模块(重要)
import random print(random.randint(1,10)) # random.randint(a,b) 生产 a~b的随机整数 print(random.random()) # random.random 生成包含0 但不包含1 的浮点数 print(random.choice("SAKANACTION")) # 从一个序列中,随机返回一个元素 L = [1,2,3,4,5,6,7,8,9] print(random.choice(L)) random.shuffle(L) # random.shuffer(x) # 把列表X 打乱 print(L) #输出 4 0.5164610192334719 K 9 [8, 7, 9, 4, 6, 5, 1, 3, 2]
-
os模块
用于操作系统中的文件目录的处理
1.1.3.2第三方模块
第三方提供的模块
以下是一些常用的:
模块 | 功能 | 示例 |
---|---|---|
numpy | 数值计算 | 科学运算、矩阵操作 |
pandas | 数据分析 | 数据清洗与处理 |
matplotlib | 数据可视化 | 绘制图表 |
requests | HTTP请求处理 | 爬取网页内容,调用API |
flask | Web应用框架 | 快速搭建Web服务 |
1.1.3.3自定义模块
- 用户自己编写的模块,用于复用代码。
- 文件名以 .py 结尾,存放自定义的函数、类等
1.2包package
1.2.1基本概念
-
定义:
- 包是包含多个模块的目录。
- 包的本质是一个包含 __init__.py 文件的文件夹。
- 文件 __init__.py 可为空,也可以包含初始化代码。
-
作用:用于组织模块的集合,形成层次化的结构,便于管理大型项目。
-
结构:
my_package / __init__.py module1.py module2.py subpackage / __init__.py module3.py
1.2.2 导入包和子包
- 使用
import
关键字可以导入包和子包,以访问其中的模块和内容。# 同模块的导入规则 import 包名 [as 包别名] import 包名.模块名 [as 模块新名] import 包名.子包名.模块名 [as 模块新名] from 包名 import 模块名 [as 模块新名] from 包名.子包名 import 模块名 [as 模块新名] from 包名.子包名.模块名 import 属性名 [as 属性新名] # 导入包内的所有子包和模块 from 包名 import * from 包名.模块名 import *
1.2.3__init__.py
__init__.py 用于初始化Python包或模块,作用有:
- 标识包目录: 告诉Python解释器当前目录应被视为一个包。
- 执行初始化代码: 可以包含任何代码,通常用于包的初始化操作,如变量初始化、导入模块等。这些代码在包被导入时执行。
- 控制包的导入行为: 通过
__all__
变量明确指定从包中可以导入哪些模块,使用from import *时指只能使用all后的模块。 - 提供包级别的命名空间:
__init__.py
中定义的变量和函数可以在包的模块中共享。 - 批量导入模块: 可以在
__init__.py
文件中批量导入模块,这些模块可以更方便地使用。
# __init__.py 文件示例
# 1. 批量导入系统模块
import os
import sys
import datetime
# 2. 定义包级别的变量
package_variable = "This is a package variable"
# 3. 控制包的导入行为
__all__ = ['module1', 'module2']
# 4. 执行初始化代码
print("Initializing mypackage")
# 注意:这个代码会在包被导入时执行
# 5. 导入包内的模块
from . import module1
from . import module2
2.正则表达式
一个特殊的字符序列,能够检查一个字符串是否与某种模式匹配;内置re模块使Python拥有**正则表达式(regular express)**功能。
2.1字符匹配
正则表达式在网络爬虫、数据分析中有着广泛使用,是很方便的工具
2.1.1方法和功能
方法 | 功能 |
---|---|
match() | 判断一个正则表达式是否从开始处匹配一个字符串 |
search() | 遍历字符串,找到正则表达式匹配的第一个位置,返回匹配对象 |
findall() | 遍历字符串,找到正则表达式匹配的所有位置,并以列表的形式返回。如果给出的正则表达式中包含子组,就会把子组的内容单独返回,如果有多个子组就会以元组的形式返回。 |
finditer() | 遍历字符串,找到正则表达式匹配的所有位置,并以迭代器的形式返回 |
import re
#match()
arr=re.match("sakanaction","sakanaction的新曲《kaiju》大hit")
print(arr) #<re.Match object; span=(0, 11), match='sakanaction'>
#search
arr=re.search("sakanaction","sakanaction是一个日本乐队,sakanaction的新曲《kaiju》大hit")
print(arr.span()) #(0, 11)
#findall()
arr=re.findall("sakanaction","sakanaction是一个日本乐队,sakanaction的新曲《kaiju》大hit")
print(arr) #['sakanaction', 'sakanaction']
#finditer()
arr=re.finditer("sakanaction","sakanaction是一个日本乐队,sakanaction的新曲《kaiju》大hit")
for i in arr:
print(i.span()) #(0, 11) (19, 30)
匹配规则:
- “sakanaction”匹配文本中的“sakanaction”
data=re.findall("sakanaction","sakanaction是一个日本乐队,sakanaction的新曲《kaiju》大hit") print(data) #['sakanaction', 'sakanaction']
- [sakanaction]匹配单个字符
data=re.findall("[sakanaction]","sakanaction是一个日本乐队新曲《kaiju》大hit") print(data) #['s', 'a', 'k', 'a', 'n', 'a', 'c', 't', 'i', 'o', 'n', 'k', 'a', 'i', 'i', 't']
- [^sakanaction]匹配除了sakanaction以外的其他字符
data=re.findall("[^sakanaction]","sakanaction是一个日本乐队新曲《kaiju》大hit") print(data) #['是', '一', '个', '日', '本', '乐', '队', '新', '曲', '《', 'j', 'u', '》', '大', 'h']
- [a-z]匹配a~z的任意字符([0-9]也可以)
data=re.findall("[0-9]sakanaction","0sakanaction是一个日本乐队新曲《kaiju》大hit") print(data) #['0sakanaction']
- .匹配除了换行符以外的任意字符
#. data=re.findall("!sakanaction","0sakanaction是一个日本乐队新曲《kaiju》大hit") print(data) #['!sakanaction'] #.+ 至少为1次 data=re.findall(".+sakanaction","我去!sakanaction是一个日本乐队新曲《kaiju》大hit") print(data) #['我去!sakanaction'] #.? 0/1次 data=re.findall(".?sakanaction","我去?sakanaction是一个日本乐队新曲《kaiju》大hit") print(data) #['?sakanaction']
2.1.2特殊字符
特殊字符 | 含义 |
---|---|
\d | 匹配任何十进制数字;相当于类 [0-9] |
\D | 与 \d 相反,匹配任何非十进制数字的字符;相当于类 0-9 |
\s | 匹配任何空白字符(包含空格、换行符、制表符等);相当于类 [ \t\n\r\f\v] |
\S | 与 \s 相反,匹配任何非空白字符;相当于类 \t\n\r\f\v |
\w | 匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式[a-zA-Z0-9_] |
\W | 于 \w 相反 (注:re.ASCII 标志使得 \w 只能匹配 ASCII 字符) |
\b | 匹配单词的开始或结束 |
\B | 与 \b 相反 |
import re
#\d
text = "sakanaction666,action834"
data = re.findall(r"n\d", text) # 只匹配一个数字
print(data) #['n6', 'n8']
#\D
text = "sakanaction666,action834"
data = re.findall(r"n\D", text) # 只匹配一个非数字
print(data) #['na']
#\s
text = "sakanaction666, action 834"
data = re.findall(r"\saction\s", text) # 匹配一个空白字符
print(data) #[' action ']
\S 略
\w
text = "sakanaction666, action 834"
data = re.findall(r"\waction", text) # 匹配任意一个字符
print(data) #['naction']
\W略
\b
text = "sakanaction666, action 834"
data = re.findall(r"\bsakana", text) # 匹配开头或结束
print(data) #['sakana']
\B略
2.2. 数量控制
控制匹配规则的重复次数
2.2.1 *重复0次或多次
import re
text = "sakanaction666, sakanaction 834"
data = re.findall("sakanaction6*", text)
print(data) #['sakanaction666', 'sakanaction']
2.2.2 +重复1次或多次
import re
text = "sakanaction666, sakanaction 834"
data = re.findall("sakanaction6+", text)
print(data) #['sakanaction666']
2.2.3 ?重复1次或0次
import re
text = "sakanaction666, sakanaction 834"
data = re.findall("sakanaction6?", text)
print(data) #['sakanaction6', 'sakanaction']
2.2.4 {n}重复n次
import re
text = "sakanaction666, sakanaction 834"
data = re.findall("sakanaction6{3}", text)
print(data) #['sakanaction666']
2.2.5 {n,}重复n次或多次
import re
text = "sakanaction666, sakanaction66 834"
data = re.findall("sakanaction6{3,}", text)
print(data) #['sakanaction666']
2.2.6 {n,m}重复n到m次
import re
text = "sakanaction666, sakanaction666666 834"
data = re.findall("sakanaction6{3,5}", text)
print(data) #['sakanaction666']
2.3分组
- ()提取兴趣区域
import re
text = "我最喜欢sakanaction专辑834194, 人气最高的也是专辑8341941"
data = re.findall(r"专辑(\d{6})", text)
print(data) #['834194', '834194']
- (|)提取兴趣区域(| = or)
import re
text = "专辑834售出834 专辑document售出了1000份欸"
data = re.findall(r"专辑(\w{2,}售出\d{3}|\w{2,}售出了\d{3,})", text)
print(data) #['834售出834', 'document售出了1000']
2.4开始和结束
- ^开始
text="sakanaction834是一个日本乐队新曲《kaiju》大hit"
data=re.findall(r"^sakanaction\d+",text)
print(data) #['sakanaction834']
- $结尾
text="sakanaction834是一个日本乐队新曲《kaiju》大hit 这就是834sakanaction"
data=re.findall(r"\d+sakanaction$",text)
print(data) #['834sakanaction']
2.5特殊字符
由于正则表达式中* . \ {} () 等等符号具有特殊含义,如果你指定的字符正好就是这些符号,需要用\进行转义
import re
text = "数学中集合的写法是{2}"
data = re.findall(r"\{2\}", text)
print(data) # ['{2}']
2.6常用方法
2.6.1 re.findall
获取匹配到的所有数据
import re
arr=re.findall("sakanaction","sakanaction是一个日本乐队,sakanaction的新曲《kaiju》大hit")
print(arr) #['sakanaction', 'sakanaction']
2.6.2 re.match
从字符串的起始位置匹配,成功返回一个对象否则返回none。
匹配成功返回对象,对象的方法:
方法 | 功能 |
---|---|
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
import re
arr=re.match("sakanaction","sakanaction的新曲《kaiju》大hit")
print(arr) #<re.Match object; span=(0, 11), match='sakanaction'>
2.6.3 re.search
扫描整个字符串并返回第一个成功匹配的字符串。成功返回一个对象否则返回none
import re
arr=re.search("sakanaction","sakanaction是一个日本乐队,sakanaction的新曲《kaiju》大hit")
print(arr.span()) #(0, 11)
2.6.4 re.sub
替换匹配成功的字符
类似与字符串的replace函数
import re
data=re.sub("sakanaction","鱼韵","我去?sakanaction是一个日本乐队,sakanaction新曲《kaiju》大hit")
print(data) #我去?鱼韵是一个日本乐队,鱼韵新曲《kaiju》大hit
2.6.5 re.split
根据匹配成功的位置对字符串进行分割
import re
data=re.split(r"\s{1,}","我去 sakanaction 新曲 《kaiju》 大hit")
print(data) #['我去', 'sakanaction', '新曲', '《kaiju》', '大hit']
2.6.6 re.finditer
类似findall 但是不会全部返回出来 而是返回迭代器(比如匹配成功了10万个 全部返回就很吃内存了)
import re
arr=re.finditer("sakanaction","sakanaction是一个日本乐队,sakanaction的新曲《kaiju》大hit")
for i in arr:
print(i.span()) #(0, 11) (19, 30)
2.7 常见正则
QQ号:[1 - 9][0 - 9]{4, }(腾讯QQ号从10000开始)
帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
身份证号(15位、18位数字):^\d{15}|\d{18}$
短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$