zoukankan      html  css  js  c++  java
  • day19 装饰器

    Python之路,Day7 = Python基础7


    random
    wrapper 包装材料;包装纸;书皮
    global a 全局的(也就是,函数最外面的那个)
    nonlocal a 局部的,上层的函数的变量,如果函数中没有,不会去全局变量中找,直接报错


    # 闭包函数: 1.内部函数 2.对外部作用域的引用(全局变量除外)
    # 闭包函数的特点:
      自带作用域
      延迟计算或惰性计算
    f.__closure__ 所有的闭包函数都有这个方法,也就是说,如果有这个方法,就证明它是闭包函数
    f.__closure__[0].cell_contents 查看闭包函数里面的外部包含的变量(只包含自己调用的那个变量)


    装饰器
      定义:装饰器本质为任意可调用的对象,被装饰的对象也可以为任意可调用的对象。。。
      功能:在不修改被装饰对象的源代码及调用方式的前提下,为其添加新功能
      原则:
        1.不修改源代码
        2.不修改调用方法

      语法:
        在被装饰的函数上方的一行协商 @装饰器的名字



    def outer(func):
      def inner(*args, **kwargs):
        print("111")
        res = func(*args, **kwargs)
        print('222')
        return res
      return inner

    ======================homework=============

    一:编写函数,(函数执行的时间是随机的)
    二:编写装饰器,为函数加上统计时间的功能
    三:编写装饰器,为函数加上认证的功能

    四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
    注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 # __author__ = "Always"
     4 # Date: 2017/6/14
     5 
     6 import time, random
     7 
     8 auth = {'login':False}
     9 
    10 def aut():
    11     """
    12     从文件读取用户名和密码,从而验证是否登录成功
    13     登陆成功后,修改登陆状态
    14     """
    15     while True:
    16         username = input('username:').strip()
    17         password = input('password:').strip()
    18         if not username or not password:continue
    19 
    20         with open('username', 'r', encoding='utf-8') as f:
    21             for i in f:
    22                 userinfo = eval(i.strip())
    23                 if username == userinfo['name'] and password == userinfo['password']:
    24                     auth['login'] = True
    25                     return 1
    26             else:
    27                 print('Inout Error...')
    28 
    29 
    30 def check(func):
    31     """
    32     检查 auth 的登陆状态,如果为 False, 需要验证,否则,不需要验证
    33     :return:
    34     """
    35     def wrapper(*args, **kwargs):
    36         if auth['login'] == False:
    37             aut()
    38         func()
    39     return wrapper
    40 
    41 def timmer(func):
    42     """
    43     这个是装饰器
    44     为函数添加一个新功能:打印运行程序时使用花费的时间
    45     :return:
    46     """
    47     def wrapper(*args, **kwargs):
    48         start_time = time.time()
    49         res = func(*args, **kwargs)
    50         stop_time = time.time()
    51         print('All cost %s.'%(stop_time - start_time))
    52         return res
    53 
    54     return wrapper
    55 @check
    56 @timmer
    57 def say_hello():
    58     """
    59     打印一个 hello。。。 ,每个字母间隔随机秒
    60     :return:
    61     """
    62     for i in 'Hello。。。':
    63         print(i)
    64         time.sleep(random.randrange(1,2))
    65 
    66 @check
    67 @timmer
    68 def say_goodbye():
    69     for i in 'goodbye。。。':
    70         print(i)
    71         time.sleep(random.randrange(1, 2))
    72 
    73 # say_hello()
    74 
    75 say_hello()
    76 say_goodbye()

    五:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

    六:为题目五编写装饰器,实现缓存网页内容的功能:
    具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

    七:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    # __author__ = "Always"
    # Date: 2017/6/14
    
    import os, sys, time
    if not os.path.exists(r'缓存'):
        os.mkdir(r'缓存')
    
    
    url_dict = {'baidu':'http://www.baidu.com',
                '52pojie':'http://www.52pojie.cn',
                }
    
    
    from urllib.request import urlopen
    
    
    def wrapper(func):
        """
        这是个装饰器,主要的作用是接收一个url的路径,然后返回这个网页的代码
        :param func:
        :return:
        """
        def inner(*args, **kwargs):
    
            file_name = args[0].split('.')[1]
            if os.path.exists(r'缓存/%s'%file_name) and os.path.getsize(r'缓存/%s'%file_name) > 0:
                with open(r'缓存/%s'%file_name, 'rb') as f:
                    print('缓存已经存在,正在读取。。。')
                    time.sleep(2)
                    return f.read()
    
            # 将新网址加入字典中
            url_dict[file_name] = args[0]
    
    
            print('正在从网上下载。。。')
            time.sleep(2)
            res = func(*args, **kwargs)
            # print(res)
            # print(type(res))
    
            # print(res)
            # input()
            with open(r'缓存/%s' % file_name, 'wb') as f:
                f.write(res)
            # input('回车键结束。。。。')
            return res
        return inner
    
    
    @wrapper
    def get(url):
        return urlopen(url).read()
    
    
    
    # res = get('http://www.baidu.com')
    # print(res.decode())
    
    # print(get('http://www.baidu.com').decode())
    
    while True:
        choose_list = []
        for c, i in enumerate(url_dict):
            choose_list.append(i)
            print(' %s  %s		%s'%(c+1, i, url_dict[i]))
        choose = input('
    请输入序号或直接输入网址:http://www.baidu.com
    >>>').strip()
        if choose.upper() == "Q":
            break
        elif choose.isdigit() and 0 < int(choose) <= len(choose_list):
    
    
            res = get(url_dict[choose_list[int(choose) - 1]])
            print(res)
        elif 'http://' in choose:
            res = get(choose)
            print(res)
        else:
            print('输入错误')
        time.sleep(2)

    初写代码,BUG,不足之处自然很多,如有问题,欢迎指出。

     谢谢!!!

  • 相关阅读:
    linux软件安装方式
    docker 安装 jenkins touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
    [ERR] Node goodsleep.vip:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
    Linux 常用命令 服务器间scp 用户 export 创建文件、软连接
    redis 安装 集群 主从 哨兵 docker
    WPF密码框中禁止复制、粘贴
    Application 统计在线人数
    【转义字符】HTML 字符实体&lt; &gt: &amp;等
    SQL语句统计每天的数据
    正则表达式计算代码数
  • 原文地址:https://www.cnblogs.com/alwaysInMe/p/7011328.html
Copyright © 2011-2022 走看看