Python常用模块

Python常用模块

1. 时间模块(time)

和时间有关系的我们就要用到时间模块。在使用模块之前,应该首先导入这个模块。

# 常用方法
import time
time.sleep(secs)
# 使线程延迟指定的时间运行,时间单位为秒

time.time()
# 获取当前时间戳
  1. 在Python表示时间的三种方式:

    1. 时间戳:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。

    2. 格式化时间:"2019-07-02"

    3. 结构化时间:struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)

      # Python中时间日期格式化符号
      %y 两位数的年份表示(00-99)
      %Y 四位数的年份表示(000-9999)
      %m 月份(01-12)
      %d 月内中的一天(0-31)
      %H 24小时制小时数(0-23)
      %I 12小时制小时数(01-12)
      %M 分钟数(00=59)
      %S 秒(00-59)
      %a 本地简化星期名称
      %A 本地完整星期名称
      %b 本地简化的月份名称
      %B 本地完整的月份名称
      %c 本地相应的日期表示和时间表示
      %j 年内的一天(001-366)
      %p 本地A.M.或P.M.的等价符
      %U 一年中的星期数(00-53)星期天为星期的开始
      %w 星期(0-6),星期天为星期的开始
      %W 一年中的星期数(00-53)星期一为星期的开始
      %x 本地相应的日期表示
      %X 本地相应的时间表示
      %Z 当前时区的名称
      %% %号本身
      
      import time
      # 时间戳
      ret = time.time()
      print(ret)
      
      # 结构化时间
      ret = time.localtime()
      print(ret)
      
      # 格式化时间
      ret= time.strftime('%Y-%m-%d')
      print(ret)
      

      小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;结构化时间则是用来操作时间的

  2. 几种格式之间的转换

 ![](https://img2018.cnblogs.com/blog/1451970/201907/1451970-20190704001051682-1546502527.png)



  ```python
  import time
  # 1、时间戳 ——> 结构化时间
  timestamp = time.time()
  struct_time = time.localtime(timestamp)
  
  # 2、结构化时间 ——> 格式化时间
  format_time = time.strftime("%Y-%m-%d", struct_time)
  
  # 3、格式化时间 ——> 结构化时间
  struct_time = time.strptime(format_time, "%Y-%m-%d")
  
  # 4、结构化时间 ——> 时间戳
  stamptime = time.mktime(struct_time)
  ```

2. random模块

import random

# 1、获取随机整数(闭区间)
random.randint(3,5)

# 2、获取随机整数(左闭右开)
random.randrange(3, 5)

# 3、获取随机0-1之内随机小数
random.random()

# 4、获取指定范围内的随机小数
random.uniform(1, 3)

# 5、随机选择一个并返回值
lst = [1, "dogfa", {"age": 18}, [1,2,3], ("哈哈",)]
random.choice(lst)

# 6、随机选择多个并返回值,返回个数取决于第二个参数
lst = [1, "dogfa", {"age": 18}, [1,2,3], ("哈哈",)]
random.sample(lst, 2)

# 7、打乱列表顺序
lst = [1, "dogfa", {"age": 18}, [1,2,3], ("哈哈",)]
random.shuffle(lst)

3. sys模块

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

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0),错误退出sys.exit(1)
sys.version        获取Python解释程序的版本信息
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称

4. os模块

os模块是与操作系统交互的一个接口

os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息

os.system("bash command")  运行shell命令,直接显示
os.popen("bash command).read()  运行shell命令,获取执行结果
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd

os.path
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回 
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path) 返回path的大小
                
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'

注意:os.stat('path/filename') 获取文件/目录信息 的结构说明

stat 结构:

st_mode: inode 保护模式
st_ino: inode 节点号。
st_dev: inode 驻留的设备。
st_nlink: inode 的链接数。
st_uid: 所有者的用户ID。
st_gid: 所有者的组ID。
st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
st_atime: 上次访问的时间。
st_mtime: 最后一次修改的时间。
st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。

5. re模块

import re

# 将所有满足正规则的值查询出来,并返回一个列表
ret = re.findall("a", "abcsasdasdafas")
print(ret)
# ['a', 'a', 'a', 'a', 'a']

# 将满足正则规则的第一个值查询出来,返回的是一个包含匹配结果的对象,可以通过obj.group()方法取出满足匹配结果的值,如果没有匹配到值,则返回None
ret = re.search("a", "abcsasdasdafas")
print(ret)
# <_sre.SRE_Match object; span=(0, 1), match='a'>
print(ret.group())
# a

# 与search一样,只不过match只会从头开始匹配,相当于re.search("^a")
ret = re.match("a", "abcsasdasdafas")
print(ret)
# <_sre.SRE_Match object; span=(0, 1), match='a'>
print(ret.group())
# a

# 对满足正则规则的值进行分割
ret = re.split("[ab]", "abcd")
print(ret)
# ['', '', 'cd']


# 将满足正则规则的值替换成W,参数1表示只替换3个
ret = re.sub("\d", "W", "ad1a212af5a4s54a", 3)
print(ret)
# adWaWW2af5a4s54a

# 和re.sub一样,只不过返回的值是一个元祖,里面包含替换的次数
ret = re.subn("\d", "W", "ad1a212af5a4s54a", 3)
print(ret)
# ('adWaWW2af5a4s54a', 3)

# 将正则表达式编译成一个正则表达式对象,再次解析正则表达式时将节省时间
obj = re.compile("\d{3}")
ret = obj.search("123das45asd879asd")
print(ret.group())
# 123

# 返回值是一个迭代器,节省空间
ret = re.finditer("\d", "123affdsfdsds5f4sdf")
print([i.group() for i in ret])
# ['1', '2', '3', '5', '4']

注意:

  1. findall的优先级查询

    import re
    
    ret_lsit = re.findall("www.(baidu|2345).com", "www.baidu.com")
    print(ret_lsit)
    # ['baidu']		这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
    
    ret_lsit = re.findall("www.(?:baidu|2345).com", "www.baidu.com")
    print(ret_lsit)
    # ['www.baidu.com']
    
  2. split的优先级查询

    import re
    
    ret_lsit = re.split("\d+", "dogfa38oldniu48djb27")
    print(ret_lsit)
    # ['dogfa', 'oldniu', 'djb', '']
    
    ret_lsit = re.split("(\d+)", "dogfa38oldniu48djb27")
    print(ret_lsit)
    # ['dogfa', '38', 'oldniu', '48', 'djb', '27', '']
    
    #在匹配部分加上()之后所切出的结果是不同的,
    #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
    #这个在某些需要保留匹配部分的使用过程是非常重要的。
    

re模块扩展

  1. 匹配标签

    import re
    
    ret = re.search("<(?P<tags>\w+)>.*</(?P=tags)>", "<h1>哈哈哈</h1>")
    print(ret.group())			# <h1>哈哈哈</h1>
    print(ret.group("tags"))	# h1
    
    #可以在分组中利用?<name>的形式给分组起名字
    #获取的匹配结果可以直接用group('名字')拿到对应的值
    
  2. 匹配整数

    import re
    
    ret = re.findall(r"-?\d+\.\d+|(-?\d+)", "1-2*(60+(-40.35/5)-(-4*3))")
    print(ret)		# ['1', '-2', '60', '', '5', '-4', '3']
    ret.remove("")
    print(ret)		# ['1', '-2', '60', '5', '-4', '3']
    
  3. 数字匹配

    1、 匹配一段文本中的每行的邮箱
          http://blog.csdn.net/make164492212/article/details/51656638
    
    2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;
    
       分别取出1年的12个月(^(0?[1-9]|1[0-2])$)、
       一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$
    
    3、 匹配qq号。(腾讯QQ号从10000开始)  [1,9][0,9]{4,}
    
    4、 匹配一个浮点数。       ^(-?\d+)(\.\d+)?$   或者  -?\d+\.?\d*
    
    5、 匹配汉字。             ^[\u4e00-\u9fa5]{0,}$ 
    
    6、 匹配出所有整数
    

    在线测试工具: http://tool.chinaz.com/regex/

6. 序列化模块

1. 什么是序列化?

   将其它数据格式内容转换成一个字符串的过程就叫做**序列化**。

2. 序列化的目的

   1. 以某种存储形式使自定义对象持久化
   2. 将对象从一个地方传递到另一个地方
   3. 使程序更具有维护性

   ![](https://img2018.cnblogs.com/blog/1451970/201907/1451970-20190704001159992-348986373.png)



3. Json

   Json模块提供了四个功能:dumps、dump、loads、load

   在Python中大部分类型数据不能转换成Json格式,只有少部分如:str,list,dict,int 类型可以转换成Json格式数据类型,且Json格式中字典的key值一定为字符串类型,在Json中字符串类型全都用双引号(" ")表示。

   1. dumps 和 loads

      ```python
      import json
      
      dic = {"name":"dogfa", "age":18, "gender":"male", 1:2}
      
      json_dic = json.dumps(dic)	 # 序列化:将一个字典转换成一个字符串
      print(json_dic)
      # {"name": "dogfa", "age": 18, "gender": "male", "1": 2}
      
      new_dic = json.loads(json_dic)	# 反序列化:将Json格式数据转换成字典格式数据
      print(new_dic)
      # {'name': 'dogfa', 'age': 18, 'gender': 'male', '1': 2}
      
      # 对比前后转换我们发现在转换成Json格式的时候,key全部转换成了字符串类型,而对这个结果再次转换回字典格式类型key表现的形式依旧是字符串类型。
      ```

   2. dump 和 load

      ```python
      import json
      
      dic = {"name":"dogfa", "age":18, "gender":"male", 1:2}
      
      f = open("file/dog", mode="w", encoding="utf-8")
      json.dump(dic, f, ensure_ascii=False)	
      # dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
      f.close()
      # ensure_ascii:当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入Json的中文即可正常显示。
      
      f = open("file/dog", mode="r", encoding="utf-8")
      ret = json.load(f)
      # load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
      print(ret)
      ```

      注意:可以dump多次数据到文件中,但是load不出来了。想dump多个数据进文件,用dumps。

      ```python
      import json
      
      dic = {"name":"dogfa", "age":18, "gender":"male", 1:2}
      lst = [1, 2, 3, 4]
      
      # 存值
      f = open("file/dog", mode="w", encoding="utf-8")
      json_dic = json.dumps(dic, ensure_ascii=False)
      json_lst = json.dumps(lst, ensure_ascii=False)
      f.write(json_dic + "\n")
      f.write(json_lst + "\n")
      
      # 取值
      f = open("file/dog", mode="r", encoding="utf-8")
      for line in f:
          print(json.loads(line))
      ```

4. pickle

   pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load  (不仅可以序列化字典,列表...**可以把Python中基本上所有的数据类型序列化**)

   ```python
   import pickle
   
   dic = {"name":"dogfa", "age":18, "gender":"male", 1:2}
   
   pic_dic = pickle.dumps(dic)
   print(pic_dic)	# 一串bytes类型内容
   
   new_dic = pickle.loads(pic_dic)
   print(new_dic)	# {"name":"dogfa", "age":18, "gender":"male", 1:2}
   
   
   # pickle还可以存储对象
   import time
   struct_time = time.localtime()
   print(type(struct_time), struct_time.tm_mday)
   # <class 'time.struct_time'> 3
   
   f = open("file/dog", mode="wb")
   pickle.dump(struct_time, f)
   
   f = open("file/dog", mode="rb")
   new_struct_time = pickle.load(f)
   print(new_struct_time.tm_mday)	# 3
   ```

   总结:当序列化的内容是列表或者字典,推荐使用json模块。但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用Python对这个数据进行反序列化的话,那么就可以使用pickle。

7. hashliib模块

  1. 什么是hash?
  hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),该算法接受传入的内容,经过运算得到一串hash值。
  1. hash值得特点

    1. 只要传入的内容一样,得到的hash值必然一样

    2. 不能由hash值返解成内容

    3. 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的

MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示

import hashlib

md5_obj = hashlib.md5()
md5_obj.update("dogfa".encode("utf-8"))
ret = md5_obj.hexdigest()
print(ret)
# df4a1f9d8687dfaac078aa0a24a1ca29

md5_obj.update("sb".encode("utf-8"))
print(md5_obj.hexdigest())
# 819bc0bd1c65f19111f95462e0560629

md5_obj = hashlib.md5()
md5_obj.update("dogfasb".encode("utf-8"))
ret = md5_obj.hexdigest()
print(ret)
# 819bc0bd1c65f19111f95462e0560629

# 注意:把一段很长的数据update多次,与一次update这段长数据,得到的结果一样
# 但是update多次为校验大文件提供了可能。

由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”。

import hashlib

md5_obj = hashlib.md5("我是盐".encode("utf-8"))
md5_obj.update("dogfasb".encode("utf-8"))
ret = md5_obj.hexdigest()
print(ret)
# 2c39693230a2e0ff4f98163e5b177a1c

8. logging模块(日志模块)

1. 日志级别

   ```python
   CRITICAL = 50 #FATAL = CRITICAL
   ERROR = 40
   WARNING = 30 #WARN = WARNING
   INFO = 20
   DEBUG = 10
   NOTSET = 0 #不设置
   ```

2. 默认级别为warning,默认打印到终端

   ```python
   import logging
   
   logging.debug('调试debug')
   logging.info('消息info')
   logging.warning('警告warn')
   logging.error('错误error')
   logging.critical('严重critical')
   
   '''
   WARNING:root:警告warn
   ERROR:root:错误error
   CRITICAL:root:严重critical
   '''
   ```

3. logger对象配置

   ```python
   import logging
   
   # 创建一个日志格式
   format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
   
   logger = logging.getLogger("sb")
   
   filehandle = logging.FileHandler("file/dog", encoding="utf-8")
   streamhandle = logging.StreamHandler()
   
   filehandle.setFormatter(format)
   streamhandle.setFormatter(format)
   
   logger.addHandler(filehandle)
   logger.addHandler(streamhandle)
   logger.setLevel(logging.DEBUG)
   
   
   logger.debug("我是debug")
   logger.info("我是info")
   logger.warning("我是warning")
   logger.error("我是error")
   logger.critical("我是critical")
   ```

4. 配置参数

   ```
   logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
   
   filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
   filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
   format:指定handler使用的日志显示格式。
   datefmt:指定日期时间格式。
   level:设置rootlogger的日志级别
   stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
   
   format参数中可能用到的格式化串:
   %(name)s Logger的名字
   %(levelno)s 数字形式的日志级别
   %(levelname)s 文本形式的日志级别
   %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
   %(filename)s 调用日志输出函数的模块的文件名
   %(module)s 调用日志输出函数的模块名
   %(funcName)s 调用日志输出函数的函数名
   %(lineno)d 调用日志输出函数的语句所在的代码行
   %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
   %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
   %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
   %(thread)d 线程ID。可能没有
   %(threadName)s 线程名。可能没有
   %(process)d 进程ID。可能没有
   %(message)s用户输出的消息
   ```

5. 追踪错误提示信息

   ```python
   import traceback
   
   try:
       a
   except Exception as e:
       print(traceback.format_exc())
       
       
   # Traceback (most recent call last):
   #   File "E:/Python Code//日志文件.py", line 4, in <module>
   #     a
   # NameError: name 'a' is not defined
   ```

直接复制使用版本

import logging

# 一:日志配置
logging.basicConfig(
    # 1、日志输出位置:1、终端 2、文件
    # filename='access.log', # 不指定,默认打印到终端

    # 2、日志格式
    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',

    # 3、时间格式
    datefmt='%Y-%m-%d %H:%M:%S %p',

    # 4、日志级别
    # critical => 50
    # error => 40
    # warning => 30
    # info => 20
    # debug => 10
    level=30,
)

# 二:输出日志
logging.debug('调试debug')
logging.info('消息info')
logging.warning('警告warn')
logging.error('错误error')
logging.critical('严重critical')

'''
# 注意下面的root是默认的日志名字
WARNING:root:警告warn
ERROR:root:错误error
CRITICAL:root:严重critical
'''
2、日志配置字典
"""
logging配置
"""

import os

# 1、定义三种日志输出格式,日志中可能用到的格式化串如下
# %(name)s Logger的名字
# %(levelno)s 数字形式的日志级别
# %(levelname)s 文本形式的日志级别
# %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
# %(filename)s 调用日志输出函数的模块的文件名
# %(module)s 调用日志输出函数的模块名
# %(funcName)s 调用日志输出函数的函数名
# %(lineno)d 调用日志输出函数的语句所在的代码行
# %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
# %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
# %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
# %(thread)d 线程ID。可能没有
# %(threadName)s 线程名。可能没有
# %(process)d 进程ID。可能没有
# %(message)s用户输出的消息

# 2、强调:其中的%(name)s为getlogger时指定的名字
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

test_format = '%(asctime)s] %(message)s'

# 3、日志配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
        'test': {
            'format': test_format
        },
    },
    'filters': {},
    'handlers': {
        #打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        #打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,日志轮转
            'formatter': 'standard',
            # 可以定制日志文件路径
            # BASE_DIR = os.path.dirname(os.path.abspath(__file__))  # log文件的目录
            # LOG_PATH = os.path.join(BASE_DIR,'a1.log')
            'filename': 'a1.log',  # 日志文件
            'maxBytes': 1024*1024*5,  # 日志大小 5M
            'backupCount': 5,
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
        'other': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'formatter': 'test',
            'filename': 'a2.log',
            'encoding': 'utf-8',
        },
    },
    'loggers': {
        #logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
            'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递
        },
        '专门的采集': {
            'handlers': ['other',],
            'level': 'DEBUG',
            'propagate': False,
        },
    },
}

3、使用
import settings

# !!!强调!!!
# 1、logging是一个包,需要使用其下的config、getLogger,可以如下导入
# from logging import config
# from logging import getLogger

# 2、也可以使用如下导入
import logging.config # 这样连同logging.getLogger都一起导入了,然后使用前缀logging.config.

# 3、加载配置
logging.config.dictConfig(settings.LOGGING_DIC)

# 4、输出日志
logger1=logging.getLogger('用户交易')
logger1.info('xx转账给xx 300w')

# logger2=logging.getLogger('专门的采集') # 名字传入的必须是'专门的采集',与LOGGING_DIC中的配置唯一对应
# logger2.debug('专门采集的日志')

common.py

9. collections模块

在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

1. deque(双端队列)

   使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

   deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈

   ```python
   from _collections import deque
   
   dq = deque(["a", "b", "c"])
   dq.append("d")
   dq.appendleft("e")      # 在队列的左端插入
   print(dq)
   # deque(['e', 'a', 'b', 'c', 'd'])
   
   print(dq[2])        # 同样可以通过索引取值
   # b
   ```

   deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。

   ```python
   # 对比列表和双端队列的插入速度
   import time
   from collections import deque
   
   lst = list(range(1000000000))
   
   # 列表插入数据时间
   start_time = time.time()
   lst.insert(0, 1)
   end_time = time.time()
   
   speed_time = round(end_time - start_time, 2)
   print("lst_time:", speed_time)
   
   
   # 双端队列插入数据时间
   dq = deque()
   dq.extend(lst)
   
   start_time = time.time()
   dq.insert(0, 1)
   end_time = time.time()
   
   speed_time = round(end_time - start_time)
   print("dq_time:", speed_time)
   ```

2. namedtuple

   我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:

   ```python
   tu = (1, 2)
   ```

   但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。

   这时,namedtuple就派上了用场:

   ```python
   from collections import namedtuple
   
   Point = namedtuple('Point', ['x', 'y'])
   p = Point(1, 2)
   
   print(p.x)	# 1
   print(p.y)	# 2
   ```

.........

posted @ 2019-07-05 01:22  与鹿逐秋  阅读(298)  评论(0编辑  收藏  举报