目录
- 包
- 1.什么是包
- 2.为什么要有包
- 3.包的导入
- 1.import + 包名
- 2.from + 包名 + import + 模块名
- 3.from + 包名.模块名 + import + 成员名
- 4.总结
- 5.绝对导入与相对导入
- time模块
- 1.时间戳
- 2.格式化时间
- 3.结构化时间
- 4.不同格式时间互相转换
- 结构化时间转格式化时间
- 格式化时间转结构化时间
- 结构化时间转时间戳
- 时间戳转结构化时间
- datetime模块
- 1.当前时间
- 2.时间加减
- random模块
- 1.随机0-1的小数
- 2.指定范围随机整数
- 3.打乱随机
- 4.随机取一个数
- 5.只随机一次
- 6.随机取两个数
- hashlib模块
- md5算法
- hamc模块
- typing模块
- 作用
- requests模块
- re模块
- re.findall()
- 元字符
- 1.^
- 2.$以..结尾
- 3..任意字符
- 4.\d数字 获取所有数字
- 5.\D : 非数字
- 6.\w
- 7.\W
- 8.\s 空
- 9.\S
- 二
- 1.+
- 2.?
- 3.*
- 4.[]
- 5.[^]
- 6.[|]
- 7.{2}
- 8.{1,3}
- 贪婪模式 *
- 非贪婪模式(.*?) *
- 了解
- 1.?=\d
- 函数
- 1.compile
- 2.math *
- 3.search *
- 4.split
- 5.sub
- subn
- 补充
- 修饰符
- 分组 *
- 有名分组 *
- 超高级用法
包
1.什么是包
包是模块的一种形式,包的本质就是一个含有.py
的文件的文件夹
2.为什么要有包
开发项目时需要成千上万的python模块,避免模块之间重名,有了包的概念。
- 简单说包就是文件夹,但必须在该文件夹下存在一个名为
__init__.py
的文件 - 每个包的目录下都必须建立一个 _init_.py 的模块,可以是一个空模块,可以写一些初始化代码,其作用就是告诉 Python 要将该目录当成包来处理。
- 包是包含多个模块的文件夹本质是模块,因此包也可含有包。
3.包的导入
包本质是模块,因此导入包和导入模块的语法类似,方法以下三种:
import 包名[.模块名 [as 别名]]
from 包名 import 模块名 [as 别名]
from 包名.模块名 import 成员名 [as 别名]
用 [] 括起来的部分,是可选部分,即在使用时可以忽略。
# 创建一个包first_package,里面有module1.2两个模块
1. #module1.py模块文件
2. display(n):
3. print(n)
5. #module2.py 模块文件
6. class Item:
7. display(self):
8. print("调用模块中类的方法")
1.import + 包名
import first_package.module1
first_package.module1.display(20)
运行代码来使用模块中代码,但使用该模块中的成员时,需添加‘包名.模块名’为前缀,可以用 as 来将前缀作为一个别名
import first_package.module1 as module
module.display(20)
直接导入包ing,并不会将包中所有模块全部导入程序中,只是导入并执行报下的 _init_.py 文件。
2.from + 包名 + import + 模块名
from first_package import module1
module1.display(20)
使用此语法格式导入包中的模块后,在使用去成员时不需要待包名前缀,但需要带模块名前缀
3.from + 包名.模块名 + import + 成员名
用于向程序中导入‘包.模块’中的指定成员。
导入的变量(函数、类),可以直接适应变量名(函数名、类名)调用
from first_package.module1 import display
display(20)
4.总结
1.包就是模块,包用来导入用
2.包是含有__init__.py
的文件夹; 导包就是导入__init__
3.包一定是被当作模块文件导入,模块文件 m1.py/m2.py 的搜索路径以执行文件 包的介绍.py 路径为准
1.函数过多,想要分类导入,提高开发效率
2.新建的一个文件夹,将函数分开成多个文件,放入文件夹内
3.这个文件夹内的.py文件导入函数,需要中转站
4. __init__.py文件,可以作为中转,在里面导入想要导出的模块文件
5. from + 执行文件的所在目录.模块名 + import + 导入函数
6.直接在执行文件中导入__init__文件名 + 函数名
这个含有__init__的文件夹就叫包
5.绝对导入与相对导入
绝对导入必须按照执行文件的搜索路径为基准,是执行文件的路径
# aaa/.py
from aaa.m1 import func1
from aaa.m2 import func2
相对导入则是当前文件夹为根路径
-
.
代表当前被导入文件所在的文件夹 -
..
代表当前被导入文件夹所在的文件夹上一级 -
...
代表当前被导入文件夹所在的文件夹上一级的上一级
time模块
提供了三种不同类型的时间(时间戳),三种不同类型的时间可以相互转换
1.时间戳
time.time()
:1970年1月1日00:00:00开始按秒计算的偏移量
time.sleep(1)
:睡眠一秒
2.格式化时间
time.strftime('%Y-%m-%d %X')
格式化时间表示的是普通字符串格式的时间
print(time.strftime('%Y-%m-%d %X'))
# 2019-09-28 17:44:27
这里时间的连接符是可以更改的
3.结构化时间
time.localtime()
:获得的是结构化的时间,对应打印出来
print(time.localtime())
'''time.struct_time(tm_year=2019, tm_mon=9, tm_mday=28, tm_hour=17, tm_min=44, tm_sec=27, tm_wday=5, tm_yday=271, tm_isdst=0)'''
4.不同格式时间互相转换
结构化时间转格式化时间
struct_time = time.localtime(3600*24*365)
print(time.strftime('%Y-%m-%d %X',struct_time))
# 1971-01-01 08:00:00
格式化时间转结构化时间
format_time = time.strftime('%Y-%m-%d %X')
print(time.strptime(format_time,'%Y-%m-%d %X'))
# time.struct_time(tm_year=2019, tm_mon=9, tm_mday=28, tm_hour=17, tm_min=44, tm_sec=27, tm_wday=5, tm_yday=271, tm_isdst=-1)
结构化时间转时间戳
struct_time = time.localtime(3600*24*365)
print(time.mktime(struct_time))
# 31536000.0
时间戳转结构化时间
time_stamp = time.time()
print(time.localtime(time_stamp))
# time.struct_time(tm_year=2019, tm_mon=9, tm_mday=28, tm_hour=17, tm_min=44, tm_sec=27, tm_wday=5, tm_yday=271, tm_isdst=0)
datetime模块
时间的加减
1.当前时间
datatime.datetime.now()
打印当前时间
2.时间加减
datetime.timedelta()
括号里的时间默认是以天为单位
加时间
print(now + datetime.timedelta(3)) #默认以天为单位 +3天
print(now + datetime.timedelta(weeks=3))
减时间
print(now - datetime.timedelta(hours=3))
print(now + datetime.timedelta(hours=-3))
打印没有毫秒的时间
print(now.replace(year=1949, month=10, day=1, hour=10, minute=1, second=0, microsecond=0))
# 1949-10-01 10:01:00
random模块
随机数
1.随机0-1的小数
random.random()
2.指定范围随机整数
random.randint(-8,3)
随机-8-3的整数
3.打乱随机
lt=[1,2,3]
random.shuffle(lt)
print(lt)
# [2, 1, 3]
4.随机取一个数
print(random.choice(lt))
# 2
5.只随机一次
random.seed(10) # 加数只会随机一次
print(random.random())
6.随机取两个数
print(random.sample([1,'a','c',2,3,4],2))
# [4, 'c']
hashlib模块
对字符加密
md5算法
m = hashlib.md5()
# 将字符转化成哈希数值永不重复,且算法不可逆
m.update(b'say')
# 叠加性
m.update(b'hello') # 981fe96ed23ad8b9554cfeea38cd334a
m.update(b'sayhello') # 981fe96ed23ad8b9554cfeea38cd334a
hamc模块
对字符加密,并加上秘钥(加盐)
import hmac
m = hmac.new(b'maerzi')
# 秘钥 (公司内部的秘钥算出一个序列)
m.update(b'hash123456') # f82317e44545b0ab087109454814b5c4
# 用户密码算法获得的序列
print(m.hexdigest())
# 通过序列得到一个序列
typing模块
与函数联用,控制函数参数的数据类型,提供了基础数据类型之外的数据类型
lt = [1, 2, 3, 4]
print(type(lt) is list)
from typing import Iterable, Iterator # 控制数据类型
def func(x: int, lt: Iterable) -> list:
return [1, 2, 3]
func(10, '123123')
作用
- 类型检查,防止运行时出现参数和返回值类型不符合。
- 作为开发文档附加说明,方便使用者调用时传入和返回参数类型。
- 该模块加入后并不会影响程序的运行,不会报正式的错误,只有提醒。
- Iterable、Iterator:可迭代类型、迭代器类型
- Generator:生成器类型
requests模块
爬虫--》爬数据,模拟浏览器对url发送请求,拿到数据
import requests
response = requests.get('https://ishuo.cn') # 获取网址url
data = response.text
print(data)
re模块
去字符串中找符合某种特点的字符串
re.findall()
*
import re
s='abc123'
res= re.findall('..*?',s)
print(res)
# ['a', 'b', 'c', '1', '2', '3']
元字符
具有特殊意义的字符
1.^
以...开头
s='abcabcc123abc'
res= re.findall('^ab',s)
print(res) #['ab']
res = re.findall('^b',s)
print(res) #[]
2.$
以..结尾
res = re.findall('bc$',s)
print(res) # ['bc']
3..
任意字符
在搜索的字符后面增加一个任意字符并返回abc+(任何字符)
但必须四个字符
s = 'abc abc1ccabcc'#['abc ', 'abc1', 'abcc']
# s = 'abc' # [] 但必须四个字符
res = re.findall('abc.',s)
print(res)
4.\d
数字 获取所有数字
s= 's_9 4k\n'
res = re.findall('\d',s)
print(res) # ['9', '4']
5.\D
: 非数字
包含 字母 下划线 \n
s= 's_9 4k\n'
res = re.findall('\D',s)
print(res) # ['s', '_', ' ', 'k', '\n']
6.\w
非空
查找数字 字母 下划线
s= 's_9 4k\n'
res = re.findall('\w',s)
print(res) #['s', '_', '9', '4', 'k']
7.\W
空
只会查找 空格 \t \n
s= 's_9 4k\n'
res = re.findall('\W',s)
print(res) # [' ', '\n']
8.\s 空
只会查找空格 \t \n
s= 's_9 4k\n'
res = re.findall('\s',s)
print(res)# [' ', '\n']
9.\S
非空
不会查找 空格 \t \n
s= 's_9 4k\n'
res = re.findall('\S',s)
print(res) # ['s', '_', '9', '4', 'k']
二
1.+
至少一个
查找加号前面的字符必须要有至少1个 可以多不能少
# 也就是 a必须有 2个数不限++++
s= 'a2222 dca200a22a'
print(re.findall('a2+',s))
# ['a2222', 'a2', 'a22']
2.?
有 0-1个
查找 ?
前面的一个字符有 0-1个的数 a必须有 2 最多有1个或0个
s= 'a2222 dca200a22a'
print(re.findall('a2?',s))
# ['a2', 'a2', 'a2', 'a']
3.*
0到无穷个
查找 *号前面的数字有0-无穷都行,开头的必须要有
s='sss55saas'
print(re.findall('sa*',s))
# ['s', 's', 's', 'saa', 's']
4.[]
限定取
[]
中括号里的有的就查找 + 后缀
s = 'abc bbc cbc dbc'
print(re.findall('[abx]b', s))
# ['abc', 'bbc']
5.[^]
限定不取
[^]
只要中括号里没有的 + 后缀的
s = 'abc bbc cbc dbc'
print(re.findall('[^abx]b', s))
# [' b', 'cb', 'db']
6.[|]
或
# |或 查找字符
s = 'abcbbcdbc'
print(re.findall('ab|bc', s))
# ['ab', 'bc', 'bc']
7.{2}
限定数量为2
{2}:前面的字符2个 只查找 ab +两个c
# {2}:前面的字符2个 只查找 ab +两个c
s = 'abc abccc abccccc'
print(re.findall('abc{2}', s))
8.{1,3}
限定数量范围
获取 ab + c 的1-3个字符 指定了c字符范围
# {1,3}: 获取 ab + c 的1-3个字符 指定了c字符范围
s = 'abc abcc abccc abccccc'
print(re.findall('abc{1,3}', s))
# ['abc', 'abcc', 'abccc', 'abccc']
贪婪模式 *
.
(任意字符)*
(0-无穷个)
s = 'abcdefgbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbg'
print(re.findall('a.*g', s))
# ['abcdefgbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbg']
非贪婪模式(.*?) *
.(任意字符)*(0-无穷个)?(让他进入非贪婪模式)
s = 'abcdefgbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbg'
print(re.findall('a.*?g', s))
# ['abcdefg']
了解
1.?=\d
不消耗字符串取数字
# a(?=\d) :a后面是数字,但是不要数字,不消耗字符串内容
s = 'a123 aaaa a234 abc'
print(re.findall('a(?=\d)', s)) # ['a', 'a']
print(re.findall('a(?=\w)', s))
# ['a', 'a', 'a', 'a', 'a', 'a']
函数
1.compile
早期不能填模式转换
s = 'abcd abcddd abc'
res = re.compile('abcd*')
print(re.findall(res, s)) #['abcd', 'abcddd', 'abc']
print(re.findall('abcd*', s)) #['abcd', 'abcddd', 'abc']
2.math *
## match: 从开头找一个,找得到就不找了 ;找不到报错 --》
s = 'ab abcddd abc'
res = re.match('abcd*', s)
print(res.group())
3.search *
## search: 从字符串找一个,就不找了
s = 'ab abcddd abc'
res = re.search('abcd*', s)
print(res.group())
4.split
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.split('\d+', s))
5.sub
相当于replace,可以替换
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.sub('\d+', ' ', s))
subn
可以替换,同时查找替换了多少次
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.subn('\d+', ' ', s))
补充
修饰符
re.s
会让.
匹配换行符
s = '''abc
abcabc*abc
'''
print(re.findall('abc.abc', s))
# ['abc*abc']
print(re.findall('abc.abc', s, re.S))
# ['abc\nabc', 'abc*abc']
分组 *
只要括号里的,查找a(.)c(d),所有符合的只要括号里的。
s = 'abc abcd abcdd'
print(re.findall('a(.)c(d)', s))
# [('b', 'd'), ('b', 'd')]
有名分组 *
会将名字和筛选出符合的拼接成字典,?P<name>
是加上的名字
s = 'abc abcd abcdd'
print(re.search('a(?P<name>.)c(?P<name2>d)', s).groupdict())
# {'name': 'b', 'name2': 'd'}
超高级用法
\g<name1>
使有名分组不能删
s = 'abc123abc123' # c123a
print(re.sub('c(\d+)a', ' ', s))
# ab bc123
print(re.sub('c(?P<name1>\d+)a', ' \g<name1> ', s))
# \g<name1>这个东西不能替换掉
# ab 123 bc123
重要
.*?
贪婪和非贪婪
findall
re.S
match和sarch的区别
分组
有名分组:给分组加名字
哪些做了解
杂七杂八的元字符
特殊构造元字符
特殊修饰符