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,不足之处自然很多,如有问题,欢迎指出。

     谢谢!!!

  • 相关阅读:
    沙盒中Documents、Library和tmp的用处 iOS
    LeetCode二叉树的前序遍历、中序遍历、后序遍历、层序遍历、最大深度Swift
    LeetCode判断一个单向链表是否有环?
    C#字符串处理
    【源码分享】十套C#管理系统程序源码
    【源码分享XY01】C#学生管理系统
    HL7的简单介绍
    【源码分享XY06】C#MVC+Sqlserver员工信息管理系统
    【源码分享XY04】php+MySQL开发的图书管理系统
    js将数值转为个十百千万显示
  • 原文地址:https://www.cnblogs.com/alwaysInMe/p/7011328.html
Copyright © 2011-2022 走看看