• day20 装饰器补充


    Python之路,Day8 = Python基础8

    装饰器
    from functools imoort wraps # 保留原函数所有信息,比如:用__doc__查看注释的时候,显示原来的注释
    def func01(func):
      @wraps(func) # 用__doc__查看注释的时候,显示原来的注释
      def wrapper(*args, **kwargs):
        print('func01---------------------01')
        res = func(*args, **kwargs)
        print('func01---------------------02')
        return res
      # 上面的效果就相当于在这里加了一句 wrapper.__doc__ = func.__doc__
      return wrapper

      装饰器的参数:
        再包一层

    def doco(file_type = 'file'):
        def outer(func):
            def wrapper(*args, **kwargs):
                if file_type == 'file':
                    print('with open file')
                elif file_type == 'mysql':
                    print('deal with mysql')
                else:
                    print('i do not konw how to deal')
                res = func(*args, **kwargs)
                return res
            return wrapper
        return outer
    
    
    
    @doco('file')
    def func1():
        print('fucn1')
    
    @doco('mysql')
    def func2():
        print('fucn2')
    
    @doco('abc')
    def func3():
        print('fucn3')
    
    func1()
    func2()
    func3()

    迭代器
      1.重复
      2.基于上一次的结果
      可迭代对象:
        python为了提供一种不依赖于索引的迭代方式,
        会为一些对象内置 __iter__ 方法,
        obj.__iter__称为可迭代的对象
          obj.__iter__() 得到的结果就是迭代器
          得到的迭代器,既有__iter__又有__next__方法
            __iter__:
            __next__: 返回下一个值
        好处:
          1.可以不依赖索引
          2.惰性计算,节省内存
        缺点:
          1.取值麻烦,需要一个一个取值
          2.不能往回取值
          3.不能获取迭代器的长度

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

    # 整理今天装饰器代码(每人手写一份,注意,是手写,交到小组长手里,明天我检查),准备明天默写
    def demeo(file_type = 'file'):
        def outer(func):
            def inner(*args, **kwargs):
                if file_type == 'file':
                    print('deal with 33[35;0mfile33[0m...')
                elif file_type == 'mysql':
                    print('deal with 33[35;0mmysql33[0m...')
                else:
                    print("deal with 33[35;0mothers33[0m...")
                res = func(*args, **kwargs)
                return res
            return inner
        return outer
    
    @demeo()
    def f1():
        print("my name is f1...")
    
    @demeo('mysql')
    def f2():
        print('f2 is my name...')
    
    @demeo('abc')
    def f3():
        print('is me, f3...')
    
    
    f1()
    f2()
    f3()
    # 2 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到文件中
    # 注意:时间格式的获取
    # import time
    # time.strftime('%Y-%m-%d %X')
    import time
    
    log_path = r'C:UsersAdministratorPycharmProjects老男孩全栈5期homeworkday08loglog.log'
    
    def outer(func):
        def inner(*args, **kwargs):
            with open(log_path, 'a', encoding='utf-8') as f:
                log_info = time.strftime('%Y-%m-%d %X ') + func.__name__ + ' run
    '
                f.write(log_info)
    
            res = func()
    
            return res
        return inner
    
    @outer
    def f1():
        print("This is f1.....")
    
    
    f1()
    # 3 判断下列数据类型是可迭代对象or迭代器
    #
    # s='hello'
    # l=[1,2,3,4]
    # t=(1,2,3)
    # d={'a':1}
    # set={1,2,3}
    # f=open('a.txt')
    #
    # 4 分别用依赖索引和不依赖索引两种方式迭代上述对象
    from collections import Iterable
    
    
    s='hello'
    l=[1,2,3,4]
    t=(1,2,3)
    d={'a':1}
    set={1,2,3}
    f=open('a.txt')
    
    def print_while(a):
        count = 0
        while count < len(a):
            print(a[count])
            count += 1
    def print_for(a):
        for i in a:
            if isinstance(a, dict):
                print(i,a[i])
            else:
                print(i)
    
    print('  s is Iterable: %s'%isinstance(s, Iterable))
    print_while(s)
    print_for(s)
    
    print('  l is Iterable: %s'%isinstance(l, Iterable))
    print_while(l)
    print_for(l)
    
    print('  t is Iterable: %s'%isinstance(t, Iterable))
    print_while(t)
    print_for(t)
    
    print('  d is Iterable: %s'%isinstance(d, Iterable))
    # print_while(d)
    print_for(d)
    
    print('set is Iterable: %s'%isinstance(set, Iterable))
    # print_while(set)
    print_for(set)
    
    print('  f is Iterable: %s'%isinstance(f, Iterable))
    # print_while(f)
    print_for(f)
    # 5 选做题:
    # 基于课上所讲网页缓存装饰器的基础上,实现缓存不同网页的功能
    # 要求,用户提交的不同url,都能缓存下来,对相同的url发起下载请求,优先从缓存里取内容
    import os, time, hashlib
    
    
    #
    # print(hash('abcdefg'))
    # print(hash('abcdefg'))
    
    
    cach_dir = "C:\Users\Administrator\PycharmProjects\老男孩全栈5期\homework\day08\cach\"      # 设置一个缓存的目录
    print(cach_dir)
    
    if not os.path.exists(cach_dir):          # 查看缓存目录是否存在,如果不存在,创建
        os.mkdir(cach_dir)
    
    
    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):
    
    
    
            url_name = args[0]                         # url_name,就是想要下载的网页的名字
            sha1 = hashlib.sha1()                         # 调用加密算法 sha1
            sha1.update(url_name.encode())                    # 将url 进行加密,得到结果,后期用来查看缓存是否存在
            sha1_name = sha1.hexdigest()                         # 将加密后的 url(字符串) ,赋值给 sha1_name
            file_name = cach_dir + sha1_name                   # 确定文件路径
    
            url_dict[args[0].split('.')[1]] = args[0]               #  将网页信息写入字典中,如果存在,则更新
    
            if os.path.exists(file_name) and os.path.getsize(file_name) > 0:        # 判断缓存文件是否存在,大小是否大于 0
                with open(file_name, 'rb') as f:          # 打开文件,并且用 rb 二进制的方式打开
                    print('缓存已经存在,正在读取。。。')
                    time.sleep(2)
                    return f.read()
    
            # 将新网址加入字典中
    
            # url_dict[args[0].split('.')[1]] = args[0]               #  将网页信息写入字典中,如果存在,则更新
    
    
            print('正在从网上下载。。。')
            time.sleep(2)
            res = func(*args, **kwargs)
    
            with open(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 = []                 # 这里我定义了一个列表,主要是把存放地址的字典的 key 放进去,因为字典是无须的,我想实现输入序号(下表)的方式选择地址,用列表的话,可以实现数字(下标)对应列表元素(字典的keys)
        for c, i in enumerate(url_dict): # 打印序号,并循环打印字典的keys
            choose_list.append(i)        # 分别将 每个 key 放入到列表中,这样的话,下面打印选项的时候,我就可以通过对应关系找到 用户所选择的网址是哪一个
            print(' %s  %s		%s'%(c+1, i, url_dict[i]))            # 将字典中的内容打出来,例如:  1   baidu    www.baidu.com
        choose = input('
    请输入序号或直接输入网址:http://www.baidu.com
    >>>').strip()   # 这里获取一个用户的选择
        if choose.upper() == "Q":                    # 如果选择是 'q' 或者 'Q', 那么退出
            break
        elif choose.isdigit() and 0 < int(choose) <= len(choose_list):   # 如果 choose 是数字,而且,数字的大小等于列表的长度(也就是说选择范围为打印菜单的序号)
    
    
            res = get(url_dict[choose_list[int(choose) - 1]])           # 那么,就把这个选择对应的网址传给函数   get(), 得到的返回值给 res
            print(res)
        elif 'http://' in choose:                               # 如果, choose 中包含 'http://' 这几个字符的话,我就认为,你输入了一个完整的网址
            res = get(choose)                      # 这个时候,我就将这个完整的网址传个  get()  函数,将返回值给 res
            print(res)
        else:                   # 如果都不满足,提示输入错误
            print('输入错误')
        time.sleep(2)
  • 相关阅读:
    某labs上传writeup-上传漏洞总结
    帮朋友写一个爬取地区信息的脚本
    python tab补全
    python中requests库中文乱码问题
    python中的Queue模块
    python中的ftplib模块
    ThinkSnS v4后台任意文件下载漏洞
    通过or注入py脚本
    bing查询旁站脚本
    Mysql的分页查询语句的性能分析
  • 原文地址:https://www.cnblogs.com/alwaysInMe/p/7019378.html
Copyright © 2020-2023  润新知