目录

  一、基础概念

    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 "<stdin>", line 1, in <module>
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">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <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<name>....)  分组匹配re.search(’(?P<province>[0-9]{2})(?P<city>[0-9]{2})(?P<hometown>[0-9{2}])(?P<birthday>[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<province>[0-9]{2})(?P<city>[0-9]{2})(?P<hometown>[0-9]{2})(?P<birthday>[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))

 

 

 

 

 

 

 

  

 

 

  

 

posted on 2017-02-22 11:27  爱python的小皮  阅读(647)  评论(0编辑  收藏  举报