模块:
计算机在开发过程中,代码越写越多,也就也来越难以维护,所以为了编写可维护的代码,我们会把函数进行分组,放在不同的文件里。在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 *
作用:从模块中所有内容全部导入当前命名空间
注意:不应该过多的使用,占用内存太多了。容易导致变量的冲突
#注意!!两个导入包的区别,以time为例
import time #第一种
time.sleep(0)
from time import time #第二种
time.sleep(0)
from time import * #第三种
sleep(0)
"""两个在导入之后都可以调用sleep但是调用的方法书写格式不同,第一种和第二种是要写上包名,而第三种直接写方法名,
但是在我们日常编写中,我们都是采用前两种种方式,以防止在代码块中命名的重复,和降低代码阅读的难度
注意 如果想要在两个包中能够互相调用的话,采用第一种方式,这种情况一般都是用到自己写的包的互相调用中
"""
模块中的__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():改变本地时区
datetime模块
比time高级了不少,可以理解为 datetime 基于time进行了封装,提供了更实用的函数接口
datetime模块的接口更直观,更容易调用。
模块中的类:
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
Point = namedtuple("Point",["x", "y"])
point = Point(1,2)
print(point.x, point.y)
defaultdict():
在使用dict时,如果引用的key不存在,会抛出KeyError异常,如果希望key不存在时,也能得到一个默认的值,就使用defautdict
from collections import defaultdict
d2 = defaultdict(lambda :"XiaoHa")#默认值不存在就会得到里面的值
d2["a"] = 1
print(d2)
print(d2["a"])
print(d2["d"])
print(d2.get("d"))
除了key值不存在时,返回的是自己设定的值外其他的都和普通的dict方法运用相同。
OrdereDict():
我们平时使用dict时,key值的存放是无序的,对dict进行的带时,无法保存key的顺序。如果需要key值的有序性,就使用OrdereDict
from collections import OrdereDict
d3 = OrdereDict{[("a", [11, 111]), ("b", "22"),("c", "33")]}
print(d3)
print(d3["a"])
print(d3.get("a"))#字典的顺序是按照存入时键值对的顺序,其中也可以放入列表。
Counter():
Counter就是一个简单的计数器,本质上是dict的一个子类,对列表中字符串某个元素在列表中出现的数字统计,在对文章分析的时候这个会用到。
from collections import Counter
a = "XiaoHa say hello world"
c = Counter()
print(c)#一个Counter类型的
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散列值的算法
通过计算名字和命名空间的MD4散列值得到的,保证了同一命名空间中不同名字的唯一性和不同命名空间的唯一性。但同一命名空间的相同名字生成相同的UUID
4、uuid4():基于随机数的算法
由伪随机数得到的,有一定的重复概率,概率是可以计算出来的但是几率太小。
5、uuid5():基于名字和SAH1散列值的算法
算法和uuid3相同,不同的是使用SHA1算法
使用经验:
1、python中没有DCE,所以uuid忽略使用
2、uuid4存在概率性重复,由于无映射性,最好不使用
3、如果在全局的分布式环境下,最好使用uuid1
4、若名字的唯一性要求,最好使用uuid3或uuid5
import uuid
print(uuid.uuid1())
print(uuid.uuid4())
print(uuid.uuid3(uuid.NAMESPACE_DNS,"XiaoHa"))
print(uuid.uuid3(uuid.NAMESPACE_DNS,"XiaoHa"))
print(uuid.uuid3(uuid.NAMESPACE_DNS,"haha"))
print(uuid.uuid5(uuid.NAMESPACE_DNS, "XiaoHa"))
base64模块:
概念:
用记事本打开图片等文件会看到一堆乱码,是因为二进制文件包含很多无法显示的内容,所以想让记事本能处理二进制数据,就需要将二进制字符串转换。base64就是一种常见的二进制编码方式
原理:
一个包含64个字符的数组:["a"-"z","A"-"Z","0"-"9","+","/"]
对二进制数组进行处理,没三个字节一组,一组就是24bit,划为4组,每组6bit,得到四个数字作为索引,然后查找对应的表,得到相应的四个字符,就是编码后的字符串,在末尾如果不够的话会使用=进行补位。
作用:
适用于小段内容的编码,比如数字证书签名,cookie,网页中传输的少量二进制数据。
注意:bsae64是一种通过查表的编码方式,不能用于加密。
import base64
#编码
s1 = b"hello world"
print(base64.b64encode(s1))
#解码
s2 = b"aGVsbG8gd29ybGQ="
print(base64.b64decode(s2))
如果我们要编码的二进制不是3的倍数,base用\x00字节在末尾补足,在编码的末尾我们加上一个或者2个等号表示补了多少字节,解码时会自动去掉。
由于标准base64编码后可能会出现+和/,在URL中不能直接作为参数
提供base64.urlsafe_b64encode()编码,保证url的安全,将+和/替换成-和_,提供base64.urlsafe_b64decode()解码
由于= 字符可能出现在base64编码中,但是=在url、cookie里面会造成歧义,所以很多base64编码会把=去掉
我们可以可以自定义编码对照表列表中64个字符的排序,但是通常是不会有人用的
hashlib模块
提供了常见的摘要算法:如IMD5,SHA1
摘要算法:
又称哈希算法,散列算法。
原理:
它通过一个函数,把任意长度的数据转为一个长度固定的数据串(通常十六进制的字符串表示)
加密:
MD5
最常见的照耀算法,速度快,生成的结果是128位的字节,通常用32位的16进制字符串表示
s1 = b"XiaoHa is a good man"
m5 = hashlib.md5()
m5.updata(s1)
print(m5.hexdigest())
如果信息量比较大,可以分多次调用updata,最后结果一样
SHA1
调用SHA1和调用MD5完全一样,SHA1的结果是160bit字节,通常40位16进制字符串表示
s1 = b"XiaoHa is a good man"
sh1 = hashlib.sha1()
sh1.updata(s1)
print(sh1.hexdigest())
SHA256
SHA512
越安全的算法,不仅越慢,而且摘要会更长 可能会出现两个不同的数据通过HASH算法后得到了相同的摘要,因为摘要算法是将无限多的数据映射到有限的集合中,如果两个数据的摘要相同,称之为碰撞,但是非常渺茫
应用:
任何允许用户登录的网站都会存储用户登录的用户和密码,那么密码一般存储的是原密码的摘要值,如果明文存到数据中,如果数据库泄露,所有用户信息会暴露,正确的保存口令的方式不是存储明文,而是存储口令的摘要,当用户登录时首先会计算用户输入的明文口令的摘要,和数据库中的对比,如果一致说明口令正确否则一定错误。
hmac模块
是使用一个key对数据进行“杂读”后在进行的hash ,使用hmac比hash更安全,不同的key会产生不同的hash。对同一条数据,key不同得到的摘要值不同。
import hmac
s = b"XiaoHa is a good man"
key = b"haha"
h = hmac.new(key, s, digestmod = "MD5")
print(h.hexdigest())
itertools模块:
无限迭代:count(start = 0, step = 1)
cycle(iterable):把传入的序列无限重复下去
repeat(object[, times]):把一个元素无限重复下去,如果提供了第二个参数,就可以指定重复次数
有限迭代:chain(*iterables)
把一组迭代对象串联起来,形成一个迭代对象
import itertools
c = itertools.count()
for i in c:
print(i)
time.sleep(1)
cy = itertools.cycle("XiaoHa")
for i in cy:
print(i)
time.sleep(1)
r = itertools.repeat("XiaoHa",3)
for i in r:
print(i)
time.sleep(1)
cha = itertools.chain("ABC", "abc")
for i in cha:
print(i)
time.sleep(1)
g = itertools.groupby("aavbbbccdebfff")
for key, value in g:
print(key,list(value))
time.sleep(1)
排列组合
全排列 itertools.permutations(iterable,len)
从n个不同的元素中取出m个元素,按照一定的序列排成一列,叫做从n个元素中获取m个元素的一个排列,当m=n时叫做全排列
组合 itertools.combinations(iterable, n)
从n个不同的元素中,任意m个元素为一组,叫做从n个不同元素中取出m个元素的组合
排列组合(笛卡尔积)itertools.product(*iterable, repeat=1, )
#全排列 数学A
p = list(itertools.permutations([1,2,3,4], 4))
print(p)
#组合 数学C
c = list(itertools.combinations([1,2,3,4],4))
print(c)
#排列组合
pc = list(["".join(x) for x in itertools.product("0123456789",repeat=4)])
print(pc)