9.28 模块

1.包==模块

拿来导入用的,包是含有__init__的文件夹,导包就是导入init;

包一定是被当作模块文件的导入,模块文件(m1.py/m2.py)的搜索路径以执行文件(包的介绍.py)路径为准

9.28 模块

如下我们建一层包:

扩展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
上一篇:MySQL数据库MyISAM和InnoDB存储引擎的比较


下一篇:9.28 包/time/datetime/random/hashlib/hmac/typing/requests/re模块