Python学习笔记第五周

目录

  一、基础概念

    1、模块定义

    2、包的定义

    3、导入包的本质

    4、导入模块的本质

    5、导入方法

    6、import的本质

    7、导入优化

    8、模块分类

    9、标准库介绍

      1、time与datetime

      2、random模块

      3、os模块

      4、sys模块

      5、shutil模块

      6、shelve模块

      7、XML模块

      8、Pyyaml模块

      9、configParser模块

      10、hashlib模块

      11、re模块

      12、collections模块

      13、subprocess模块

      14、logging模块

    10、二分法

    11、冒泡排序

    12、时间复杂度

    13、深拷贝

 

一、基础概念:

  1、模块定义

  本质就是.py结尾的python文件(文件名:test.py 对应模块名: test),用来从逻辑上组织python代码(变量、函数、类、逻辑)

  2、包的定义

  用来从逻辑上组织模块的,本质就是一个目录(必须带有一个名字叫__init__.py的文件)

  3、导入包的本质

  执行包目录下所在的__init__.py文件

  4、导入模块的本质

  将该模块的python文件在导入的程序中通过解释器去解释一遍

  5、导入方法

    1、import module_name

    2、import module_name1,module_name2.....

    3、from module_name import func_name (as   func1_name)  #可以对导入的函数起别名,为了避免与本文件的函数重名导致功能没法实现

 

  6、import的本质

  导入模块本质就是找到这个文件,并且把python文件解释一遍,其中import test 表示    test=‘test.py   all code’  把该test.py文件全部解释一遍,而from test import m m=‘test.py about m code’  表示从test.py文件中取出关于m的代码在本文件中解释一遍

 

  7、导入优化

  通常情况下,使用import module_name 如果在其中总是使用test函数,这样每次在使用时会实现检查test函数在module_name模块中是否存在,为了提高效率,可以使用from module_name import test方法导入该函数,相当于直接将test函数在这里直接解释了一编,提高运行效率

 

  8、模块分类

    1、标准库也叫内置模块

    2、开源模块也叫第三方模块

    3、自定义模块

  9、标准库介绍

    1、time与datetime

时间戳,以秒为单位

      time.time()函数,以秒来计算

print(time.time())  #time.time不需要提供任何参数,表示自1970年1月1日到现在经过多少秒
#输出:
1487733672.621412

  

      元组方式表示时间struct_time,包括了9个元素

      time.localtime()#如果里面没有提供任何参数,会表示当前时间, 如果里面提供已秒为单位的数字,会显示对应其对应时间

print(time.localtime())
#输出
time.struct_time(tm_year=2017, tm_mon=2, tm_mday=22, tm_hour=14, tm_min=34, tm_sec=7, tm_wday=2, tm_yday=53, tm_isdst=0)#其中wday代表本周第几天,yday代表本年的第几天,而lsdst代表夏令时
#DST:夏令时
#UTC:世界标准时间

      time.timezone #以秒的格式表示时区

print(time.timezone)
#输出
-28800           #28800/3600=8表示东八区

      time.daylight#是否使用夏令时

print(time.daylight)
#输出
0

      time.sleep()#其中跟参数表示暂停运行几秒

time.sleep(3)

      time.gmtime与locatime

      两者都是表示以元组形式表示时间,同时都以秒为所传参数,其中gmtime表示UTC时间,而localtime表示本地时间

print(time.gmtime())
print(time.gmtime(394049430))
#输出
time.struct_time(tm_year=2017, tm_mon=2, tm_mday=22, tm_hour=6, tm_min=53, tm_sec=56, tm_wday=2, tm_yday=53, tm_isdst=0)
time.struct_time(tm_year=1982, tm_mon=6, tm_mday=27, tm_hour=18, tm_min=10, tm_sec=30, tm_wday=6, tm_yday=178, tm_isdst=0)
print(time.localtime())
print(time.localtime(394049430))
#输出
time.struct_time(tm_year=2017, tm_mon=2, tm_mday=22, tm_hour=14, tm_min=54, tm_sec=57, tm_wday=2, tm_yday=53, tm_isdst=0)
time.struct_time(tm_year=1982, tm_mon=6, tm_mday=28, tm_hour=2, tm_min=10, tm_sec=30, tm_wday=0, tm_yday=179, tm_isdst=0)
x = time.localtime()
print(x.tm_year)  #同理,在得到的strcut_time中可以根据参数取不同的值
#输出
2017

 

      time.mktime()#直接传入元组的形式,变为对应的秒

x = time.localtime(394049430)
print(x)
print(time.mktime(x)) #通过传入已元组形式的时间,转换成对应的秒
#输出
time.struct_time(tm_year=1982, tm_mon=6, tm_mday=28, tm_hour=2, tm_min=10, tm_sec=30, tm_wday=0, tm_yday=179, tm_isdst=0)
394049430.0

  

      time.strftime()#将struct_time转成格式化的时间字符串

 

x = time.localtime(394049430)
print(time.strftime('%Y-%m-%d %H:%M:%S', x))#%Y代表四位的年,%y代表两位表示的年,%m代表月,%M代表分钟,%H代表小时,%S代表秒 %w代表这种的第几天
#输出
1982-06-28 02:10:30

      time.strptime()#将格式化的时间字符串转成struct_time

x = time.localtime(394049430)
y = time.strftime('%y-%m-%d %H:%M:%S', x)
print(time.strptime(y,'%%m-%d %H:%M:%S'))# 前面为格式化的时间字符串,后面是对应的格式,可以将该格式化时间字符串变为struct_time元组,格式只要匹配就可以,没有顺序要求例如:time.strptime("02-20 14:08:34 2017", "%m-%d %H:%M:%S %Y")
#输出
time.struct_time(tm_year=1982, tm_mon=6, tm_mday=28, tm_hour=2, tm_min=10, tm_sec=30, tm_wday=0, tm_yday=179, tm_isdst=-1)

      strftime('格式',struct_time(元组格式))  --->转换成格式化时间字符串

      strptime('格式化时间字符串',‘格式’)  -----> 转成成struct_time

 

      转换关系:

        时间戳转成struct_time:gmtime、localtime

        struct_time转成时间戳:mktime

        struct_time转成格式化时间字符串:strftime

        格式化时间字符串转成struct_time:strptime

 

      time.asctime()#将struct_time转成格式化时间字符串,格式为%a %b %d  %H:%M:%S %Y,其中%a表示星期,%b表示月,如果asctime没有传递参数,默认会导入localtime()的结果

print(time.asctime())
x = time.localtime(394049430)
print(time.asctime(x))
#输出
Wed Feb 22 15:44:21 2017
Mon Jun 28 02:10:30 1982

 

      time.ctime()将时间戳转成为%a %b %d  %H:%M:%S %Y,其中%a表示星期,%b表示月

print(time.ctime()) #如果没参数传递,会将locatime转成成的秒传进去
x = time.time()
print(time.ctime(x))  #传递进来的是时间戳,为秒
#输出
Wed Feb 22 15:48:25 2017
Wed Feb 22 15:48:25 2017

 

      datetime模块:

        datetime.datetime.now()#获取当前时间

print(datetime.datetime.now())
#输出
2017-02-22 15:52:24.551932

        datetime.datetime.now()+datetime.timedelta(3) #默认是三天后的时间

print(datetime.datetime.now()+datetime.timedelta(3))
#输出
2017-02-25 15:54:03.199349

        datetime.datetime.now()+datetime.timedelta(-3)#三天前的时间

print(datetime.datetime.now()+datetime.timedelta(-3))
#输出
2017-02-19 15:54:59.262861

         datetime.datetime.now()+datetime.timedelta(hours=3)#三小时后的时间

print(datetime.datetime.now()+datetime.timedelta(hours=3))
#输出
2017-02-22 19:04:30.683096

        datetime.datetime.now()+datetime.timedelta(hours=-3)#三小时前的时间

print(datetime.datetime.now()+datetime.timedelta(hours=-3))
#输出
2017-02-22 13:05:11.410832

        当前时间替换time.replace()

c_time= datetime.datetime.now()
print(c_time)

r_time = c_time.replace(minute=3,hour=2)
print(r_time)
#输出
2017-02-22 16:08:55.694556
2017-02-22 02:03:55.694556

  

 

 

    2、random模块

import random

print(random.random())  #random()函数会在0-1之间随机取值
#输出
0.28605143730067417

print(random.randint(1,3)) #从整数中随机取值,得到的值均为1-3之间,1和3均有机会取到
#输出
3

print(random.randrange(1,3))#随机取1-2的整数,不会取到3
#输出
2


print(random.choice('abcde'))  #choice表示从序列中取值,序列包括字符串 元组  列表  字典
#输出
#b
print(random.choice([4,3,2,4]))
#输出
3
print(random.choice((4,3,2,4)))
#输出
4

print(random.sample('hello word',4))  #随机取四个数字
#输出
#['r', 'l', 'w', 'h']

print(random.uniform(1,3))   #手工设置random.random的取值范围,默认只是0-1之间,通过uniform方法可以做到在任意范围
#输出
2.07789196870395


item = [1,2,3,4,5,6,7,8]
random.shuffle(item)
print(item)
#输出
[5, 2, 3, 8, 6, 4, 1, 7]

    例子:

      验证码

 

import  random

checkcode = ''


for i in range(1,6):
    x = random.randint(0,9) #取0-9随机数
    if x == i:
        x = chr(random.randint(65,90)) #将随机取一个数字然后转换成ascii码
    else:
        x = random.randint(0,9)
    checkcode += str(x)  #添加x到字符串中
print(checkcode)

 

    3、os模块

>>> import os
>>> os.getcwd()  #获取当前路径
'/Users/Gavin'
>>> os.chdir('/Users')  #修改当前路径
>>> os.getcwd()
'/Users'
>>> os.curdir  #获取当前目录
'.'
>>> os.pardir  #获取上一级目录
'..'
>>> os.makedirs('/Users/Gavin/Desktop/a/b/c')  #创建目录,就算没有父级目录页会递归创建
>>> os.removedirs('/Users/Gavin/Desktop/a/b/c')#删除目录,如果父集目录没有文件也会随之删除
os.mkdir('/Users/Gavin/Desktop/a/b/c')#如果创建的目录中没有父集目录会报错
Traceback (most recent call last):
  File "", line 1, in 
FileNotFoundError: [Errno 2] No such file or directory: '/Users/Gavin/Desktop/a/b/c'
>>>os.mkdir('/Users/Gavin/Desktop/a')
>>>os.rmdir('/Users/Gavin/Desktop/a')#删除创建的目录
>>>os.listdir('/Users/Gavin/Desktop')#列出目录中的文件以及子目录
>>>os.remove('/Users/Gavin/Desktop/ä¸两ç½网å合å¹并.xlsx')#删除对应的文件
>>>os.rename('/Users/Gavin/Desktop/oldname.doc','/Users/Gavin/Desktop/newname.doc')#修改文件名
>>>os.stat('/Users/Gavin/Desktop/newname.doc')
os.stat_result(st_mode=33152, st_ino=40047776, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=116224, st_atime=1487753837, st_mtime=1487753837, st_ctime=1487753837)
>>> os.sep  #显示特定系统的目录分隔符
'/'
>>> os.linesep #显示特定系统的换行符
'\n'
>>> os.pathsep#显示特定系统的路径分隔符
':'
 os.environ  #显示环境变量
environ({'SHELL': '/bin/bash', 'SHLVL': '1', 'PWD': '/Users/Gavin', 'TMPDIR'})
>>> os.name
'posix'
os.system('ls -l')  #执行系统bash命令
total 2992
drwx------    3 Gavin  staff      102 10 29 11:42 Applications
drwx------+  35 Gavin  staff     1190  2 22 22:10 Desktop
>>> os.path.abspath('__file__')  #查找文件的绝对路径
'/Users/Gavin/__file__'
>>> os.path.split('/Users/Gavin')  #os.path.split会将字符串通过/分割为两部分,不管文件或者路径是否存在
('/Users', 'Gavin')
>>> os.path.split('a/b')
('a', 'b')
>>> os.path.dirname(os.path.abspath('__file__'))  #os.path.dirname显示文件所在路径
'/Users/Gavin'
>>> os.path.basename(os.path.abspath('__file__'))   #os.path.basename只显示文件名
'__file__'
>>> os.path.exists('/Users/Gavin')  #os.path.exists判断文件或者目录是否存在
True
>>> os.path.exists('/Users/a')
False
>>> os.path.isfile('/Users/Gavin/Desktop/newname.doc') #判断是否为文件
True
>>> os.path.isfile('/Users/Gavin/Desktop/oldboy')
False
>>> os.path.isfile('/Users/Gavin/Desktop/oa')  #就算不存在也不会报错只不过显示不为文件
False
>>> os.path.isdir('/Users/Gavin/Desktop/oa')  #判断目录是否为目录,不存在也不会报错
False
>>> os.path.isdir('/Users/Gavin/Desktop')  #判断是否为目录
True
>>> os.path.join('a','b')  #将前面两个字符串通过/方式合并
'a/b'
>>> os.path.join('/Users','Gavin')
'/Users/Gavin'
>>> os.path.getatime('/Users/Gavin') #目录或者文件的访问时间
1487772945.0
>>> os.path.getctime('/Users/Gavin')  #目录或者文件的创建时间
1486950756.0

 

    4、sys模块

>>> sys.version  #显示python版本号
'3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25) \n[GCC 4

vim sys-test.py
import sys
print(sys.argv[1])
print(sys.argv[2])
>>>python3 sys-test.py  a  b
a
b
>>>sys.exit(1)  #退出,默认情况下正常退出为0

 

    5、shutil模块

      进行高级的文件、文件夹的拷贝工作,还可以压缩包

       shutil.copyfileobj(src_file,dest_file) #拷贝文件,不常用,因为没有流控制

import shutil

source_file= open('本节笔记','r',encoding='utf-8')
dest_file = open('本节拷贝','w',encoding='utf-8')
shutil.copyfileobj(source_file,dest_file)

      shutil.copyfile(src_file,dest_file)#拷贝文件,copyfile比copyfileobj多了with open file as f这个步骤,所以无需使用source_file  和dest_file这两个变量代替引用

shutil.copyfile('本节笔记','本节拷贝')   #源文件存在,目标文件可以存在,也可以不存在

      shutil.copymode(src_file,dest_file) #只拷贝权限,内容,组、用户都不变

shutil.copymode('本节笔记','本节拷贝')  #目标文件需要存在,只拷贝权限

      shutil.copystat(src_file,dest_file)#拷贝状态的信息,包括:mode bits, atime, mtime, flags

shutil.copymode('本节笔记','本节拷贝')  #目标文件需要存在,只拷贝权限

      shutil.copy(src_file,dest)#copy比copyfile更高明的一点就是在于dest就算是目录,copy动作也会成功,同时会在dest的目录下创建一个和src_file完全相同的文件名,比copyfile多了copymode方法

shutil.copy('本节笔记','/Users/Gavin/PycharmProjects/python/day5/test')

      shutil.copy2(src_file,dest)#copy2和copy类似,和copy的区别在于不是调用copymode,而是调用copystat函数

shutil.copy2('本节笔记','/Users/Gavin/PycharmProjects/python/day5')

      shutil.copytree('src_dict','dest_dict') #copytree是目录拷贝,将源目录所有文件和目录全部拷贝到目标目录,有个必须注意的地方在于dest_dict目录必须是不存在的,如果存在就会报错

shutil.copytree('/Users/Gavin/Desktop/a','/Users/Gavin/Desktop/k')

      shutil.rmtree('目录')#rmtree会递归方式删除相应目录

shutil.rmtree('/Users/Gavin/Desktop/a')

      shutil.move(src_dict,dest_dict)#将a目录更名为b目录,如果在不同路径下,就完成移动动作

shutil.move('/Users/Gavin/Desktop/a','/Users/Gavin/Desktop/b')

       shutil.make_archive(base_name,format,root=dir='') 

shutil.make_archive('/Users/Gavin/Desktop/b/desktop','zip',root_dir='/Users/Gavin/Desktop/b')
'''第一个参数表示base_name即压缩后的名字,后缀名会自动添加为第二个参数也就是压缩的方法包括:bztar,gztar,tar,xztar,zip等方法可选,root_dir表要压缩
目录或者文件,总体来讲,第一个是压缩后的basename,如果第一个参数只写了名字而没有写目录,会将压缩包保存到当前目录然后添加后面第二个参数为扩展名,第三个参数表示要压缩的目录或者文件'''
print(shutil.get_archive_formats())  #表示压缩打包包括哪几种方法,如果忘记可以通过该函数进行查询

      补充说明:

      shutil对压缩包的调用ZipFile和TarFile两个模块完成的

        a) ZipFile函数

import zipfile
#压缩
z = zipfile.ZipFile('压缩名.zip','w')  #压缩文件 
z.write('本节笔记')    #要压缩的文件添加
z.write('本节拷贝')   #要压缩的文件添加
z.close()
#解压
z = zipfile.ZipFile('压缩名.zip','r')
z.extractall() #将压缩文件解压
z.close()

        b) TarFile

import tarfile
#打包
tar = tarfile.open('tar.tar','w')
tar.add('本节笔记.zip',arcname='本节笔记.zip')
#tar.add('本节拷贝',arcname='本节拷贝.zip')
tar.close()
#解包
tar = tarfile.open('tar.tar','r')
tar.extractall()
tar.close()

 

 

    6、shelve模块

      一个简单的k,v 将内存数据通过持久化的模块,可以持久任何pickle可支持python数据格式

import shelve,datetime

info = {'name':'gavin', 'age': 16 ,'job': 'IT'}
name1 = [1,2,3,4,5]
name2 = 'abededg'
time_now = datetime.datetime.now()
#持久化存储
with shelve.open('shelve_test',) as f:  #通过shelve.open方式打开文件,不需要写w和r
    f['info'] = info   #将需要持久化的数据导入shelve_test中保存
    f['name1'] = name1
    f['name2'] =  name2
    f['time_now'] = time_now

#从文件中读取
with shelve.open('shelve_test',) as f:
    print(f.get('name1'))   #通过k方式获取value
    print(f.get('info'))
    print(f.get('name2'))
    print(f.get('time_now'))

 

    7、XML模块

      xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。

      xml的格式如下,就是通过<>节点来区别数据结构的:

xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2rank>
        <year>2008year>
        <gdppc>141100gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    country>
    <country name="Singapore">
        <rank updated="yes">5rank>
        <year>2011year>
        <gdppc>59900gdppc>
        <neighbor name="Malaysia" direction="N"/>
    country>
    <country name="Panama">
        <rank updated="yes">69rank>
        <year>2011year>
        <gdppc>13600gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    country>
data>

      xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
 
#遍历xml文档
for child in root:
    print(child.tag, child.attrib)
    for i in child:
        print(i.tag,i.text)
 
#只遍历year 节点
for node in root.iter('year'):
    print(node.tag,node.text)

      修改和删除xml文档内容

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
 
#修改
for node in root.iter('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)
    node.set("updated","yes")
 
tree.write("xmltest.xml")
 
 
#删除node
for country in root.findall('country'):
   rank = int(country.find('rank').text)
   if rank > 50:
     root.remove(country)
 
tree.write('output.xml')

      自己创建xml文档

import xml.etree.ElementTree as ET
 
 
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml) #生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True)
 
ET.dump(new_xml) #打印生成的格式

 

    8、Pyyaml模块

      Python也可以很容易的处理ymal文档格式,只不过需要安装一个模块,参考文档:http://pyyaml.org/wiki/PyYAMLDocumentation 

 

    9、configParser模块

      用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser。

       a)生成config文件

import configparser

config = configparser.ConfigParser()

config['DEFAULT'] = {
    'ServerAliveInterval': '45',
    'Compresssion': 'yes',
    'CompressionLevel': '9'
}

config['bitbucket.org'] = {}
bitbucket = config['bitbucket.org']
bitbucket['User'] = 'hg'
config['topsercret.server.com'] = {}
topsercert = config['topsercret.server.com']
topsercert['Host Port'] = '50022'
topsercert['ForwardX11'] = 'no'
config['DEFAULT']['ForwardX11'] = 'yes'
with open('example.ini', 'w') as f:
    config.write(f)
#输出
[DEFAULT]
serveraliveinterval = 45
compressionlevel = 9
compresssion = yes
forwardx11 = yes

[bitbucket.org]
user = hg

[topsercret.server.com]
host port = 50022
forwardx11 = no

 

      b)读配置文件

import configparser

config = configparser.ConfigParser()

print(config.sections()) #开始没有读进来之前没法看到sections

config.read('example.ini')

print(config.sections())  #通过sections函数没法读到default内容

conf_default = config.defaults()
for line in conf_default:
    print('%s:\t%s' %(line,conf_default[line]))

print(config['bitbucket.org']['User'])

if 'bitbucket.org' in config:
    print(True)

topsecert = config['topsercret.server.com']
print(topsecert['Host Port'])
for key in config['bitbucket.org']:
    print(key)
#输出
[]
['bitbucket.org', 'topsercret.server.com']
serveraliveinterval:    45
compressionlevel:    9
compresssion:    yes
forwardx11:    yes
hg
True
50022
user
serveraliveinterval
compressionlevel
compresssion
forwardx11

 

      c)修改配置文件

import configparser

config = configparser.ConfigParser()

config.read('example.ini')

#读取
secs = config.sections()
print(secs)

options = config.options('bitbucket.org')  #单独针对调用某一section对应的配置选项,options选项会将default选项内容带入
print(options)

item_list= config.items('bitbucket.org')  #针对调用section中对应的配置选项已经对应参数,item选项会将default选项也带入
print(item_list)

val = config.get('bitbucket.org','user')
print(val)
val = config.get('bitbucket.org','compresssion')
print(val)

#修改
sec = config.remove_section('bitbucket.org')  #移除secion
sec = config.add_section('DB')  #添加section
sec = config.has_section('DB') #判断section是否存在
print(sec)
sec = config.has_option('topsercret.server.com','forwardx11')  #判断section中的option是否存在
print(sec)

config.set('DB','mysql','https://www.mysql.com/3306')    #对section中的option添加参数,必须为str类型

config.remove_option('topsercret.server.com','Host Port')  #移除section内option
with open('example1.ini','w') as f:
    config.write(f) 
#输出
[DEFAULT]
serveraliveinterval = 45
compressionlevel = 9
compresssion = yes
forwardx11 = yes

[topsercret.server.com]
forwardx11 = no

[DB]
mysql = https://www.mysql.com/3306

 

    10、hashlib模块

      用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlib

m = hashlib.sha512()  #hashlib还包括md5 sha1等不同安全等级的函数调用

m.update('hello'.encode(encoding='utf-8'))

print(m.hexdigest())  #按照16进制格式显示

m.update('中文也可以加密'.encode(encoding='utf-8'))
print(m.hexdigest())

m1 = hashlib.sha512()
m1.update('hello中文也可以加密'.encode(encoding='utf-8'))
print(m1.hexdigest())


m2 = hashlib.sha512()
with open('config.cfg','r') as f:
    f1 = f.read()

m2.update('f1'.encode(encoding='utf-8'))  #可以将整个文件进行加密
print(m2.hexdigest())
#输出
9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
9600f16b6ac743e6a78557de89b458f9c373424d8762ed4730397148e5f352d0339e879786fd0404635c907503f7a73ae70ea9be82dbcf9a1c66cc77f33690de
9600f16b6ac743e6a78557de89b458f9c373424d8762ed4730397148e5f352d0339e879786fd0404635c907503f7a73ae70ea9be82dbcf9a1c66cc77f33690de
bc07fac547256ebcf7abc70731753f4ba70d4c09d856fab4f89255787bde9cbadc2ab85a77dcbbb523a7acf818bdf8db2da5ffb9b1a4d2b4ad71810795d3a546

      python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密

 

import hmac

h = hmac.new('中文key也可以'.encode(encoding='utf-8'),'message也是可以是中文'.encode(encoding='utf-8')) #前面是key,后面mess,在后面可以使用加密方法,但是一直没有使用过
h.update('我们在奋斗的路上一直不停留'.encode(encoding='utf-8'))
print(h.hexdigest())
#输出
749c771880c1cf952c957623605918d8

 

    11、re模块

      常用的正则表达式符号

        '.'  默认匹配除了\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行

        ’^‘  匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r'^a', '\nabc\necc',flags=re.MULTILINE)

        '$'  匹配字符结尾,或e.search('foo$', 'bfoo\nsdfsf', flags=re.MULTILINE).group()也可以

        ’*‘  匹配*号前的字符0次或多次,re.findall('ab*', 'cabb3abcbbac') 结果为['abb', 'ab', 'a']

        '+'  匹配前一个字符1次或多次,re.findall('ab+', 'ab+cd+abb+bba')结果['ab', 'abb']

        '?'  匹配钱一个字符1次或0次

        ’{m}‘ 匹配前一个字符m次

        ’{m,n}‘ 匹配前一个字符m到n次,re.findall('ab{1,3}', 'abb abc abbcbbb') 结果['abb', 'ab', abb]

              '|'  匹配|左或|右的字符,re.search('ab|ABC','ABCBabcCD') 结果['ABC']

        (...)  分组匹配,re.search('(abc){2}a(123|456)c', 'abcabca456c').group() 结果  abcabca456c

        \A    只从字符开头匹配,re.search('\Aabc', 'alexabc') 是匹配不到的,\A ==  ^

        \Z  匹配字符结尾,同$

        \d  匹配数字0-9

        \D  匹配非数字

        \w  匹配[A-Za-z0-9]

        \W  匹配非[A-Za-z0-9]

        \s    匹配空白字符,\t  \n  \r  ,re.search('\s' ,'ab\tc1\n3').group() 结果\t

        \b  类似与bash中\<      \>对单词做锚定

            (?P....)  分组匹配re.search(’(?P[0-9]{2})(?P[0-9]{2})(?P[0-9{2}])(?P[0-9]{8})‘, '

371481199306143242').groupdict()   结果是{’province‘: 37, 'city': 14, 'hometown': 81,'birthday': 19930614}

 

      最常用的匹配语法

re.match    从头开始匹配
re.search   匹配包含
re.findall  把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub      匹配字符并替换

      仅需轻轻知道的几个匹配模式

re.I(re.IGNORECASE):     忽略大小写(括号内是完整写法,下同)
M(MULTILINE):            多行模式,改变'^''$'的行为(参见上图)
S(DOTALL):               点任意匹配模式,改变'.'的行为             

 

import re

Match = re.search(r'\ber\b', ' i am er eraber')
print(Match.group())
#输出
er

a = re.match('chen', 'chenronghuachenronghua')  #有返回就是匹配到了,match从开头匹配
print(a.group())
#输出
chen

a = re.match('k', 'chenronghuachenronghua')
print(a)  #匹配不到,如果写a.group()会报错
匹配不到

a = re.match('chen\d', 'chen234ronghua1234chenronghua12431adec')  #有返回就是匹配到了
print(a.group())
#输出
chen2   \d代表数字,匹配一次,如果表示一个或多个,使用\d+

a = re.match('.+', 'chen234ronghua1234chenronghua12431adec')  #有返回就是匹配到了
print(a.group())
#输出
chen234ronghua1234chenronghua12431adec

a = re.search('^chen', 'chen234ronghua1234ronghua12431adec')  #匹配所有,但是找到第一个就返回
print(a.group())
#输出
chen

a = re.search('^c.+n\d+', 'chen234ronghua1234ronghua12431adec')  #已c开头,中间用多个任意字符,后面是一个数字\d,因为使用search所以只能匹配第一个匹配就返回
print(a.group())
#输出
chen234
a = re.findall('^c.+n\d+', 'chen234ronghua1234ronghua12431adec')  #findall会匹配全部匹配到值
print(a)
#输出
 ['chen234']

a = re.findall('\+$', 'chen234ronghua1234ronghua12431adec')  #findall会匹配全部匹配到值D   \D表示匹配非数字但是会匹配特殊字符
print(a)
#输出
['adec']

a = re.search('a[a-zA-Z]+c$', 'chen234ronghua1234ronghua12431adec')  #[a-zA-Z]表示匹配所有字符一次,加+表示1次到多次
print(a.group())
#输出
adec
a = re.search(r'\b#.+#$', '1123#hello#')   #\b表示锚定字符
print(a.group())
#输出
 #hello#

a = re.findall(r'a?', 'abaalexa')   # ?表示匹配前面字符0-1次
print(a)
#输出
['a', '', 'a', 'a', '', '', '', 'a', '']


a = re.search('[0-9]{3}','aa1x2a345aa')   # {3}匹配 数字3次
print(a.group())
#输出
345

a = re.findall('[0-9]{1,3}','aa1x2a345aa')   # {1,3}匹配 数字1-3次
print(a)
#输出
['1', '2', '345']


a = re.findall('abc|ABC','abcdedaABCCDABC')   #匹配abc或者ABC
print(a)
#输出
['abc', 'ABC', 'ABC']

a = re.findall('(abc){2}','abcabcABCabcdeabcabcdaedabcadedcad')   #
print(a)
#输出
['abc', 'abc']

a = re.findall('\A[0-9]+[a-z]+\Z','103494abd')   #\A 等效于^    \Z 等效于\
print(a)
#输出
['103494abd']

a = re.findall('\D','103494abd\t \n\\')   #\D 匹配非数字包括字符和特殊格式
print(a)
#输出
['a', 'b', 'd', '\t', ' ', '\n', '\\']


a = re.findall('\w','103494abd\t \n\\')   #\w 匹配数字和字母
print(a)
#输出
['1', '0', '3', '4', '9', '4', 'a', 'b', 'd']

a = re.findall('\W','103494abd\t \n\\')   #\W匹配非数字和字母  表示特殊格式与空格
print(a)
输出
#['\t', ' ', '\n', '\\']

a = re.findall('\s','103494abd\t \n\\')   #\s匹配特殊字符 空格  不包括 "\"
print(a)
#输出
['\t', ' ', '\n']


a = re.search('(?P[0-9]{2})(?P[0-9]{2})(?P[0-9]{2})(?P[0-9]{8})', '371481199306143242')
print(a.groupdict())
输出
#{'province': '37', 'hometown': '81', 'city': '14', 'birthday': '19930614'}


a = re.search('[a-z]+','abccdA', flags=re.I)   #re.I 忽略大小写
print(a.group())
#输出
abccdA


a = re.search('[a-z]+','abccdA', flags=re.I)   #re.I 忽略大小写
print(a.group())
输出
abccdA

a = re.search('[a-z]+d$','abccdA\nsecondline\nthird', flags=re.M)   #re.M匹配换行
print(a.group())
#输出
third

a = re.search('.+','oneline\nsecondline\nthird\nfourthline', flags=re.S)   #在.中如何使用re.S可以连换行都能匹配上
print(a.group())
#输出
oneline
secondline
third
fourthline

 

    12、conllections模块

       1、Counter函数

        counter函数对字符串、列表进行分割,统计字符串出现的次数

import collections
obj = collections.Counter('abedjdjajdebaqazwsxedccvfredaa djdjejkd;ddoeeo;ddedpdkdkdk')#元素里出现次数记录,计数器功能
print(obj) #输出 Counter({'d': 16, 'e': 8, 'j': 6, 'a': 6, 'k': 4, 'o': 2, 'c': 2, ';': 2, 'b': 2, 'w': 1, 'q': 1, 'v': 1, 'z': 1, ' ': 1, 'f': 1, 'p': 1, 'r': 1, 'x': 1, 's': 1})
ret = obj.most_common(5) #输出前五个
print(ret)
#输出
[('d', 16), ('e', 8), ('j', 6), ('a', 6), ('k', 4)]
obj = collections.Counter([11,22,33,22,33])  #对列表进行统计
print(obj)
#输出
Counter({33: 2, 22: 2, 11: 1})
obj.update(['erc',11,11,22,11])    #对原有obj进行更新,添加数据
print(obj)
#输出
Counter({11: 4, 22: 3, 33: 2, 'erc': 1})
obj.subtract(['erc', 11,22,33,11])
print(obj)
#输出
Counter({11: 2, 22: 2, 33: 1, 'erc': 0})

       

      2、双向队列与单向队列

        deque表示双向队列,双向队列表示从右面与左面均可添加与消耗队列中的数据

import collections
d = collections.deque()
d.append('1')  #正常的append从右面添加,append可以添加单个元素
d.appendleft('10')  #从左面添加
d.appendleft('1')
print(d)
#输出
deque(['1', '10', '1'])
print(d.count('1'))
#输出
2
d.extend(['aa','bb','aa']) #extend添加多个元素
print(d)
#输出
deque(['1', '10', '1', 'aa', 'bb', 'aa'])
d.extendleft(['aa','bb','aa'])
print(d)
#输出
deque(['aa', 'bb', 'aa', '1', '10', '1', 'aa', 'bb', 'aa'])

        单向队列只能从一侧添加一侧消耗

import queue
q = queue.Queue()
q.put('123')
print(q.qsize())
#输出
1

q.put('789')
print(q.qsize())
#输出
2

print(q.get())
#输出
123

print(q.get())
#输出
789

 

       3、可命名元组

import collections

M = collections.namedtuple('Mytuple', ['x','y','z'])
obj = M(11,22,33)
print(obj.x,obj.y,obj.z)
#输出
11 22 33

      

      4、有序字典

 

import collections
dic = collections.OrderedDict()  #有序字典定义

dic['k1'] = 'v1'
dic['k2'] = 'v2'
dic['k3'] = 'v3'

for i in dic:
    print(i + '\t\t' + dic[i])
#输出®
k1        v1
k2        v2
k3        v3

dic.popitem()
print(dic)
#输出
OrderedDict([('k1', 'v1'), ('k2', 'v2')])

ret = dic.pop('k1')
print(dic)
print(ret)
#输出
OrderedDict([('k2', 'v2')])
v1
dic.setdefault('k2','444') #如果没有就变成444,如果本身有值就不变
dic.setdefault('k4')  #只有k4,就把值变为None
print(dic)
#输出
OrderedDict([('k2', 'v2'), ('k4', None)])

dic.update({'k2': 'v222', 'k10':'v10'})  #通过update方法添加多个元素,如果原来key存在会修改原value
print(dic)
#输出
OrderedDict([('k2', 'v222'), ('k4', None), ('k10', 'v10')])

      5、默认字典

import collections
dic = collections.defaultdict(list)  #创建一个字典,字典的默认值为list

dic['k1'].append('alex')
dic['k1'].extend(['gavin','age',23])
print(dic)
#输出
defaultdict(<class 'list'>, {'k1': ['alex', 'gavin', 'age', 23]})

dic1 = collections.defaultdict(dict)

dic1['k1']['k1'] = 'v1'
dic1['k2']['k2'] = 'v2'
print(dic1)
#输出
defaultdict(<class 'dict'>, {'k2': {'k2': 'v2'}, 'k1': {'k1': 'v1'}})

    13、subprocess模块

      subprocess将代替os.system与os.spawn模块,在python2.7中,subprocess模块调用call()函数显示实时输出结果,通过Popen函数保存输出结果,在python3.5以后,通过run()代替call()函数

import subprocess

subprocess.run('df -h',shell=True)

a = subprocess.Popen('df -h',shell=True,stdout=subprocess.PIPE) #run与call和Popen都是如此,如果参数不止一个,同时也不想通过列表方式传入,需要shell=True
#如果需要保存输出结果,需要通过Popen函数保存,同时需要通过subprocess.PIPE管道方式将结果传递给输出
print(a.stdout.read())

     终端输入命令分为两种:

      1、输入即可得到输出  如ifconfig    

      2、输入进行某环境依赖再输入 如python

    需要交互命令实例:

    可以使用这个方法与另外一个子进程进行交互(配合管道PIPE来使用)

import subprocess
obj = subprocess.Popen(['python'], stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
obj.stdin.write('print 1 \n'.encode('utf-8'))
obj.stdin.write('print 2 \n'.encode('utf-8'))
obj.stdin.write('print 3 \n'.encode('utf-8'))
obj.stdin.write('print 4 \n'.encode('utf-8'))

out_err_list = obj.communicate(timeout=10)#如果想结束进程,使用communicate函数
print(out_err_list)

 

    14、logging模块

      很多程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误告警灯信息输出,python的logging模块提供了标准的日志接口,可以通过它存储各种格式的日志,logging的日志分为debug、info、warning、error5个等级

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %H:%M:%s ', filename='example-log.log',level=logging.INFO)
#%S 表示正常秒  %s表示更精确的秒, %p表示  AM或者PM这个可以和%I一起使用
logging.debug('this message should go to the log files')
logging.info('so should this')
logging.warning('and this, too')

   10、二分法

def find_data(data,find_i):
    if len(data) > 1:
        if data[int(len(data)/2)] > find_i:
            print(data[:int(len(data)/2)])
            find_data(data[:int(len(data)/2)],find_i)
        elif data[int(len(data)/2)] < find_i:
            print(data[int(len(data)/2):])
            find_data(data[int(len(data)/2):],find_i)
        else:
            print('find the number: %s' %data[int(len(data)/2)])
    else:
        if data[int(len(data)/2)] == find_i:
            print('find the number: %s' %data[int(len(data)/2)])
        else:
            print('cant not find')
if __name__ == '__main__':
    data = list(range(1,50,3))
    find_data(data,5)

  

  11、冒泡排序

 

data = [10,4,33,21,22,54,3,8,11,5,22,17,13,6]
for j in range(1,len(data)):
    for i in range(len(data)-j):
        if data[i] > data[i+1]:
            tmp = data[i]
            data[i] = data[i+1]
            data[i+1] = tmp

print(data)

 

  12、时间复杂度

      时间复杂度是用来衡量算法的优劣,通常来讲,算法效率越高,时间复杂度消耗的时间越低,通常来说,时间复杂度分为O(n) 线性复杂度,O(n2)和O(n3),还有 O(1)和O(logn),其中O(1)为常量,不论数据量多大,都是同一时间完成,效率最高,而O(logn)的典型代表就是二分法和二叉树法,这种方法随着数据量越高,效率越高, O(n)为线性增长,随着数据量的增大而线性增大,最后是O(n2)  O(n3)分别代表算法中存在两次循环和三次循环,效率比前面的低

 

  13、深拷贝

    拷贝分为深拷贝与浅拷贝,其中copy.copy()与变量赋值均属于浅拷贝,浅拷贝的特点为只拷贝第一层数据,而不拷贝第一层以外的数据,这样的坏处在于修改了第一层以外的数据的拷贝数据时,原始数据也会跟着修改,而深拷贝会拷贝所有数据,无论数据处于第几层,这样拷贝数据与原始数据相互之间不受影响

import copy
'''
#浅拷贝

copy.copy()

#深拷贝
copy.deepcopy()

#赋值
a = '111'
b = a
'''
#赋值
a1 = 123
b1 = 123
print(id(a1))
print(id(b1))

a2 = a1
print(id(a1))
print(id(a2))

#字符串拷贝,对于字符串,深浅拷贝都只是指向内存都一地址
a3 = copy.copy(a1)
print(id(a3))

a4 = copy.deepcopy(a1)
print(id(a4))

#对元组/列表/字典拷贝


n1 = {'k1': 'wu', 'k2': 123, 'k3': ['alex',456]}
n2 = n1 #赋值
print(id(n1))
print(id(n2))

n3 = copy.copy(n1) #浅拷贝,只拷贝一层,所以n3只拷贝了k1 k2  k3对应的值,而k3中代表的列表没有进行拷贝
print(id(n3))

print(id(n3['k3']))  #由于浅拷贝只拷贝一层,所以n3与n1的k3对应的列表内存地址一样
print(id(n1['k3']))

n4 = copy.deepcopy(n1)
print(id(n4['k3']))
print(id(n4))

 

 

 

 

 

 

 

  

 

 

  

 

转载于:https://www.cnblogs.com/xiaopi-python/p/6428082.html

你可能感兴趣的:(Python学习笔记第五周)