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)
原文地址:https://www.cnblogs.com/alwaysInMe/p/7019378.html