Day22&23&24 python基础---面向对象进阶--常用模块

一,模块的概念

  别人写好的功能放在一个文件里

  内置模块:安装python解析器的时候一起装上的

  第三方模块,扩展模式:需要自己安装

  自定义模块:自己写的py文件

    

  1.序列化模块

    序列:列表,元祖,字符串,bytes

  Q1:什么叫序列化

    把一个数据类型转换成, 字符串,bytes类型的过程就是序列化

  Q2:为什么要把一个数据类型序列化?

    当需要把一个数据类型存储在文件中

    当需要把一个数据类型通过网络传输的时候

  json的优点:在所有语言中都通用

       缺点:只支持非常少的数据类型,对数据类型的约束很苛刻:

          字典的key必须是字符串,且所有的字符串都必须是用""表示

          只支持:数字 字符串 列表 字典

   应用场景:在网络操作中,以及多语言环境中,要传递字典、数字、字符串、列表等简单的数据类型的时候使用

import json
stu = {'name':'小明','sex':'male'}
ret = json.dumps(stu)      #序列化过程
lis = [1,2,3,4,5,6]
lst = json.dumps(lis)
print(stu,type(stu))
print(ret,type(ret))
print(lst,type(lst))

a = json.loads(ret)        #反序列化的过程
b = json.loads(lst)
print('a-->',a,type(a))
print('b-->',b,type(b))

  文件操作间的序列化与反序列化:

#dump和load比较适合存取单个数据量的较大的字典或列表,否则最好使用dumps和loads
import json
dic = {'name':'小明','sex':'male'}
with open('json_file','w',encoding='utf-8') as f:
    json.dump(dic,f,ensure_ascii=False)   #可以多次往一个文件中dump,但是不能多次load,否则报错
                                          #ensure_ascii参数默认为True,传入False,中文字符默认以中文的形式传入文件
with open('json_file','r',encoding='utf-8') as f:
    dic = json.load(f)
print(dic,dic['name'])

   json格式化输出

#json格式化
import json
data = {'username':['李华','二愣子'],'sex':'male','age':16}
json_dic2 = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False)
print(json_dic2)

  pickle的优点:

      操作文件必须以+b模式打开

      在load的时候,如果这个要被load的内容所在的类不在内存中,会报错

      pickle支持多次dump和多次load(需要异常处理)

      支持几乎所有的python数据类型

      缺点:只有python语言支持 

import pickle
stu = {'name':'小明','sex':'male',1:('a','b')}
ret = pickle.dumps(stu)   #以bytes形式序列化
print(ret)
d = pickle.loads(ret)     #反序列化后,pickle几乎完全支持python的数据类型,所以int类型的键,和元组都能支持
print('d--->',d,type(d)) 

  文件操作间的序列化与反序列化:

import pickle
class Course():
    def __init__(self,name,price):
        self.name = name
        self.price = price
python = Course('python',29800)
linux = Course('linux',25800)
mysql = Course('mysql',18000)
ret1 = pickle.dumps(python)
ret2 = pickle.dumps(linux)
ret3 = pickle.dumps(mysql)
print(ret1)
print(ret2)
print(ret3)

p = pickle.loads(ret1)
a = pickle.loads(ret2)
d = pickle.loads(ret3)
print(p.name,p.price)
print(a.name,a.price)
print(d.name,d.price)

with open('pickle_file','wb') as f:
    pickle.dump(python,f)  #dump序列化对象,可传入一个文件句柄
    # f.write(ret1)
with open('pickle_file','rb') as f:
    course = pickle.load(f)   #load反序列化对象,可传入一个文件句柄
    # ret = f.read()      
    # course = pickle.loads(ret)
print(course.name)
#多次dump序列化传入对象,并多次load反序列化读取对象
import pickle
class Course():
    def __init__(self,name,price):
        self.name = name
        self.price = price
python = Course('python',29800)
linux = Course('linux',25800)
mysql = Course('mysql',18000)

def my_dump(course):
    with open('pickle_file','ab') as f:
        pickle.dump(course,f)
my_dump(python)
my_dump(linux)
my_dump(mysql)

with open('pickle','rb') as f:
    while 1:
        try:
            content = pickle.load(f)
            print(content.name)
        except EOFError:  #若读取不到数据会报错,所以需要异常处理
            break

  2.时间模块(time)

  格式化时间:str数据类型的时间,例:'2018年9月4日 9时10分20秒'

        时间字符串是人能够看懂的时间

  时间戳时间:浮点数,秒为单位

    #1970 1.1 00:00:00  英国伦敦时间

    #1970 1.1 00:00:00 东8时区(北京时间)

    时间戳是计算机能够识别的时间

  结构化时间:元组

    是用来操作时间的

#时间戳-->结构化时间
#time.gmtime(时间戳)  #UTC时间,与英国伦敦当地时间一致
#time.localtime(时间戳)  #当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时

print(time.gmtime(1500000000))  #可传入时间戳显示,该时间戳的结构化时间(UTC)
print(time.localtime(1500000000))    #不传值,默认是当期时间


#结构化时间-->时间戳
time_tuple = time.localtime(1500000000)
print(time.mktime(time_tuple))
#结构化时间-->字符串时间
#time.strftime("格式定义","结构化时间")  结构化时间参数若不传,则显示当前时间
print(time.strftime('%Y-%m-%d %X'))   
#时间戳-->结构化时间-->字符串时间
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(1500000000)))

#字符串时间-->结构化时间-->时间戳
#time.strptime(时间字符串,字符串对应格式)
time.strptime('2018-9-1','%Y-%m-%d') #具体时间不传,默认为0
str_time = '2018-8-8'
struct_time = time.strptime(str_time,'%Y-%m-%d')
print(struct_time)
timestamp = time.mktime(struct_time)
print(timestamp)

#实例:
# 写函数,计算本月1号的时间戳时间
# 通过我拿到的这个时间,能迅速的知道我现在所在时间的年 月
def get_timestamp():
    fmt_time = time.strftime('%Y-%m-1')   #结构化时间-->字符串时间
    struct = time.strptime(fmt_time,'%Y-%m-%d')  #字符串时间-->结构化时间
    res = time.mktime(struct)     #结构化时间-->时间戳
    return res
ret = get_timestamp()
print(ret)

  3.随机数模块

import random
#取随机小数 *
print(random.random())   #(0,1)0-1范围内,不包括0,1
print(random.uniform(2,3))  #(n,m)n-m范围内,不包括n,m

#取随机整数 ****
print(random.randint(1,2))   #[1,2] 闭区间,包括2
print(random.randrange(1,2))  #[1,2) 开区间 不包括2
print(random.randrange(1,100,2))   #隔一个取一个

#从一个列表中随机抽取 ****
lst = [1,2,3,4,5,('a','b'),'cc','dd']
ret = random.choice(lst)  
print(ret)
ret = random.choice(range(100))
print(ret)
#从一个列表中随机抽3个
ret = random.sample(lst,3)
print(ret)  #返回一个列表

#乱序 ***
random.shuffle(lst)  #将有序对象乱序
print(lst)
#实例:
import random
def get_code(n=6,alph_flag = True):
    code = ''
    for i in range(n):
        c = str(random.randint(0,9))
        if alph_flag:
            alpha_upper = chr(random.randint(65,90)) #大写字母的ascii码 
            alpha_lower = chr(random.randint(97,122)) #小写字母的ascii码 
            c = random.choice([c,alpha_upper,alpha_lower])
        code += c
    return code
ret = get_code()
print(ret)

  4.os模块:操作系统相关模块

import os
os.mkdir('dirname')  #创建目录
os.makedirs('dirname1/dirname')  #创建递归目录

#只能删掉空文件夹
os.rmdir('dirname')
os.removedirs('dirname1/dirname2') #先从最底的目录开始删除

print(os.listdir('file')) #显示文件中所有的文件夹和文件的名,包括隐藏文件

print(os.stat('file')) #主要用作查看文件最后修改时间

# 转换为绝对路径
print(os.path.abspath('file'))
print(os.path.abspath('file'))

#切分目录,和文件名
path = 'file'
ret = os.path.split(path)
print(ret)
#切分目录,和文件名,并返回目录
ret1 = os.path.dirname(path)
print(ret1)
#切分目录,和文件名,并返回文件名
ret2 = os.path.basename(path)
print(ret2)

#判断目标文件是否存在,返回bool值
res = os.path.exists('file')
print(res)

#判断文件或目录,返回bool
print(os.path.isfile('file'))
print(os.path.isdir('file'))

#目录拼接
ret = os.path.join('file')
ret = os.path.abspath(ret)  #规范化
print(ret)

#获取文件最后访问时间
os.path.getatime('file')
#获取文件最后修改的时间
os.path.getmtime('file')
#获取文件创建时间
os.path.getctime('file')

#获取文件的大小(字节) windows 4096文件的信息,扩一倍
                    #   linux/mac 文件夹占的大小 32/64
size = os.path.getsize('file/dirname')
print(size)
size = os.path.getsize('file')  #只能看文件的占用的空间,不是所有文件的大小
print(size)

#以字符串的形式来执行操作系统的命令
os.system('bash command')

#以字符串的形式来执行操作系统的命令,并返回
os.popen('bash command').read()

#显示执行这个文件时所在的目录
os.getcwd()

#切换目录
print(__file__) #当前的绝对目录
os.chdir('file')

  5.sys模块:是与python解释器交互的一个接口

import sys 
#sys.argv 
print(sys.argv)  #命令行参数List,第一个元素是程序本身路径

#sys.path
print(sys.path) #import模块,遍历这个列表,寻址模块的路径
#一个模块能否被导入,就看这个模块所在的目录在不在sys.path路径中
#内置模块和第三方扩展模块都需要我们处理sys.path就可以直接使用
#自定义的模块的导入工作需要自己手动的修改sys.path?

#内置模块目录
# 'C:\xxxx\Python36\lib'
# 第三方模块目录
# 'D:xxx\lib\site-packages'
#sys.modules {查看当前内存空间中所有的模块:和这个模块的内存空间}

  6.collections模式:根据基础数据类做一些扩展

#内置的数据类型
    # int  float complex
    # str  list   tuple
    # dict set
#基础数据类型
    # int  float complex
    # str  list   tuple
    # dict
#set不是基础数据类型

  有序字典:py3.6以后自动有序

# 有序字典  py3.6以后自动有序
dic = {'a':1}
d = dict([('a',1),('k1','v1')])     #正常创建字典的写法
print(d)

from collections import OrderedDict
dd = OrderedDict([('a',1),('k1','v1')])
print(dd)
for k in dd:
    print(k,dd[k])
dd['k2'] = 'v2'
print(dd)

  默认字典:

# 默认字典
from collections import defaultdict
d = defaultdict(list)  #传入一个可调用参数,并执行,返回的值作为value的值
print(d['a'])
d['b'].append(123)  #增加一个键值对,并在d['b']中的列表追加元素
print(d)
d = {}
d['a']  #增加一个键值对

func = lambda :'default'
d = defaultdict(func)   #自定义默认字典的默认value
print(d['kkk'])
d['k'] = 'vvvvv'    #修改字典的value
print(d)

  可命名元组:

    可命名元组非常类似一个只有属性没有方法的类型

#可命名元组
from collections import namedtuple
birth = namedtuple('Struct_time',['year','month','day'])
b1 = birth(2018,9,5)
print(type(b1))
print(b1.year)
print(b1.month)
print(b1.day)
print(b1)

#可命名元组非常类似一个只有属性没有方法的类
#['year','month','day']是对象属性名
#Struct_time是类 的名字
#这个类最大的特点就是一旦实例化 不能修改属性的值

  双端队列:双端队列可以弥补list的缺点

#双端队列
#
数据结构:链表原理 from collections import deque dq = deque() #创建一个双端队列 dq.append(1) #从末尾添加一个值 dq.append(2) dq.appendleft(3) #从开头添加一个值 print(dq) print(dq.pop()) #从末位弹出一个值 print(dq.popleft()) #从开头弹出一个值

#队列:先进先出,后进后出
import queue
q = queue.Queue() # 创建队列
q.put(1) #存一个值
q.put(2)
q.put('aaa')
q.put([1,2,3])
q.put({'k':'v'})
print(q.get()) #取一个值
print(q.get())

  Counter: Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。

c = Counter('abcdeabcdabcaba')
print c
输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})

   

  7.hashlib模块:内部有不止一种算法的模块  *****

    1.由于数据的不安全性,为了保证用户的信息绝对的安全,所以所有人的密码都不能以明文的形式存储,而应该经过适当的处理以密文的形式存起来。否则可能会被撞库破解

    2.大家去计算这个密文,使用的是相同的算法

    3.这个算法不可逆

    4.不同的字符串通过这个算法的计算得到的密文总是不同的

    5.相同的算法,相同的字符串,获得的结果总是相同(适用于不同的语言,不同的环境:操作系统,版本,时间)

#常规使用方式:
md5_obj = hashlib.md5()   #md5_obj不能重复使用
md5_obj.update('alex3714'.encode('utf-8'))
ret = md5_obj.hexdigest()

  hashlib摘要算法:具有多种算法,

  md5算法:32位16进制的数学字符组成的字符串

    应用最广大的摘要算法

    效率高,相对不复杂,如果只是传统摘要不安全

  sha算法:40位的16位进制的数字字符组成的字符串

    sha算法要比md5算法更复杂

    shan:n的数字越大算法越复杂,耗时越久,结果越长,越安全

sha_obj = hashlib.sha512()   
sha_obj.update('alex3714'.encode('utf-8'))
ret = sha_obj.hexdigest()
print(len(ret))


def get_md5(s):
    md5_obj = hashlib.md5()   #md5_obj只能用一次,所有写成函数比较方便
    md5_obj.update(s.encode('utf-8'))
    ret = md5_obj.hexdigest()
    return ret
print(get_md5('alex3714'))
#多次update与一次性update结果是一样的
md51 = hashlib.md5()
md51.update(b'666666')    
md51.update(b'999999')   # 1ad2daed30c3862a267485c7cc9aacce
print(md51.hexdigest())

md51 = hashlib.md5()
md51.update(b'666666999999') # 1ad2daed30c3862a267485c7cc9aacce
print(md51.hexdigest())

  加盐:固定的盐,会导致恶意注册的用户密码泄露

def get_md5(s):
    md5_obj = hashlib.md5(''.encode('utf-8'))
    md5_obj.update(s.encode('utf-8'))
    ret = md5_obj.hexdigest()
    return ret

  动态加盐:每个用户都有一个固定的并且互不相同的盐

def get_md5(user,s):
    md5_obj = hashlib.md5(user.encode('utf-8'))
    md5_obj.update(s.encode('utf-8'))
    ret = md5_obj.hexdigest()
    return ret

print(get_md5('alex','alex3714'))  #使用用户名作为盐

  应用场景:

#登录验证
usr = input('username:').strip() passwd = input('passwd:').strip() def get_md5(s): md5_obj = hashlib.md5() md5_obj.update(s.encode('utf-8')) ret = md5_obj.hexdigest() return ret with open('userinfo',encoding='utf-8') as f: for line in f: u,p = line.strip().split('|') if u == usr and p == get_md5(passwd): print('登录成功') break else: print('用户或密码不正确')
# 文件的一致性校验
# 给一个文件中的所有内容进行摘要算法得到一个md5的结果
# 下载的是视频、或者大文件
# 应该是以rb的形式来读 读出来的都是bytes
# 并且不能按行读 也不能一次性读出来
import os
import hashlib
def get_file_md5(file_path,buffer = 1024):
    md5_obj = hashlib.md5()
    file_size = os.path.getsize(file_path)  #先确认文件大小是否一致
    with open(file_path,'rb') as f:
        while file_size:
            content = f.read(buffer)   #默认每次取1024个字节
            file_size -= len(content) 
            md5_obj.update(content)
    return md5_obj.hexdigest()

print(get_file_md5( r'file')) # 路径里不能有空格

  8.配置文件:

    当在开发环境的程序上线到生成环境或者生产环境时,往往需要修改文件,可以使用配置文件对需要操作的文件进行管理   

#生成配置文件
import configparser
config = configparser.ConfigParser()  #相当于实例化一个对象
config["DEFAULT"] = {'ServerAliveInterval': '45',   #添加属性
                      'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11':'yes'
                     }
config['bitbucket.org'] = {'User':'hg'}
config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}
with open('example.ini', 'w') as configfile:   #写入:生成配置文件
   config.write(configfile)
#查看配置文件
import configparser
config = configparser.ConfigParser()
print(config.sections())        #  []
config.read('example.ini')     #加载配置文件
print(config.sections())        #   ['bitbucket.org', 'topsecret.server.com']

print('bytebong.com' in config) # False
print('bitbucket.org' in config) # True
print(config['bitbucket.org']["user"])  # hg
print(config['DEFAULT']['Compression']) #yes
print(config['topsecret.server.com']['ForwardX11'])  #no
print(config['bitbucket.org'])          #<Section: bitbucket.org>
for key in config['bitbucket.org']:     # 注意,有default会默认default的键
    print(key)
print(config.options('bitbucket.org'))  # 同for循环,找到'bitbucket.org'下所有键
print(config.items('bitbucket.org'))    #找到'bitbucket.org'下所有键值对
print(config.get('bitbucket.org','compression')) # yes       get方法Section下的key对应的value
#配置文件的增删改
import configparser
config = configparser.ConfigParser()
config.read('example.ini')
config.add_section('yuan')
config.remove_section('bitbucket.org')
config.remove_option('topsecret.server.com',"forwardx11")
config.set('topsecret.server.com','k1','11111')
config.set('yuan','k2','22222')
config.write(open('new2.ini', "w"))

  9.logging模块

  Q1:什么是日志?

    无处不在的,所有的程序都必须记录日志

日志的主要应用:
例:
# 1.给用户看的
    # 购物软件
    # 视频软件
    # 银行卡
# 2.给内部人员看的
    # 给技术人员看的
        # 计算器
        # 500个小表达式
        # 一些计算过程、或者是一些操作过程需要记录下来
        # 程序出现bug的时候 来帮助我们记录过程 排除错误
    # 给非技术人员看的
        # 学校、公司的软件
            # 谁在什么时候做了什么事儿,删除操作
import logging
logging.basicConfig(level=logging.INFO)   #显示优先级
logging.debug('debug message')    # 计算或者工作的细节
logging.info('info message')      # 记录一些用户的增删改查的操作
logging.warning('input a string type') # 警告操作
logging.error('error message')     # 错误操作
logging.critical('critical message')  # 批判的 直接导致程序出错退出的
# 简单配置
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%c',
                    filename='test.log')
logging.warning('input a string type') # 警告操作
logging.error('EOF ERROR ') # 警告操作
logging.info('6666') # 警告操作
# 对象的配置
    # 解决简单配置的中文问题
    # 可以同时向文件和屏幕输出内容

# 先创建一个log对象 logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# 还要创建一个控制文件输出的文件操作符
fh = logging.FileHandler('mylog.log')
# 还要创建一个控制屏幕输出的屏幕操作符
sh = logging.StreamHandler()
# 要创建一个格式
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fmt2 = logging.Formatter('%(asctime)s - %(name)s[line:%(lineno)d] - %(levelname)s - %(message)s')

# 文件操作符 绑定一个 格式
fh.setFormatter(fmt)
# 屏幕操作符 绑定一个 格式
sh.setFormatter(fmt2)
sh.setLevel(logging.WARNING)
# logger对象来绑定:文件操作符, 屏幕操作符
logger.addHandler(sh)
logger.addHandler(fh)


logger.debug('debug message')    # 计算或者工作的细节
logger.info('info message')      # 记录一些用户的增删改查的操作
logger.warning('input a string type') # 警告操作
logger.error('error message')     # 错误操作
logger.critical('critical message')  # 批判的 直接导致程序出错退出的

 

原文地址:https://www.cnblogs.com/lianyeah/p/9584926.html