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_project\python36\log.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()

    • 示例:进度条
      • \r 为覆盖原值,取最后一值
    #进度条示例:
    import sys
    import time
    
    for i in range(1,101):
        msg = "%s%%\r" %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%%\r"%val,end='')
    
  • sys.argv:(运维常用(重要)

    import sys
    
    #获取用户执行脚本时,传入参数
    #在CMD中运行该脚本,并传入要删除的文件路径(D:/test)
    #C:\python36\python36.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_project\python36\20190904.mp4,等于path的绝对路径
    
  • os.path.dirname:获取路径的上级目录

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

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

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

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

    import os
    result = os.walk(r'D:\pycharm_project\python36')
    for a,b,c in result:
        print(a,b,c)
        
    #找到路径下所有的文件呢
    import os
    result = os.walk(r'D:\pycharm_project\python36')
    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:\python36\python36.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
posted @ 2020-05-18 11:23  薛定谔的猫儿  阅读(94)  评论(0编辑  收藏  举报