1.包==模块
拿来导入用的,包是含有__init__
的文件夹,导包就是导入init;
包一定是被当作模块文件的导入,模块文件(m1.py/m2.py)的搜索路径以执行文件(包的介绍.py)路径为准
如下我们建一层包:
扩展aaa.py模块,需要建立一个aaa的目录文件,并且删除aaa.py文件,将aaa.py修改成m1.py和m2.py两个文件,让模块功能的使用方法不变
#m1.py
def f1():
print('f1')
def f2():
print('f2')
#m2.py
def f3():
print('f3')
def f4():
print('f4')
#aaa\__init__.py
from aaa.m1 import *
from aaa.m2 import *
#run.py
import aaa
print(aaa.f1)
print(aaa.f3)
两层包
#m3.py
def f5():
print('f5')
def f6():
print('f6')
#m4.py
def f7():
print('f7')
def f8():
print('f8')
包的作用:当模块内部函数过多,为了方便管理模块,把一个模块划分成多个模块,但是又不能改变导入方式,把多个模块放入一个包内。
绝对导入:
#bbb\__init__.py
from aaa.bbb.m3 import *
from aaa.bbb.m4 import *
相对导入:
.表示当前文件夹下文件
..表示父文件夹下文件
...表示爷爷文件夹下文件
from .m3 import *
from .m4 import *
#run.py
import aaa
print(aaa.f5)
2.time模块
提供了三种不同类型的时间,不同类型之间可以相互转换
import time
print(time.time()) #时间戳
print(time.strftime("%Y-%m-%d %X")) #格式化时间--》字符串格式的时间
print(time.localtime()) #结构化时间
#1.结构化时间-->格式化时间
struct_time=time.localtime(3600*24*365)
print(time.strftime("%Y-%m-%d %X",struct_time))
#2.格式化时间-->结构化时间
format_time=time.strftime("%Y-%m-%d %X")
print(time.strptime(format_time,"%Y-%m-%d %X"))
#3.结构化时间-->时间戳
struct_time=time.localtime(3600*24*365)
print(time.mktime(struct_time))
#4.时间戳-->结构化时间
time_stamp=time.time()
print(time.localtime(time_stamp))
start=time.time()
time.sleep(3)
end=time.time()
print(end-start) #3.000171661376953
3.datetime模块
时间的加减
import datetime
now=datetime.datetime.now()
print(now)
#默认3天
print(now+datetime.timedelta(3))
#加3周
print(now+datetime.timedelta(weeks=3))
#加3小时
print(now+datetime.timedelta(hours=3))
#减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))
运行结果:
2019-09-28 17:01:20.139233
2019-10-01 17:01:20.139233
2019-10-19 17:01:20.139233
2019-09-28 20:01:20.139233
2019-09-28 14:01:20.139233
2019-09-28 14:01:20.139233
1949-10-01 10:01:00
4.random模块
随机数
import random
#0-1
print(random.random())
#[1-3]生成随机数,包括1和3
print(random.randint(1,3))
#打乱顺序
lt=[1,2,3]
random.shuffle(lt)
print(lt)
#随机选择一个数
print(random.choice(lt))
#列表元素任意n个元素的集合
print(random.sample([1,'a','c',2,3,4],2))
运行结果:
0.33954512687219873
3
[3, 2, 1]
1
[1, 'a']
5.hashlib和hmac模块
hashlib模块:对字符加密
hmac模块:对字符加密,并且加上密钥
1.hash算法:
m=hashlib.md5()
m.update('hello'.encode('utf8'))
print(m.hexdigest())
m.update('hash'.encode('utf8'))
print(m.hexdigest())
m2=hashlib.md5()
m2.update('hellohash'.encode('utf8'))
print(m2.hexdigest())
m3=hashlib.md5()
m3.update('hello'.encode('utf8'))
print(m3.hexdigest())
运行结果:
5d41402abc4b2a76b9719d911017c592
97fa850988687b8ceb12d773347f7712
97fa850988687b8ceb12d773347f7712
5d41402abc4b2a76b9719d911017c592
hash加密算法可以反解,所以并不好用
hash_pwd = '0562b36c3c5a3925dbe3c4d32a4f2ba2'
pwd_list = [
'hash3714',
'hash1313',
'hash94139413',
'hash123456',
'123456hash',
'h123ash',
]
def make_pwd_dic(pwd_list):
dic={}
for pwd in pwd_list:
m=hashlib.md5()
m.update(pwd.encode('utf8'))
dic[pwd]=m.hexdigest()
return dic
def break_code(hash_pwd,pwd_dic):
for k,v in pwd_dic.items():
if v==hash_pwd:
print('hash的微信密码是=》 %s' %k)
break_code(hash_pwd,make_pwd_dic(pwd_list))
运行结果:
hash的微信密码是=》 hash123456
2.hmac模块:有密钥的加密,很难被盗取密码
如果要保证hmac模块最终结果一致,必须保证:
1.hmac.new括号内指定的初始key一样
2.无论update多少次,校验的内容累加到一起是一样的内容
import hmac
#注意hamc模块只接受二进制数据的加密
h1=hmac.new(b'hash')
h1.update(b'hello')
h1.update(b'world')
print(h1.hexdigest())
m=hmac.new(b'maerxzfj')
m.update(b'hash123456')
print(m.hexdigest())
m=hmac.new(b'sausjsnn c$$#($&')
m.update(b'hash123546')
print(m.hexdigest())
运行结果:
905f549c5722b5850d602862c34a763e
74e176bfc472dd6ef997014ad8664354
50c0598a05acda467d406497b210ca06
6.typing模块
与函数联用,控制函数的数据类型,提供了基础数据类型之外的数据类型
from typing import List,Tuple,Dict
def add(a:int,string:str,f:float,
b:bool)->Tuple[List,Tuple,Dict,bool]:
list1=list(range(a))
tup=(string,string,string)
d={"a":f}
b1=b
return list1,tup,d,b1
print(add(5,"hhhh",2.3,False))
在传入参数时通过“参数名:类型”的形式声明参数的类型;
返回结果通过“->结果类型“的形式声明结果的类型
在调用的时候如果参数的类型不正确pycharm会有提醒,但不会影响程序的运行
对于如list列表等,还可以规定得具体一些,如:“->list[str]"规定返回的是列表,并且元素是字符串
from typing import List
def func(a:int,string:str)->List[int or str]:
list1=[]
list1.append(a)
list1.append(string)
return list1
7.request模块
爬虫-->模拟浏览器对URL发送请求,拿到数据
正则re:从大的字符串中挑选出 具有某种形状特点的字符串
.*?表示所有的都要
import requests
response=requests.get('https://ishuo.cn')
data=response.text
import re
content_list=[]
content_res=re.findall('<div class="content">(.*?)</div>',data)
for i in content_res:
if i.startswith('<ul>'):
continue
content_list.append(i)
title_list = re.findall('</span><a href="/subject/.*?">(.*?)</a>', data)
title_content_dict={k:v for k,v in zip(title_list,content_list)}
with open('duanzi.txt','w',encoding='utf8') as fw:
for k,v in title_content_dict.items():
fw.write(f'{v}:\n{k}\n\n')
8.re模块
import re
# s='去字符串找符合某种特点的字符串'
# res=re.findall('',s)
# print(res)
#元字符
s='abcdbdc'
#^:以···开头
print(re.findall('^ab',s)) #['ab']
print(re.findall('^bc',s)) #[]
#$:以···结尾
s='abcdabc'
print(re.findall('bc$',s)) #['bc']
print(re.findall('ab$',s)) #[]
#.:任意字符
s='ajkjsbb哄dm'
print(re.findall('sbb.',s)) #['sbb哄']
#\d:数字
s='akjsd3947jk'
print(re.findall('\d',s)) #['3', '9', '4', '7']
#\w:非空,数字字母下划线
s='akjsda_23 34hd'
print(re.findall('\w',s)) #['a', 'k', 'j', 's', 'd', 'a', '_', '2', '3', '3', '4', 'h', 'd']
#\s:空,空格/\t/\n
s='aliswd_23 42jl'
print(re.findall('\s',s)) #[' ']
#\D:非数字
s='akba3947skjd'
print(re.findall('\D',s)) #['a', 'k', 'b', 'a', 's', 'k', 'j', 'd']
#\W:空
s='skdksj_23 42328jl'
print(re.findall('\W',s)) #[' ', ' ']
#\S:非空
s='advd_484 09kjhf'
print(re.findall('\S',s)) #['a', 'd', 'v', 'd', '_', '4', '8', '4', '0', '9', 'k', 'j', 'h', 'f']
#+:匹配前一个字符1次或者无限次:
s='abcdddd abcd abc'
print(re.findall('abcd+',s)) #['abcdddd', 'abcd']
#?:匹配前一个字符0或1次
s='abcdddd abcd abc'
print(re.findall('abcd?',s)) #['abcd', 'abcd', 'abc']
#*:匹配前一个字符0次或者无限次
s='abcddddddd abcd abc'
print(re.findall('abcd*',s)) #['abcddddddd', 'abcd', 'abc']
#[]:中括号内的都可以
s='abc bbc cbc dbc'
print(re.findall('[abc]bc',s)) #['abc', 'bbc', 'cbc']
#[^]:中括号的都不可以
s='abc bbc cbc dbc'
print(re.findall('[^abc]bc',s)) #['dbc']
#|:或(如果|没有被包括在()内,则它的范围是整个正则表达式)
s='abc bbc dbc'
print(re.findall('abc|bbc',s)) #['abc', 'bbc']
#{2}:匹配前一个字符2次
s='abccabc abccc'
print(re.findall('abc{2}',s)) #['abcc', 'abcc']
#贪婪模式
#.(任意字符)*(0-无穷个)
s='abcdjfjdsgvvvvvvvvvvvvvvg'
print(re.findall('a.*g',s)) #['abcdjfjdsgvvvvvvvvvvvvvvg']
#非贪婪模式
#.(任意字符)*(0-无穷个)?(让他进入非贪婪模式)
s='abcdjfjdsgvvvvvvvvvvvvvvg'
print(re.findall('a.*?g',s)) #['abcdjfjdsg']
# a(?=\d) :a后面是数字,但是不要数字,不消耗字符串内容
s = 'a123 aaaa a234 abc'
# a1 aa
# aa
# aa a2 ab
print(re.findall('a(?=\d)', s))
print(re.findall('a(?=\w)', s))
#bug
#.(任意字符)*(0-无穷个)?(让他进入非贪婪模式)
s='anbddbn'
print(re.findall('.*?',s))
#匹配邮箱
s= '#@#@#@nickchen121@163.com$$$$////nick@qq.com$$#$#$[]]2287273393@162.com@$2423423lksdlfj#'
# \w(字母/数字/下划线)+(0-无穷个)@ \w(字母/数字/下划线)+(0-无穷个).com
print(re.findall('\w+@\w+.com', s))
# 函数
## compile
s = 'abcd abcddd abc'
# res = re.compile('abcd*')
email_pattern = re.compile('\w+@\w+.com')
phone_patter = re.compile('\d{13}')
print(re.findall(email_pattern, s))
print(re.findall('abcd*', s))
# ## match: 从开头找一个,找得到就不找了 ;找不到报错 --》
# s = 'ab abcddd abc'
# res = re.match('abcd*', s)
# print(res.group())
## search: 从字符串找一个,就不找了
s = 'ab abcddd abc'
res = re.search('abcd*', s)
print(res.group())
## split
s = 'ab23423abcddd234234abcasdfjlasjdk234l23lk4j2kl34kl25k3j2kl3j5lkj'
print(re.split('\d+', s))
## 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']
## 分组 --> 只要括号里的(*****)
s = 'abc abcd abcdd'
print(re.findall('a(.)c(d)', s))
## 有名分组(了解)
s = 'abc abcd abcdd'
print(re.search('a(?P<name>.)c(?P<name2>d)', s).groupdict())
# 超高级用法
s = 'abc123abc123' # c123a
print(re.sub('c(\d+)a', ' ', s))
print(re.sub('c(?P<name1>\d+)a', ' \g<name1> ', s)) # \g<name1>这个东西不能替换掉
#(*******)
# .*?
# 贪婪和非贪婪
# findall
# re.S
# match和sarch的区别
# 分组
# 有名分组:给分组加名字
运行结果:
['a', 'a']
['a', 'a', 'a', 'a', 'a', 'a']
['', '', '', '', '', '', '', '']
['nickchen121@163.com', 'nick@qq.com', '2287273393@162.com']
[]
['abcd', 'abcddd', 'abc']
abcddd
['ab', 'abcddd', 'abcasdfjlasjdk', 'l', 'lk', 'j', 'kl', 'kl', 'k', 'j', 'kl', 'j', 'lkj']
ab abcddd abcasdfjlasjdk l lk j kl kl k j kl j lkj
('ab abcddd abcasdfjlasjdk l lk j kl kl k j kl j lkj', 12)
['abc*abc']
['abc\nabc', 'abc*abc']
[('b', 'd'), ('b', 'd')]
{'name': 'b', 'name2': 'd'}
ab bc123
ab 123 bc123