8月1号分享

装饰器讲解

  • 示例

    2. 编写装饰器,在每次执行被装饰函数之前打印一句’每次执行被装饰函数之前都得先经过这里,这里根据需求添加代码’
    3. 编写装饰器,在每次执行被装饰函数之后打印一句’每次执行完被装饰函数之后都得先经过这里,这里根据需求添加代码’
    4. 编写装饰器,在每次执行被装饰函数之前让用户输入用户名,密码,给用户三次机会,登录成功之后,才能访问该函数.
    5. 编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件,只支持单用户的账号密码,给用户三次机会),要求登录成功一次,后续的函数都无需再输入用户名和密码
    6. 编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件,可支持多账号密码),要求登录成功一次(给三次机会),后续的函数都无需再输入用户名和密码。
    7. 给每个函数写一个记录日志的功能,
    
    功能要求:每一次调用函数之前,要将函数名称,时间节点记录到log的日志中。
    所需模块:
    import time
    struct_time = time.localtime()
    print(time.strftime("%Y-%m-%d %H:%M:%S",struct_time))
    
    复习装饰器:
    装饰器是干嘛的?有什么用?
    统计爬虫函数的工作效率
    
    import time
    def timmer(func): #func = 爬虫函数
        def inner():
            start =time.time()
            func() #func() = 爬虫函数的地址() ==>调用了爬虫函数
            print(time.time()- start) #结果就是爬虫函数执行的时间
        return inner
    
    def 爬虫函数():
        '''爬虫的功能'''
    # 完成爬虫函数的基础上再完成一些新的功能
    爬虫函数 = timmer(爬虫函数) #爬虫函数 = inner的地址
    爬虫函数() #inner()
    
    ---
    # 不能紧耦合 因为拆分功能的时候容易出错
    # 不能轻易改变代码的调用习惯
    
    # 如果加上了装饰器,在调用“爬虫函数”的时候,实际上还调用了一个timmer的功能,那么没有改变用户的调用习惯,但是加上了新功能 --装饰器做的事儿
    # a有一个装饰器b 如果调用a函数,不仅把a函数执行了,还要执行b函数中的代码
    ---
    
    ---
    #在调用爬虫函数的时候执行了inner里面的内容,也同时调用爬虫函数本身
    #就相当于调用了一个爬虫函数,没改变,调的还是爬虫函数,但实际上又增加了一个新的功能
    #不仅执行了爬虫函数本身的功能还执行了inner功能
    #这就是装饰器的作用
    ---
    问题1:为什么用爬虫函数接收timmer
    解答:
    我不能调用timmer,我只能调用爬虫函数,但又希望调用爬虫函数相当于调用了timmer,所以用爬虫函数接收timmer
    
    问题2:装饰器里面执行一些动作的时候不知道放在func()上面还是下面
    解答:有的地方是固定的,有的地方是不固定的,没有明确定义,根据需要来决定
    
    
    import time
    def timmer(func): #func = 爬虫函数
        def inner():
            start =time.time()
            func() #爬虫函数的地址() ==>调用了爬虫函数
            print(time.time()- start) #就是爬虫函数执行的时间
        return inner
    @timmer #爬虫函数 = timmer(爬虫函数) #爬虫函数 = inner的地址
    		#@timmer自动把爬虫函数地址切换成inner地址
    def 爬虫函数():
        '''爬虫的功能'''
    
    爬虫函数() #inner()
    爬虫函数() #不管调用了多少次爬虫函数都相当于调inner()
    爬虫函数() #调了多少次爬虫函数就调了多少次inner()
    
    import time
    def timmer(func): #func = 爬虫函数
        def inner():
            start =time.time()
            func() #被装饰的函数
            print(time.time()- start) #就是爬虫函数执行的时间
        return inner
    @timmer #爬虫函数 = timmer(爬虫函数) #爬虫函数 = inner的地址
    def 爬虫函数():
        '''爬虫的功能'''
    #完成爬虫函数的基础上再完成一些新的功能
    爬虫函数() #inner()
    # timmer 装饰器
    # 爬虫函数 是被装饰的函数
    # 调用 爬虫函数()  相当于调用inner函数
    # inner函数里的func是通过timmer传递过来的爬虫函数 (inner里执行了被装饰的函数)
    
  • 装饰的是谁inner中func()执行的就是谁

    import time
    def timmer(func): #func = 计算器函数
        def inner():
            start =time.time()
            func() #被装饰的函数,计算器函数
            print(time.time()- start) #就是爬虫函数执行的时间
        return inner
    @timmer #爬虫函数 = timmer(爬虫函数) #爬虫函数 = inner的地址
    def 爬虫函数():
        '''爬虫的功能'''
    
    @timmer #计算器函数 = timmer(计算器) #计算器 = inner的地址
    def 计算器():
        '''计算器的功能'''
    
    爬虫函数() #inner()
    
    #装饰的是谁inner中func()执行的就是谁
    
  • 固定模式

    def wrapper(func):
        def inner(*args,**kwargs):
            ret = func(*args,**kwargs) #func()就是wahaha函数
            return ret
        return inner
    
    @wrapper #@wrapper ==> wahaha = wrapper(wahaha) = inner
    def wahaha(name):
        print(1234,name)
        return 123
    
    @wrapper
    def qqxing(age):
        print(1234,age)
        return 456
    ret = wahaha('alex') #wahaha就是装饰器的inner函数
    print(ret)
    ret1 = xixi= qqxing('xiaxia')
    print(ret1)
    
  • 想在调用wahaha之前做登录

    def wrapper(func):
        def inner(*args,**kwargs):
            #在执行func之前写登录逻辑,登录成功才能执行wahaha
            ret = func(*args,**kwargs) #func()就是wahaha函数,wahaha是被装饰的函数,你希望被装饰的函数和你即将要添加的逻辑什么关系,你就在哪儿添加代码
            #如果想在登录之后打印log执行func()之后执行打印log代码
            return ret
        return inner
    
    @wrapper #@wrapper ==> wahaha = wrapper(wahaha) = inner
    def wahaha(name):
        print(1234,name)
        return 123
    
    @wrapper
    def qqxing(age):
        print(1234,age)
        return 456
    ret = wahaha('alex') #wahaha就是装饰器的inner函数
    print(ret)
    ret1 = xixi= qqxing('xiaxia')
    print(ret1)
    
  • 所有的独立函数都要使用的功能就写在装饰器里

  • 问题装饰器里func之前要执行的功能,写单独的函数比较好,还是写功能比较好

  • 答:如果功能需要的代码很长就写函数,如果很短就写功能代码

  • 题目:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件,只支持单用户的账号密码,给用户三次机会),要求登录成功一次,后续的函数都无需再输入用户名和密码

    # 解析1:upload()、download()、move()这三个函数都需要先执行登录操作
    # 解析2:登录成功后upload()、download()、move()这三个函数调用就没有顺序规定了
    login_flag = False #先创建一个变量表示用户未登录状态
    def login(func):
        def inner(*args,**kwargs):
            global login_flag
            if login_flag is False: #如果login_flag是False说明用户还没登陆过
                username = input('username:')
                password = input('password:')
                with open(r'test',encoding='utf-8') as f:
                    for line in f:
                        line = line.strip()
                        lst = line.split('|')
                        user = lst[0]
                        pwd = lst[1]
                        if user == username and pwd == password:
                            print('登陆成功')
                            login_flag = True
                            break
                    else:
                        print('登陆失败')
                if login_flag: #如果login_flag为True就执行以下代码
                    ret = func(*args,**kwargs)
                    return ret
            return inner
    def upload():
        print('')
    def download():
        print('')
    def move():
        print('')
    
    upload()
    
    login_flag = False #先创建一个变量表示用户未登录状态
    def auth():
      global login_flag
        username = input('username:')
        password = input('password:')
        with open(r'G:\py27\其他脚本\test', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                lst = line.split('|')
                user = lst[0]
                pwd = lst[1]
                if user == username and pwd == password:
                    print('登陆成功')
                    login_flag = True
                    break
            else:
                print('登陆失败')
    
    def login(func):
        def inner(*args,**kwargs):
            i = 0 #利用i约束用户只能登陆3次
            while login_flag is False and i<3:#如果login_flag是False说明用户还没登陆过
                auth() #auth()是用户登录的逻辑
                i+=1
            if login_flag: #如果login_flag为True的时候才能执行被装饰的函数(就是以下代码)
                ret = func(*args,**kwargs) #被装饰的函数 upload download move
                return ret
        return inner
    @login
    def upload():
        print('这是一个上传文件的函数')
    
    @login
    def download():
        print('这是一个下载文件的函数')
    
    @login
    def move():
        print('这是一个移动文件的函数')
    
    upload()
    

生成器讲解

  • 示例

    def func(n):
      l = []
      for i in range(n):
       egg = '鸡蛋%s'%i
       l.append(egg)
      return l
    ret = func(100)
    print(ret)
    
    生成器:更省内存
    def 老母鸡(n): #生成器函数
      for i in range(n):
       egg = '鸡蛋%s'%i
       yield egg
    生蛋器 = 老母鸡(20) #生成器
    print(生蛋器)
    for egg in 生蛋器:
     print(egg)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值