• python笔记(13)--带参数装饰器和常用模块(os/sys/time/datetime)


    内容目录

    • 带参数的装饰器:flask框架 + dijango缓存 + 写装饰器实现被装饰的函数要执行N次
    • 模块
      • os
      • sys
      • time(三种类型)
      • datetime 和 timezone【了解】

    内容回顾&补充

    1.函数

    写代码的方式:面向过程 ---》函数式编程 ---》面向对象编程

    1.1函数基础

    def func(a1,a2):
        pass
    
    result = func(1,2)
    

    1.2参数

    补充:对于函数的默认值慎用可变类型

    # 如果要想给value设置默认是空列表
    
    #不推荐(坑)
    def func(data,value=[]):
        pass
    
    #推荐
    def func(data,value=None):
        if not value:
            value = []
            
    

    面试题:

    • def func(a,b = [ ])有什么陷阱
    • 看代码写结果
    def func(a,b=[]):
        b.append(a)
        return b
    
    list1 = func(1)
    list2 = func(2,[11,22,33])
    list3 = func(3)
    
    print(list1,list2,list3)
    #l1 = [1,3]
    #l2 = [11,22,33,2]
    #l3 = [1,3]
    #解析:因为传参的时候,函数内使用的是自己的列表,l1结果运行后函数内有列表[1],l3运行则在函数内的列表中增加了参数值。但是l2使用的是传参进去的列表,所以不受影响
    

    1.3返回值

    闭包:

    # 不是闭包
    def func1(name):
        def inner():
            return 123
        return inner
    
    # 是闭包:封装值 + 内层函数需要使用。
    def func2(name):
        def inner():
            print(name)
            return 123
        return inner
    

    1.4作用域

    1.5递归

    • 函数自己调用自己。(效率低,容易爆栈)

    • 递归默认最大次数为1000。

      def func():
          print(1)
          func()
      
      func()
      
      def func(i):
          print(i)
          func(i+1)
       
      func(1)
      
      #用函数可以实现斐波那契数列
      def func(a,b):
          print(b)
          func(b,a+b)
      
      func(0,1)
      

    2.模块

    • hashlib
    • random
    • getpass
    • time

    内容详细

    1.装饰器

    1.1基本格式

    1.2关于参数

    #标准格式,必须加万能参数,好处是其他函数使用该装饰器时无需关注原函数的参数
    def x1(func):
        def inner(*args,**kwargs):
            return func(*args,**kwargs)
        return inner
    
    @x1
    def f1():
        pass
    
    @x1
    def f2(a1):
        pass
    
    @x1
    def f3(a1,a2):
        pass
    

    1.3关于返回值

    def x1(func):
        def inner(*args,**kwargs):
            data = func(*args,**kwargs)
            return data
        return inner
    
    @x1
    def f1():
        print(123)
        
    v1 = f1()		#v1 = None
    

    1.4关于前后

    def x1(func):
        def inner(*args,**kwargs):
            print('调用原函数之前')
            data = func(*args,**kwargs)#执行原函数并获取返回值
            print('调用原函数之后')
            return data
        return inner
    
    @x1
    def index():
        print(123)
        
    index()
    
    重点作业详解

    1.请为以下函数编写一个装饰器,添加上装饰器后可以实现:执行 read_userinfo 函时,先检查文件路径是否存在,如果存在则执行后,如果不存在则 输入文件路径不存在,并且不再执行read_userinfo函数体中的内容,再讲 content 变量赋值给None。

    def read_userinfo(path):
        file_obj = open(path,mode='r',encoding='utf-8')
        data = file_obj.read()
        file_obj.close()
        return data
    
    content = read_userinfo('/usr/bin/xxx/xxx')
    
    """
    温馨提示:如何查看一个路径是否存在?
    import os
    result = os.path.exists('路径地址')
    
    # result为True,则表示路径存在。
    # result为False,则表示路径不存在。
    """
    ############解 答#############
    import os
    
    def index(arg):
        def inner(*args,**kwargs):
            #检查路径是否存在
            path = args[0]      #*args传参进来为一个元组,如要拿哪个元素,可以使用元组下标表示
            if not os.path.exists(path):
                print('路径不存在')
                return
            data = arg(*args, **kwargs)
            return data
        return inner
    
    
    @index
    def read_userinfo(path):
        file_obj = open(path,mode='r',encoding='utf-8')
        data = file_obj.read()
        file_obj.close()
        return data
    
    content = read_userinfo('D:pycharm_projectpython36log.txt')
    print(content)
    

    1.5带参数的装饰器

    #第一步:执行 ret = xxx(index)
    #第二步:将返回值赋值给 index = ret
    @xxx
    def index():
        pass
    
    #第一步:执行 v1 = uuu(9)
    #第二步:ret = v1(index)
    #第三步:index = ret
    @uuu(9)
    def index():
        pass
    
    # ###############普通装饰器################
    def wrapper(func):
        def inner(*args,**kwargs):
            print('执行之前')
            data = func(*args,**kwargs)
            print('执行之后')
            return data
        return inner
    
    @wrapper
    def index():
        pass
    
    # ###############带参数装饰器################
    #相当于可以带参数的装饰器,函数中没有就往父级函数中找参数
    def x(counter):
        def wrapper(func):
            def inner(*args,**kwargs):
                print('执行之前')
                data = func(*args,**kwargs)
                print('执行之后')
                return data
            return inner
        return wrapper
    
    @x(9)   # index = 先执行x(9)函数,拿到返回值(内层函数wrapper),再执行wrapper(index)
    def index():
        pass
    

    练习题:

    # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,每次结果添加到列表中,最终返回列表
    
    import random
    
    def xxx(counter):
        print('x函数')
        def wrapper(func):
            print('wrapper函数')
            def inner(*args,**kwargs):
                v = [func(*args,**kwargs) for i in range(counter)]
                return v
            return inner
        return wrapper
    
    @xxx(6)
    def index():
        return random.randint(1,6)
    
    v = index()
    print(v)
    
    # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,每次结果添加到列表中,返回最后一次执行的结果【面试题】
    
    import random
    def xxx(counter):
        print('x函数')
        def wrapper(func):
            print('wrapper函数')
            def inner(*args,**kwargs):
                v = [func(*args,**kwargs)]
                return v
            return inner
        return wrapper
    
    @xxx(6)
    def index():
        return random.randint(1,6)
    
    v = index()
    print(v)
    

    1.6 自学补充

    • 元数据:flask框架

    • 多个装饰器:flask框架

      @x1
      @x2
      def func():
          pass
      

    总结:

    基本装饰器(更重要)

    def x1(func):
        def inner(*args,**kwargs):
            print('调用原函数之前')
            data = func(*args,**kwargs)#执行原函数并获取返回值
            print('调用原函数之后')
            return data
        return inner
    
    @x1
    def index():
        print(123)
        
    index()
    

    带参数的装饰器:

    #相当于可以带参数的装饰器,函数中没有就往父级函数中找参数
    def x(counter):
        def wrapper(func):
            def inner(*args,**kwargs):
                print('执行之前')
                data = func(*args,**kwargs)
                print('执行之后')
                return data
            return inner
        return wrapper
    
    @x(9)   # index = 先执行x(9)函数,拿到返回值(内层函数wrapper),再执行wrapper(index)
    def index():
        pass
    

    2.模块

    2.1 sys模块

    • sys.getrefcount:获取一个值的应用计数

      import sys
      #获取一个值的应用计数
      a = [11,22,33]
      b = a
      print(sys.getrefcount(a))	#输出为3
      
    • sys.getrecursionlimit:查询python默认支持的递归最大值

      import sys
      #python默认支持的递归最大值
      v1 = sys.getrecursionlimit()
      print(v1)		#结果为1000
      
    • sys.stdout.write --> 相当于print()

      • 示例:进度条
        • 为覆盖原值,取最后一值
      #进度条示例:
      import sys
      import time
      
      for i in range(1,101):
          msg = "%s%%
      " %i
          print(msg,end = '')
          time.sleep(0.05)
      
    • 进度条示例:文件复制并取读取文件的进度条

      #读取文件并写入进度条,将文件复制到另一个文件中。
      import os
      #1.获取文件的大小
      file_size = os.stat('20190904.mp4').st_size		#os模块中st_size为获取文件大小(字节)
      
      #一点一点的读取文件,并写入a.mp4文件中
      read_size = 0
      with open('20190904.mp4',mode="rb") as f1,open('a.mp4',mode='wb')as f2:
          while read_size < file_size:
              chunk = f1.read(1024)   #每次最多读取1024字节
              f2.write(chunk)
              read_size += len(chunk)
              val = int(read_size / file_size * 100)
              print("%s%%
      "%val,end='')
      
    • sys.argv:(运维常用(重要)

      import sys
      
      #获取用户执行脚本时,传入参数
      #在CMD中运行该脚本,并传入要删除的文件路径(D:/test)
      #C:python36python36.exe D:/pycharm_project/python36/code01.py D:/test
      #sys.argv = ['D:/pycharm_project/python36/code01.py','D:/test']
      path = sys.argv[1]      #此时path = ['D:/test']
      print(path)
      
      import shutil	#使用删除功能的模块
      chack = input("是否要删除%s文件,(输入Y确认删除)"%path).strip().upper()
      if chack == 'Y':
          shutil.rmtree(path)		#删除文件路径的操作
          print("删除成功")
      else:
          print("已退出当前操作")
          exit()
      

      1567585791482

      #练习题:让用户传参,两个参数,第一个是文件,第二个是内容,把内容追加到文件中去
      import sys
      print(sys.argv)
      if len(sys.argv) < 3 :
          print('参数不够,请重新输入')
          sys.exit(0)
      else:
          file_path = sys.argv[1]
          data_path = sys.argv[2]
          with open(file=file_path,mode='a',encoding='utf-8') as f:
              f.write(data_path)
      

      1567669824855

    • sys.exit(0):程序终止,遇到此命令,整个程序终止

      import sys
      
      
      def x1():
          print(123)
      
      def x2():
          print(456)
          
      x1()
      sys.exit(0)
      x2()		#只执行x1,不执行x2.
      
    • sys.path ----后续补充

    2.2 os模块

    和操作系统相关的数据

    • os.path.exists(path):如果path存在,返回True;如果path不存在,返回False

    • os.stat('20190904.mp4').st_size:获取文件大小

    • os.path.abspath():获取文件的绝对路径

      import os
      
      path = '20190904.mp4'
      
      v1 = os.path.abspath(path)
      print(v1)			#输出为D:pycharm_projectpython3620190904.mp4,等于path的绝对路径
      
    • os.path.dirname:获取路径的上级目录

      import os
      
      path = r'D:pycharm_projectpython3620190904.mp4'	#注意加r,转义符
      v1 = os.path.dirname(path)
      print(v1)			#输出为D:pycharm_projectpython36,等于path的上级目录
      
      • 补充(转义)

        #字符串前加r等于转义,推荐使用这个
        path = r'D:pycharm_projectpython3620190904.mp4'
        print(path)
        
        #两个反斜杠代表转义
        path = 'D:\pycharm_project\python36\n20190904.mp4'
        
    • os.path.join:路径拼接,会根据当前系统进行路径拼接

      import os
      
      path = r'D:pycharm_projectpython36'
      v = 'n.txt'
      
      result = os.path.join(path,v)
      print(result)		#结果为D:pycharm_projectpython36
      .txt
      #或者:
      result1 = os.path.join(path,'n1','n2','n3')
      print(result)		#结果为D:pycharm_projectpython36
      1
      2
      3
      
    • os.listdir:只列当前目录下所有的文件【第一层】

      import os
      result = os.listdir(r'D:pycharm_projectpython36')
      for path in result:
          print(path)
      #结果为列出了当前目录下所有的文件
      
    • os.walk:列出该目录下所有的文件,包括文件夹内的路径【所有层】【面试题】

      import os
      result = os.walk(r'D:pycharm_projectpython36')
      for a,b,c in result:
          print(a,b,c)
          
      #找到路径下所有的文件呢
      import os
      result = os.walk(r'D:pycharm_projectpython36')
      for a,b,c in result:
          #a,正在查看的目录 b,此目录下的文件夹 c,此目录下的文件
          for item in c:
              path = os.path.join(a,item)
              print(path)
      
    • os.remove(path):删除单个文件

      • path是文件的路径,如果这个路径是一个文件夹,则会抛出OSError的错误,这时需用用rmdir()来删除
    • os.rmdir(path):

      • path是文件夹路径,注意文件夹需要时空的才能被删除os.unlink('F:新建文本文档.txt')
    • os.unlink(path):

      • 功能和remove一样是删除一个文件,但是删除一个删除一个正在使用的文件会报错。

    2.3 shutil删除模块

    • shutil.rmtree():删除树文件,路径下所有的文件全部删除

      import shutil
      shutil.rmtree(path)
      
      ###示例###
      import sys
      import shutil	#使用删除功能的模块
      #获取用户执行脚本时,传入参数
      #在CMD中运行该脚本,并传入要删除的文件路径(D:/test)
      #C:python36python36.exe D:/pycharm_project/python36/code01.py D:/test
      #sys.argv = ['D:/pycharm_project/python36/code01.py','D:/test']
      path = sys.argv[1]      #此时path = ['D:/test']
      print(path)
      
      chack = input("是否要删除%s文件,(输入Y确认删除)"%path).strip().upper()
      if chack == 'Y':
          shutil.rmtree(path)		#删除文件路径的操作
          print("删除成功")
      else:
          print("已退出当前操作")
          exit()
      

    总体总结:

    • 普通装饰器
      • 参数
      • 返回值
      • 前后
    • 带参数的装饰器
    • 模块
      • random
      • hashlib
      • getpass
      • time(重点)
      • os(重点)
      • sys
      • shutil
  • 相关阅读:
    MYSQL主从同步故障一例及解决过程
    mysql主从复制
    I want a mysqldump –ignore-database option
    MYSQL使用mysqldump导出某个表的部分数据
    Linux MySQL主从复制(Replication)配置
    mysql mysqldump只导出表结构或只导出数据的实现方法
    Mysql导出表结构及表数据 mysqldump用法
    MVC 数据验证
    JS中call、apply的用法说明
    js 与或运算符 || && 妙用
  • 原文地址:https://www.cnblogs.com/lynlearnde/p/12909512.html
Copyright © 2020-2023  润新知