~~函数基础(八):模块~~

进击のpython

*****

模块


  • 是什么?

    其实随着开发的过程中,

    你就能感受到两个问题,

    一是代码越来越长,越来越长,是真的长

    二是命名问题,是真的,你把你学过的工地英语全部用上也满足不了开发的需求

    怎么办呢?

    你说,我们钉钉子的时候,我们非要先做个锤子然后再钉嘛?

    是不是锤子就已经有了,拿过来直接用就行啦!

    而你写的代码有一部分就是在做锤子

    而模块,就是锤子!

    相比较做锤子钉钉子来说,直接拿锤子钉就可以了


  • 能干啥?

    能干个锤子!

    还能干个扳手!

    在迄今为止,python内置300+个锤子,再加上第三方18w+个锤子

    基本上你想干啥,都能找到对应的工具

    也就是为什么说python简单

    因为库是真的多!


  • 怎么用?

    # 直接导入:
    import os 
    os.path
    
    # 多模块导入:
    import os
    import sys
    
    import os,sys
    
    import os 
    os.path
    # 这两句就相当于:
    from os import path,replace
    path()
    
    from os import path
    path.split()
    # 可以写成:
    from os.path import split
    split()
    

    那我觉得 split 这个太长了,想给它起个名

    from os.path import split as s
    s()
    

    那我想用这个模块,但是先不知道用那个方法,怎么办?

    from os import *
    

    但是!不建议使用!

    为什么?

    我把os里所有的模块都调用出来

    结果你就用一个方法?????

    那多占内存啊!

    虽然不差那么点东西,但是还有个更重要的原因!

    from os import *
    from sys import *
    name
    

    好嘞,我现在调用了name,你知道是os的还是sys的嘛?

    (是sys的,后调用的向前覆盖)

    那我就想调用os的name你怎么办?对不!

    还有要注意的就是,模块的调用要写在程序的开始!

    不是说写中间不行,只是不规范!


    那我要是想自己做一个锤子随身携带可以不?

    当然可以啊

    那我要怎么调用呢?

    我现在先创建一个 a56.py 的文件

    # a56.py
    print("这是自己写的模块")
    
    
    def func(n):
        print(f"你输入的是:{n}")
    
    

    再创建一个 a78.py 文件

    # a78.py
    import a56
    

    执行之后就是这样的:

    这是自己写的模块
    

    调用 a56.py里面的函数

    # a78.py
    import a56
    
    a56.func("jhgsrgxe")
    

    执行结果:

    这是自己写的模块
    你输入的是:jhgsrgxe
    

  • 去哪下

    通用方法:利用pip方法来下载(憋跟我说源码操作!没的卵用)

    pip install #库名
    

    慢不慢???就问你慢不慢!!!!!!!!

    为什么这么慢呢?

    因为这种方法就相当于去国外的服务器下载

    当然就会很慢(挂vpn的别bb)

    所以我们一般都会去国内的镜像网站去下载相应的库

    比较好的就是 豆瓣源https://pypi.doubanio.com/simple/)

    比如我想下载 paramiko 这个模块

    怎么做呢?

    pip install -i https://pypi.doubanio.com/simple/ maramiko
    

    执行了吗?什么情况?

    如果你是这样 那就得讲一下了(其实你们大部分都是这种情况)

    黄字是警告!红字是错误!

    红字说没有这个模块!

    不对啊!不是镜像网站嘛!怎么能没有呢?

    来,我们看看黄字怎么说!

    这是一个不安全或者不被信任的网站,你要是想下载的话就在后面加个东西

    --trusted-host pypi.douban.com

    OHOHOOOOOOHOHOHOHOHOHOHOHOHO~

    -所以,应-这么写:

    pip install -i https://pypi.doubanio.com/simple/ maramiko --trusted-host pypi.douban.com
    

    这样你就会发现!!!!很快!!!!!!!!!


  • 常用模块

    1、os/sys模块 :没啥说的,这个东西自己用到哪个就记住就完事了


    2、time&datetime模块时间模块

    • 时间的显示

      时间戳:从1970年1月1日到现在度过的秒数

      time.time()
      

      格式化的时间字符串:2019-07-22 12:00

      元组(struck_time):九个元素

      UTC时间:(世界协调时),就是格林威治时间

      DST 夏令时


    • 时间的转换(time模块)

      import time
      import zsh
      print(time.localtime())  # 将时间戳转换成元组形式,不指定参数,以当前时间为准
      # time.struct_time(tm_year=2019, tm_mon=7, tm_mday=10, tm_hour=15, tm_min=15, tm_sec=37, tm_wday=2, tm_yday=191, tm_isdst=0)
      
      print(time.gmtime())  # 将时间戳转换成格林威治时间的元组形式,不指定参数,以当前时间为准
      # time.struct_time(tm_year=2019, tm_mon=7, tm_mday=10, tm_hour=7, tm_min=19, tm_sec=24, tm_wday=2, tm_yday=191, tm_isdst=0)
      
      print(time.time())  # 打印当前时间戳
      # 1562743243.4245543
      
      g = time.gmtime()
      print(time.mktime(g))  # 将元组形式转换为时间戳
      # 1562714591.0
      
      time.sleep(3)  # 让程序睡(停止)一会儿
      print("___")
      
      print(time.asctime())  # 时间格式化
      # Wed Jul 10 15:27:22 2019
      
      print(time.ctime(1562714591.0))  # 将时间戳转化为asctime()
      # Wed Jul 10 07:23:11 2019
      
      print(time.strftime("%Y", time.localtime()))  # 时间格式化输出
      # 2019
      

      关于这个时间格式化,有相应的文本资料

      除了有将时间转为字符串的,还有字符串转时间的:

      import time
      
      print(time.strptime("2012/04/01", "%Y/%m/%d"))  # 将字符串转换为时间
      # time.struct_time(tm_year=2012, tm_mon=4, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=92, tm_isdst=-1)
      
      

      这有一张图,方便理解吧


    • 时间的运算(datetime)

      import datetime
      
      print(datetime.datetime.now())  # 当前时间
      # 2019-07-10 21:15:41.342153
      
      print(datetime.date.fromtimestamp(3333333))  # 传入时间戳,返回格式化时间
      # 1970-02-08
      
      
      t1 = datetime.date.fromtimestamp(3333333)  # 1970-02-08
      datetime.timedelta(days=3)  # 3 days, 0:00:00
      print(t1 - datetime.timedelta(days=3))  # 时间运算 还有 miuntes scounds
      # 1970-02-05
      
      t1 = t1.replace(year=2015)  # 时间替换
      print(t1)
      # 2015-02-08
      

    3、random模块:随机模块

    • 程序中有很多地方需要用到随机字符,通过random模块可以很容易生成随机字符串

      import random
      
      print(random.randint(1, 10))
      # 生成 1,2,3,4,5,6,7,8,9,10 随机数
      
      print(random.randrange(1, 10))
      # 生成 1,2,3,4,5,6,7,8,9 随机数
      
      print(random.randrange(1, 10, 2))
      # 生成 1,3,5,7,9 随机数
      
      print(random.random())
      # 生成0~1之间的浮点数 0.10487793352120212
      
      print(random.choice("123"))
      # 返回给定数据集合的随机字符
      
      print(random.sample("123654", 2))
      # 返回给定数据集合的随机字符,以及数量 ['6', '1']
      

      弄一个随机验证码来看看 顺便用一个新的模块 string

      import random
      import string
      
      k = string.ascii_letters + string.digits  
      #abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      print("".join(random.sample(k, 4)))
      

      还有一个有趣的东西:洗牌

      import random
      import string
      
      k = string.ascii_letters + string.digits  
      #abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      k_list = list(k)
      random.shuffle(k_list)
      
      print(k_list)
      #['K', 'H', 'a', 'Z', '8', 'B', '0', 'c', '2', 'A', 'h', 'e', 'P', 'X', '7', 'R', 'u', 'l', 'S', '6', 'o', 'O', 'I', 'f', 'E', 'Q', 'C', '5', 'j', 'd', 'n', 'r', 'x', 'G', 'b', 'Y', 'U', 'M', 'W', 'T', 'm', 'p', 'q', '4', 'i', 's', 'g', '3', 'N', 'V', 't', 'D', 'L', 'y', 'J', '9', 'F', 'z', '1', 'v', 'k', 'w']
      

      洗的乱吧!洗牌就是这样的东西!


    4、pickel:序列化

    • 一般拿到数据类型之后,我们想要存储到硬盘是不能的,因为只支持字符串和字节的模式的存储,所以才有了序列化存在的意义

      dic = {"da": 135,
             "daf": 43,
             "gawe": 546,
             "fefw": 455}
      
      f = open("123.txt","w")
      f.write(dic)
      f.close()
      print(f)
      

      直接写就会报错!

      如果用序列化呢?先看看序列化之后是什么

      import pickle
      dic = {"da": 135,
             "daf": 43,
             "gawe": 546,
             "fefw": 455}
      
      print(pickle.dumps(dic))
      # f = open("123.txt","w")
      # f.write(dic)
      # f.close()
      # print(f)
      
      

      字节模式啊,那你就可以存储了,写入文件了是吧!

      那我要是想把这个字节模式给返回呢?

      那就叫反序列化

      import pickle
      
      dic = {"da": 135,
             "daf": 43,
             "gawe": 546,
             "fefw": 455}
      
      s = pickle.dumps(dic)
      
      print(pickle.loads(s))
      

      那我们现在开始搞一些操作!将这些写在文件:

      import pickle
      
      dic = {"da": 135,
             "daf": 43,
             "gawe": 546,
             "fefw": 455}
      
      s = pickle.dumps(dic)
      
      f = open("123.pkl", "wb")  # 后缀用pkl 代表是序列化过的  wb 是因为是字节模式
      # f.write(s)               # 可以这么写,但是 pickel 提供了新的方法
      pickle.dump(dic, f)
      
      f.close()
      

      那我们要是想拿出来呢?常规操作!

      import pickle
      
      f = open("123.pkl", "rb")  # rb 是因为是字节模式
      
      print(pickle.load(f))
      
      f.close()
      

      要记住一个事

      比如我分三次dump进去数据

      那我到取出来的时候

      每load一次,就取出一次数据

      先进先出!

      pickle&json区别

      pickle 可以每次都dump() 然后循环load()

      json 就是只能dump()一次,load()一次

      pickle 只能用在python 支持所有数据类型 函数体啊对象啊都支持

      json 所有语言都支持,只支持常规数据类型 str int dict set list tuple


    5、hashlib模块:加密算法

    • 就是通过算法,变换成固定长度的输出,该输出是个数列值。但是不能通过数列值来反推

      比如:

      dawaaaa⇨hashlib⇨1233211234567

      fheigoesjgpejgp⇨hashlib⇨1233211234567

      虽然说几率不大,但是是有可能的!

      而这种现象,就是“撞库”

      但是,每次启动的时候

      相同的字符串的哈希是不一样的!

      那我这随机加密??没什么用啊!!!

      所以 就 根据 哈希算法 就研究出了 MD5 加密


    • MD5

      想看概念,自己百度去

      不可逆!!!

      为啥用??

      安全!!!防止被篡改!!!

      防止直接看明文!!!!!!

      数字签名(不知道也行)

      import hashlib
      
      m = hashlib.md5()
      
      m.update("hello world")
      
      print(m.digest())
      

      直接这么写,会报错!

      是因为没有转换成byte类型

      import hashlib
      
      m = hashlib.md5()
      
      m.update(b"hello world")
      
      print(m.digest())
      

      返回值都是字节,所以为了好看,我们转换为16进制

      import hashlib
      
      m = hashlib.md5()
      
      m.update(b"hello world")
      
      print(m.hexdigest())
      # 5eb63bbbe01eeed093cb22bb8f5acdc3
      

      这就熟悉了吧!


    6、shutil 模块:文件copy

    • 高级的 文件、文件夹、压缩包 处理模块

      shutil.copyfileobj(fsrc, fdst[, length])

      将文件内容拷贝到另一个文件中

      import shutilshutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
      

      shutil.copyfile(src, dst)

      拷贝文件

      shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在
      

      shutil.copymode(src, dst)

      仅拷贝权限。内容、组、用户均不变

      shutil.copymode('f1.log', 'f2.log') #目标文件必须存在
      

      shutil.copystat(src, dst)

      仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

      shutil.copystat('f1.log', 'f2.log') #目标文件必须存在
      

      shutil.copy(src, dst)

      拷贝文件和权限

      import shutilshutil.copy('f1.log', 'f2.log')
      

      shutil.copy2(src, dst)

      拷贝文件和状态信息

      import shutilshutil.copy2('f1.log', 'f2.log')
      

      shutil.ignore_patterns(*patterns)

      shutil.copytree(src, dst, symlinks=False, ignore=None)

      递归的去拷贝文件夹

      import shutilshutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
      #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
      

      shutil.rmtree(path[, ignore_errors[, onerror]])

      递归的去删除文件

      import shutilshutil.rmtree('folder1')
      

      shutil.move(src, dst)

      递归的去移动文件,它类似mv命令,其实就是重命名。

      import shutilshutil.move('folder1', 'folder3')
      

      shutil.make_archive(base_name, format,…)

      创建压缩包并返回文件路径,例如:zip、tar

      可选参数如下:

      • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,

      如 data_bak =>保存至当前路径

      如:/tmp/data_bak =>保存至/tmp/

      • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
      • root_dir: 要压缩的文件夹路径(默认当前目录)
      • owner: 用户,默认当前用户
      • group: 组,默认当前组
      • logger: 用于记录日志,通常是logging.Logger对象
      #将 /data 下的文件打包放置当前程序目录
      import shutil
      ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
      #将 /data下的文件打包放置 /tmp/目录
      import shutil
      ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
      

      shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:

      zipfile压缩&解压缩

      import zipfile
      # 压缩
      z = zipfile.ZipFile('laxi.zip', 'w')
      z.write('a.log')
      z.write('data.data')
      z.close()
      # 解压
      z = zipfile.ZipFile('laxi.zip', 'r')
      z.extractall(path='.')z.close()
      

      tarfile压缩&解压缩

      import tarfile
      # 压缩
      >>> t=tarfile.open('/tmp/egon.tar','w')
      >>> t.add('/test1/a.py',arcname='a.bak')
      >>> t.add('/test1/b.py',arcname='b.bak')
      >>> t.close()
      # 解压
      >>> t=tarfile.open('/tmp/egon.tar','r')
      >>> t.extractall('/egon')
      >>> t.close()
      

    7、re模块:正则表达式

    • 需求

      请从以下文件里取出所有的手机号

      姓名        地区    身高    体重    电话
      张三     北京    171    48    13651054656
      李四     上海    169    46    13813234455
      王五     深圳    173    50    13744234545
      赵六     广州    172    52    15823423569
      刘能     北京    175    49    18623423478
      大脚     北京    170    48    18623423789
      长贵     深圳    177    54    18835324583
      香秀     深圳    174    52    18933434482
      大国     上海    171    49    18042432356
      大拿     北京    167    49    13324523343
      

      你能想到的办法是什么?

      必然是下面这种吧?

      f = open("象牙山.txt",'r',encoding="gbk")
      phones = []
      for line in f:   
          name,city,height,weight,phone = line.split()    
          	if phone.startswith('1') and len(phone) == 11:        		phones.append(phone)
      print(phones)
      

      有没有更简单的方式?

      手机号是有规则的,都是数字且是11位,再严格点,就都是1开头,如果能把这样的规则写成代码,直接拿规则代码匹配文件内容不就行了?

      import re
      
      f = open("象牙山.txt")
      data = f.read()
      print(re.findall("[0-9]{11}", data))
      

      这么nb的玩法是什么?它的名字叫正则表达式


    • re模块

      正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是re


      常用规则!!!!!!!!!!!!!!!!!!

      (偷的图,,,不不不,,读书人的事情怎么能叫偷呢?)


      re的匹配语法有以下几种

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

      有几个比较好玩的应用

      你想通过数字将字符串进行分割,怎么办呢?

      import re
      
      s = "f5few4f864f634g6sg4g48e"
      print(re.findall("\D+", s)) # ['f', 'few', 'f', 'f', 'g', 'sg', 'g', 'e']
      

      知道身份证号吧(230811199704147033)

      知道组成格式吧(不知道去百度去)

      那我们想拿到城市等相关信息怎么做呢?

      import re
      
      s = "230811199704147033"
      print(re.search("([0-9]{3})([0-9]{3})([0-9]{4})", s).group())
      # 2308111997
      

      那我想分开打印呢?(group⇨groups)

      # ('230', '811', '1997')
      

      那我还想把它变成字典呢???(?P<字典的键>)

      import re
      
      s = "230811199704147033"
      print(re.search("(?P<province>[0-9]{3})(?P<city>[0-9]{3})(?P<year>[0-9]{4})", s).groupdict())
      # {'province': '230', 'city': '811', 'year': '1997'}
      

      其他的还有什么呢?

      re.search(pattern, string, flags=0)

      根据模型去字符串中匹配指定内容,匹配单个

      import re
      obj = re.search('\d+', 'u123uu888asf')
      if obj:
          print obj.group()
      

      re.findall(pattern, string, flags=0)

      match and search均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。

      import re
      obj = re.findall('\d+', 'fa123uu888asf')
      print obj
      

      re.sub(pattern, repl, string, count=0, flags=0)

      用于替换匹配的字符串,比str.replace功能更加强大

      >>>re.sub('[a-z]+','sb','武配齐是abc123',)
      >>>re.sub('\d+','|','alex22wupeiqi33oldboy55',count=2)
      'alex|wupeiqi|oldboy55'
      

      re.split(pattern, string, maxsplit=0, flags=0)

      用匹配到的值做为分割点,把值分割成列表

      >>>s='9-2*5/3+7/3*99/4*2998+10*568/14'
      >>>re.split('[\*\-\/\+]',s)
      ['9', '2', '5', '3', '7', '3', '99', '4', '2998', '10', '568', '14']
      >>> re.split('[\*\-\/\+]',s,3)
      ['9', '2', '5', '3+7/3*99/4*2998+10*568/14']
      

      re.fullmatch(pattern, string, flags=0)

      整个字符串匹配成功就返回re object, 否则返回None

      re.fullmatch('\w+@\w+\.(com|cn|edu)',"alex@oldboyedu.cn")
      

    • 标识符

      • re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
      • re.M(MULTILINE): 多行模式,改变’^’和’$’的行为
      • re.S(DOTALL): 改变’.’的行为,make the ‘.’ special character match any character at all, including a newline; without this flag, ‘.’ will match anything except a newline.
      • re.X(re.VERBOSE) 可以给你的表达式写注释,使其更可读,下面这2个意思一样
      a = re.compile(r"""\d + # the integral part           \. # the decimal point\d * # some fractional digits""",re.X)
      b = re.compile(r"\d+\.\d*")
      

*re强无敌*
*快学快学*
posted @ 2019-07-14 00:00  吃夏天的西瓜  阅读(515)  评论(0编辑  收藏  举报