模块的导入方式的介绍,time模块、datatime模块、calendar模块、collections模块、uuid模块、base64模块、hashlib模块、hmac模块、排列组合、笛卡儿积。
模块:
计算机在开发过程中,代码越写越多,也就也来越难以维护,所以为了编写可维护的代码,我们会把函数进行分组,放在不同的文件里。在python里,一个.py文件就是一个模块。
模块的优点:
- 提高代码的可维护性。
- 提高代码的复用,当模块完成时就可以在其他代码中调用。
- 引用其他模块,包含python内置模块和其他第三方模块
- 避免函数名和变量名等名称冲突。
模块的导入方式
import
直接使用import语句导入标准库的模块:
import sys print(sys.argv) #包含命令行参数的列表 print(sys.path) #自动查找所需模块的路径列表 |
import 语句:
格式:import module1[, module2]
注意:一个模块只会被导入一次,不管执行了多少次import,防止一次次的导入内存中浪费内存
使用模块中的内容:
module.方法/变量/类
from …… import……
作用:从模块中导入一个指定的部分
格式: from modulename import name…
from …… import *
作用:从模块中所有内容全部导入当前命名空间
注意:不应该过多的使用,占用内存太多了。容易导致变量的冲突
模块中的__name__属性:
每个模块都有一个__name__属性,当其值为“__main__”时,表明该模块自身在运行,
否则是被当做模块引入,此时值为模块的名字
作用:模块就是一个可执行的python文件,一个模块被另一个模块引入,想让模块中的
某一程序不执行,我们可以用__name__属性来使程序隐藏该块内码,当自身执行时,在执行‘该块代码
一般程序的其实位置都是从__name__ =="__main__"开始
包:
为了避免模块名的冲突,python又引入了按目录来组织模块的方方 称为包(package)
特点:引入包以后,值顶层的包名不予别人冲突,那么所有的模块都不会与比人冲突
注意:每个包下面都会有一个名为__init__.py的文件,可以导出包里的内容
from 包 import (可以是方法名字 只不过需要有init文件 也可以是模块的名字)
如果包里面的模块相同了
from 包.模块 import 方法
如果方法也相同了
from 包.模块 import 方法 as 变量 # 给其重新命名 之后再去操作。
内置模块:
time 模块:
UTC(世界协调时间):格林尼治时间,世界标准时间。在中国我们UTC+8
DST(夏令时):是一种为了节约能源而人为规定地方时间的制度,一般在天亮早的夏季将时间提前一小时,时间段表示形式:
1.时间戳
以整型或者浮点型表示的 是一个一秒为单位的时间间隔,这个时间的基础是1970年的1月1日零时开始算
2.元组形式
一种python的数据表示,这个元组有9个整形元素,分别表示不同的时间含义
year month(1-12) day(1-31) hours(0-23) minutes(0-59)seconds(0-59)weekday(0-6 0为周一)
Julian day (1-366):表示当前日期在本年是第几天,day in the year
DST flag(-1 or 0 or 1):夏令时格式,0表示正常格式,1表示为夏令时格式,-1表示根据当前的日期时间格式来判定
3.格式化字符串
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化月份名称
%B 本地完整月份名称
%c 本地相应的日期和时间表示
%d 一个月中第几天(01-31)
%H 一天中的第几个小时(24小时制度,00-23)
%I 一天中的第几个小时(12小时制度,01-12)
%j 一年中的第几天(001-366)
%m 月份(01-12)
%M 分钟数(00-59)
%p 本地am或者pm的相应符号
%S 秒(00-59)
%U 一年中的星期数,以星期日为一个星期
%w 一个星期中的第几天(0-6,0表示星期日)
%W 和%U基本相同,以星期一为一个星期
%x 本地相应日期
%X 本地相应时间
%y 去掉世纪的年份(00-99)
%Y 完整的年份
%Z 时区的名字,如果不存在未空字符串
方法:
time():返回房钱的时间戳,浮点数形式,无须传参 t1 = time.time()
gmtime():将时间戳转换为UTC时间元组格式,接收一个浮点型时间戳为参数,如果不传默认为当前时间的时间戳 t2 = time.gmtime()
localtime():将时间戳转换为本地时间元组格式,接收一个浮点型时间戳为参数,如果不传默认为当前时间的时间戳 t3 = time.localtime()
mktime():将本地时间元组转为时间戳,接收一个时间元组 t4 = time.mktime(t3)
asctime():将时间元组格式转为字符串形式,接收一个时间元组,不传默认为localtime时间的时间元组 t5 = time.asctime(t3)
ctime():将时间戳转为字符串,接收一个时间戳,默认值为当前时间戳
t6 = time.ctime()
strftime():将时间元组以指定的格式转换字符串格式没接收一个字符串格式化串,时间元组,不写默认为localtime()
t7 = time.strftime("%Y-%m-%d %X", t3)
strptime(): 将指定格式的时间字符串解析为时间元组,是strftime逆过程, t8 = time.strptime()
sleep():延迟一个时间段,整型或者浮点型
clock():返回当前程序执行时间,Unix系统时钟返回全部运行时间,而windos从第二次开始都是以第一次调用次函数的时间戳为基准,而不是程序开始时间为基准。
tzset():改变本地时区
datatime模块
比time高级了不少,可以理解为 datatime 基于time进行了封装,提供了更实用的函数接口
datatime模块的接口更直观,更容易调用。
模块中的类:
datetime 同时有时间和日期
timedelta 主要用于计算时间跨度
tzinfo 时区相关
time 只关注时间
date 只关注日期
获取当前时间
t1 = datetime.datetime.now()
获取指定时间
t2 = datetime.datetime(199, 10, 1, 8, 8, 8, 0)
将时间转为字符串
t3 = t1.strftime("%Y-%m-%d %X")
将格式化字符串转为datetime对象
t4 = datetime.datetime.strptime(t3, "%Y-%m-%d %X")
时间相减,返回一个时间间隔
t5 = datetime.datetime(199, 10, 1, 8, 8, 8, 0)
t6 = datetime.datetime(199, 10, 2, 8, 8, 8, 0)
t7 = t6 -t5 天数和时间都告诉了 t7.days 间隔天数 t7.second 出去天数的秒数
日历模块 calendar
calendar.month(2018,8)返回某年某月
calendar.calendar(2018) 返回某一年的
calendar.isleap()判断是否是闰年
calendar.monthrange(2018,8)返回某个月的weekday的第一天开始星期和这个月的所有天数
calendar.monthcalendar(2018,8)返回的是这个月的序列 没有的就是0
collections模块
python内建的一个集合模块,提供了许多有用的集合类
namedtuple:命名元组,本质是是一个函数,用它来创建一个自定义的tuple对象
规定tuple元素的个数,并可以用属性而不是索引来引用tuple中的元素,用namedtuple定义一个新的数据类型
from collections import namedtuple
#假设是创建一个xy轴的一个点的位置,如果只是随意的一个元组过一段时间我们就会忘记这个数据的意义。所以我们可以给其起名字,然后下次再遇到时就可以知道这个数据的意义
Point = namedtuple("Point",["x", "y"])
#设置值
point = Point(1,2)
#取值
print(point.x, point.y)
deque模块
在使用list存储数据,按照索引访问数据,但是在插入和删除元素时,会因为元素的费事的增高而变低,为了实现高速的插入和删除操作我们就引用了deque双向列表,适用于栈和队列。
from collections import deque
q = deque([1,2,3,4,5])#创建一个双向的列表
q.append(6)#从右侧添加数据
q.appendleft(0)#从左侧添加数据
q.pop()#从右侧删除数据
q.popleft()#从左侧删除数据
print(q)
defaultdict
在使用dict时,如果引用的key不存在时,会抛出KeyErroer异常。如果希望得到一个默认的值,就使用defaultdict
d1 = {"a":1, "b":2, "c":3}
# print(d1["d"])
print(d1.get("d"))
d2 = defaultdict(lambda :"good")#不存在的话就返回一个good
d2["a"] = 1
print(d2)
print(d2["a"])
print(d2["d"])
print(d2.get("d"))
OrderedDict
字典是无序的,如果想对字典进行迭代就无法保证key值的顺序。采用orderdict 这个的顺序是按照插入时键值对的顺序。
d1 = {"a":1, "b":2, "c":3}
print(d1)
# 顺序是按照键值对插入的顺序
d2 = OrderedDict([("a",[11, 111]),("c",33),("b",22)])
print(d2)
print(d2["a"])
print(d2.get("a"))
Counter
一个简单的计数器,本质上是dict的一个子类计算集合中元素出现的次数。
a = "sunck is a good man"
c = Counter()
print(c)
for ch in a:
c[ch] = c[ch] + 1
print(c)
以字典的形式展示出每个字符出现的次数
uuid模块
概述:
是128位的全局唯一标识符,通常由32字节的字母串表示,它可以保证时间和空间的唯一性,也称为GUID
原理:
通过MAC地址、时间戳、命名空间、随机数、伪随机数来保证生产的ID的唯一性
作用:
随机生成字符串,当成token使用,当成用户账号使用,当成订单号使用等(要求不相同字符串)
算法:
1、uuid1()基于时间戳
有MAC地址,当前时间错,随机数字,可以保证全球范围内的唯一性。但是由于MAC地址的使用时带来安全问题,局域网中可以使用IP来代替MAC
2、uuid2()基于分布式计算环境DCE
算法和uuid1相同,不同的是把时间戳的前四位换位POSIX的UID,实际当中很少使用,注意,Python中没有这个函数
3、uuid3()基于名字和MD5散列值
通过计算名字和命名空间的MD5散列值得到的,保证了同一命名空间中不同名字的唯一性,和不同命名空间的唯一性,但同一命名空间的相同名字生成相同的uuid
4、uuid4()基于随机数
有伪随机数得到的,有一定重复概率的,这个概率并且是可以计算出来的
5、uuid5()基于名字和SAH1散列值
算法和uuid3()相同,不同的是使用SHA1算法
使用经验:
1、python中没有基于DCE的,所以uuid2()可以忽略
2、uuid4()存在概率性重复,由于无映射性,最好不用
3、如果在全局的分布式环境下,最好使用uuid1()
4、若名字的唯一性要求,最好使用uuid3()或uuid5()
import uuid
print(uuid.uuid1())
print(type(uuid.uuid1()))
print(uuid.uuid4())
print(uuid.uuid3(uuid.NAMESPACE_DNS, "sunck"))
print(uuid.uuid3(uuid.NAMESPACE_DNS, "sunck"))
print(uuid.uuid3(uuid.NAMESPACE_DNS, "kaige"))
print(uuid.uuid5(uuid.NAMESPACE_DNS, "sunck"))
base64模块
概述:用记事本打开图片等文件,看到一坨乱码,因为二进制文件包含很多无法显示的内容。所以想让记事本能处理二进制数据,就需要将二进制字符串转换。base64是一种比较常见的二进制编码方法
编码原理:
一个包含64个字符的数组
['A', 'B', ……, 'a', 'b', ……, '0', '1', ……, '+', '/']
对二进制数据进行处理,每个三个字节一组,一组就是3x8=24bit,划为4组,每组正好6bit
得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串
作用:
适用于小段内容的编码,比如数字证书签名,cookie,网页中传输的少量二进制数据
注意:base64是一种通过查表的编码方法,不能用于加密,即使修改了字符对照表页不行。
#编码
s1 = b"sunck is a good ma"
print(base64.b64encode(s1))
#解码
s2 = b"c3VuY2sgaXMgYSBnb29kIG1h"
print(base64.b64decode(s2))
#如果要编码的二进制不是3的倍数,怎么办?
#答:base用\x00字节在末尾补足,在编码的末尾加上1个或2个等号表示补了多少个字节,解码时会自动去掉
s3 = b"sunck is a good man"
print(base64.b64encode(s3))
# 由于标准base64编码后可能出现字符+和/,在URL中就不能直接作为参数
# 提供urlsafe_b64encode编码,保证url的安全,将+和/替换成-和_,提供 urlsafe_b64decode进行url安全解码
s4 = b"sunck is a good m~"
print(base64.b64encode(s4))
print(base64.urlsafe_b64encode(s4))
s5 = b"c3VuY2sgaXMgYSBnb29kIG1-"
print(base64.urlsafe_b64decode(s5))
#由于=字符也可能出现在base64编码中,但是=在url、cookie里面会造成歧义,所以很多base64编码后会把=去掉
s6 = b"abcd"
s8 = base64.b64encode(s6)
print(s8)
# b"abcd" --> b'YWJjZA=='
# b"abcd" --> b'YWJjZA'
s7 = b'YWJjZA=='
print(base64.b64decode(s7))
#可以自定义编码对照表列表中64个字符的排序,这样可以自定义编码,但是通常情况下没有任何必要
hashlib模块
import hashlib
hashlib 模块提供了常见的摘要算法,如MD5,SHA1
摘要算法(又称哈希算法、散列算法):
原理:它通过一个函数,把任意长度的数据转为一个长度固定的数据串(通常用16进制的字符串表示)
MD5
最常见的摘要算法,速度快,生成的结果是128位字节,通常用32位id16进制字符串表示
s1 = b"sunck is a good man"
m5 = hashlib.md5()
m5.update(s1)
print(m5.hexdigest())
如果数据量比较大, 可以分多次调用update,最后的结果是一样的
m6 = hashlib.md5()
m6.update(b'sunck is ')
m6.update(b"a good man")
print(m6.hexdigest())
SHA1
调用SHA1与调用MD5完全一样,SHA1的结果是160bit字节,通常用40位16进制字符串表示
s2 = b"sunck is a nice man"
sh1 = hashlib.sha1()
sh1.update(s2)
print(sh1.hexdigest())
更安全的
SHA256
SHA512
越安全的算法不仅越慢,而且摘要会越长
有没有两个不同的数据通过hash算法后得到了相同的摘要呢?
有这种可能性,因为摘要算法是将无限多的数据映射到有限的集合中,如果两个数据的摘要相同,称之为碰撞。可能出现,但是非常渺茫
应用:
任何允许用户登陆的网站都会存储用户登录的用户名和密码,那么密码一般存储的是原密码的摘要值。
sunck--good明文存到数据中,如果数据库泄露,所有用户信息会暴露
正确的保存口令方式不是存储明文内容,而是存储口令的摘要,当用户登录时,首先会计算用户输入的明文口令的摘要,和数据库中的对比,如果一直说明口令正确,否则一定错误。
hmac模块
实现HMAC算法,是用一个key对数据进行“杂凑”后在记性的hash,使用hmac比hash算法更安全,不同的key会产生不同的hash
对于同一条数据,key不同会得到不同的摘要值
import hmac
s = b"sunck is a good man"
key = b"secret"
h = hmac.new(key, s, digestmod="MD5")
print(h.hexdigest())
itertools模块
import itertools
import time
无限迭代
count(start=0, step=1)
c = itertools.count()
for i in c:
print(i)
time.sleep(1)
cycle(iterable)
把传入的一个序列无限重复下去
cy = itertools.cycle("sunck")
for i in cy:
print(i)
time.sleep(1)
repeat(object[, times])
把一个元素无限重复下去,如果提供了第二个参数,就可以指定重复次数
r = itertools.repeat("sunck", 3)
for i in r:
print(i)
time.sleep(1)
有限迭代
把一组迭代对象串联起来,形成一个更大的迭代器
chain(*iterables)
cha = itertools.chain("ABC", "abc")
for i in cha:
print(i)
time.sleep(1)
把迭代器中相邻的重复元素挑出来放在一起
g = itertools.groupby("AABBBBccdedFFF")
for key, value in g:
print(key, list(value))
time.sleep(1)
排列组合
全排列
从n个不同元素中取出m(m<=n)个元素,按照一定的顺序排成一列,叫做从n个元素中获取m个元素的一个排列。当m==n时,这个排列称为全排列
itertools.permutations(iterable, length)
p = list(itertools.permutations([1,2,3,4], 4))
print(p)
print(len(p))
'''
5! = 1 * 2 * 3 * 4 * 5
0! = 1
1! = 1
从n个中选m个 n! / (n - m)!
4 1 4!/3!
4 2 4!/2!
4 3 4!/1!
4 4 4!/0!
'''
组合
从n个不同的元素中,任意m(m<=n)个元素为一组,叫做从n个不同元素中取出m个元素的组合
itertools.combinations(iterable, length)
c = list(itertools.combinations([1,2,3,4], 3))
print(c)
print(len(c))
'''
4 4 1
4 3 4
4 2 6
4 1 4
n!/m!(n-m)!
'''
排列组合(笛卡尔积)
itertools.product(*iterable, repeat=1)
passwds = list(["".join(x) for x in itertools.product("0123456789", repeat=6)])
print(passwds)
print(len(passwds))
passwds=("".join(x) for x in itertools.product("0123456789QWERTYUIOPASDFGHJKLZXCVBNMq wertyuiopasdfghjklzxcvbnm", repeat=8))
for i in passwds:
print(i)
time.sleep(1)