装饰器,迭代器,生成器-练习

1. 编写有参装饰器基本模板

from functools import wraps

def auth(driver):
    def deco(func):
        @wraps
        def wrapper(*args, **kwargs):
            if driver == 'file':
                print("基于文件认证")
            elif driver == 'mysql':
                print("基于mysql认证")
            elif driver == 'ldap':
                print('基于ldap认证')
            else:
                print("不支持该driver认证")
                return
            res = func(*args, **kwargs)
            return res
        return wrapper
    return deco

@auth(driver='file')  # @deco  # wrapper = deco(index)  # index = wrapper
def index():
    print("from index")

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

  • 方式一:定义的功能字典表达形式如下:
dic = {'序号':  ('函数对应的功能信息', 函数名的内存地址)}
func_dic = {}
def add_to_dic(function_name):
    def deco(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if not func_dic:
                func_dic['0'] = (function_name, func)

            # else:
            #     max_num = 0
            #     for key in func_dic:
            #         key = int(key)
            #         if key > max_num:
            #             max_num = key
            #     func_dic[str(max_num + 1)] = (function_name, func)

            # 优化: 使用max + lambda
            else:
                max_num = max(func_dic, key=lambda k: int(k))
                func_dic[str(int(max_num) + 1)] = (function_name, func)

            res = func(*args, **kwargs)
            return res
        return wrapper
    return deco

@add_to_dic(function_name='查询余额')
def check_balance():
    print("from check_balance")

@add_to_dic(function_name='充值')
def recharge():
    print("from recharge")

@add_to_dic(function_name='提现')
def withdraw():
    print("from withdraw")

@add_to_dic(function_name='转账')
def transfer():
    print("from transfer")

def run():
    check_balance()
    recharge()
    withdraw()
    transfer()

run()
print(func_dic)
'''
{
    '0': ('查询余额', <function check_balance at 0x000002A68C97E9D0>), 
    '1': ('充值', <function recharge at 0x000002A68C97EAF0>), 
    '2': ('提现', <function withdraw at 0x000002A68C97EC10>), 
    '3': ('转账', <function transfer at 0x000002A68C97ED30>)
}
'''
  • 方式二: 定义有参装饰器 + 功能函数的表现形式
dic = {'序号': 函数名对应的内存地址}
func_dic = {}
def add_to_dic(number:str):
    def deco(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            func_dic[number] = func

            res = func(*args, **kwargs)
            return res
        return wrapper
    return deco

@add_to_dic('0')
def check_balance():
    print("from check_balance")

@add_to_dic('1')
def recharge():
    print("from recharge")

@add_to_dic('2')
def withdraw():
    print("from withdraw")

@add_to_dic('3')
def transfer():
    print("from transfer")

def run():
    check_balance()
    recharge()
    withdraw()
    transfer()

run()
print(func_dic)
'''
{
    '0': <function check_balance at 0x000001F2438AE9D0>, 
    '1': <function recharge at 0x000001F2438AEAF0>, 
    '2': <function withdraw at 0x000001F2438AEC10>, 
    '3': <function transfer at 0x000001F2438AED30>
}
'''

3. 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定(订正)

'''
import time

def log_record(func, log_path=r'access.log'):
    """记录日志"""
    with open(log_path, 'at', encoding='utf-8') as f:
        f.write(f"{time.strftime('%Y-%m-%d %X')} is run function: {func.__name__}\n")

def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        log_record(func)  # 在被装饰函数func执行完毕以后, 往日志文件中追加一行内容的新功能
        return res
    return wrapper
'''
# 订正: 要在被装饰对象执行之前就记录日志时间. 因为函数的执行过程可能很长, 函数执行完毕以后, 不能确定函数开始运行的时间
import time

def log_record(func, log_path=r'access.log'):
    """记录日志"""
    with open(log_path, 'at', encoding='utf-8') as f:
        f.write(f"{time.strftime('%Y-%m-%d %X')} is run function: {func.__name__}\n")

def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        log_record(func)  # 在被装饰函数func执行之前.
        res = func(*args, **kwargs)
        return res
    return wrapper

4. 基于迭代器的方式,用while循环迭代取值字符串、列表、元组、字典、集合、文件对象(订正)

"""
# 列表
li = [1, 2, 3]
li_iterator = li.__iter__()
while True:
    try:
        print(li_iterator.__next__())
    except StopIteration:  # 通过捕捉迭代器取值完毕时出现的异常来控制while循环遍历取值结束的条件: StopIteration
        break
'''
1
2
3
'''

# 元组
t = (1, 2, 3)
t_iterator = t.__iter__()
while True:
    try:
        print(t_iterator.__next__())
    except StopIteration:
        break
'''
1
2
3
'''

# 字典
dic = {'name': 'egon', 'age': 18, 'sex': 0}
dic_iterator = dic.__iter__()
while True:
    try:
        print(dic_iterator.__next__())
    except StopIteration:
        break
'''
# 字典默认迭代取值的是key
name
age
sex
'''


# 集合
set1 = {'name', 'age', 'sex'}
set1_iterator = set1.__iter__()
while True:
    try:
        print(set1_iterator.__next__())
    except StopIteration:
        break
'''
name
age
sex
'''


# 文件对象
with open("a.txt", 'w+', encoding='utf-8') as f:
    f.write("1\n2\n3\n")
    f.seek(0)  # t模式: seek的第二个参数不指定, 模式就是0模式
    while True:
        try:
            print(f.__next__(), end='')
        except StopIteration:
            break
'''
1
2
3
'''
"""
# 订正: 定义一个函数,解决代码的冗余性
def my_iterator(obj):
    obj_iterator = obj.__iter__()
    while True:
        try:
            print(next(obj_iterator), end=' ')
        except StopIteration:
            break
# my_iterator([1, 2, 3])  # 1 2 3 1 3 5 7 9

5. 自定义迭代器实现range功能

def my_range(start, stop, step=1):  # 步长默认为1: step=1
    while start < stop:
        yield start
        start += step

res = my_range(1, 10, 2)
for i in res:
    print(i, end=' ')
posted @ 2020-03-24 22:00  给你加马桶唱疏通  阅读(123)  评论(0编辑  收藏  举报