python中装饰器练习

练习一:装饰器实现一个函数计时器
“”"
“”"
1.问题1:被装饰的函数有返回值
2.问题2:如何保留被装饰函数的函数名和帮助信息文档
“”"

import time
import random
import string

li = [random.choice(string.ascii_letters) for i in range(10)]
print(li)

def Timer(fun):
def wrapper(*args,**kwargs):

        start_time = time.time()
        res = fun(*args,**kwargs)
        end_time = time.time()
        print('运行时间为: %.5f' %(end_time - start_time))
        return res
    return wrapper

@Timer
def con_add():
    s = ''
    for i in li:
        s += (i + ',')
    print(s)

@Timer
def join_add():
    print(','.join(li))

@Timer
def fun_list(n):

    return [i * 2 for i in range(n)]

@Timer
def fun_map(n):
    return list(map(lambda x:x*2,range(n)))

con_add()
join_add()

print(fun_list(10))
print(fun_map(10))

结果为:
['C', 'R', 'z', 'p', 'z', 'H', 'D', 'V', 'V', 'A']
C,R,z,p,z,H,D,V,V,A,
运行时间为: 0.00002
C,R,z,p,z,H,D,V,V,A
运行时间为: 0.00001
运行时间为: 0.00001
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
运行时间为: 0.00001
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

1.问题1:被装饰的函数有返回值

import time
import functools

def add_log(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = fun(*args,**kwargs)
        end_time = time.time()
        print('[%s] 函数名: %s, 运行时间: %6f,运行返回值结果: %d' %(time.ctime(),fun.__name__,end_time - start_time,res))
        return res
    return wrapper

@add_log
def add(x,y):
    time.sleep(1)
    return x + y

add(1,2)
结果为:
[Tue Apr  2 03:50:43 2019] 函数名: add, 运行时间: 1.001367,运行返回值结果: 3

2.问题2:如何保留被装饰函数的函数名和帮助信息文档
(1)导入 functools包,加入 @functools.wraps(fun)
(2)print(xxx.doc) ##帮助信息文档
print(xxx.name) ##函数名

import time
import random
import string
import functools

li = [random.choice(string.ascii_letters) for i in range(100)]
print(li)

def Timer(fun):
    """这是一个装饰器Timer"""
     @functools.wraps(fun)      ##函数帮助文档
    def wrapper(*args,**kwargs):
        """这是一个wrapper函数"""
        start_time = time.time()
        res = fun(*args,**kwargs)
        end_time = time.time()
        print('运行时间为: %.5f' %(end_time - start_time))
        return res
    return wrapper

@Timer
def con_add():
    s = ''
    for i in li:
        s += (i + ',')
    print(s)

@Timer
def join_add():
    print(','.join(li))

@Timer
def fun_list(n):
    """这是fun_list函数"""
    return [i * 2 for i in range(n)]

@Timer
def fun_map(n):
    return list(map(lambda x:x*2,range(n)))


print(fun_list.__doc__)
print(fun_list.__name__)

print(time.ctime())
['Z', 'v', 'k', 'L', 'V', 'S', 'G', 'k', 'H', 'P']
这是一个wrapper函数
wrapper
Tue Apr  2 03:49:34 2019

练习二:inspect.getcallargs

import functools
import inspect

def is_admin(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        #inspect.getcallargs返回一个字典,key值是形参,value值
        #是对应的实参{'name':'root'}
        inspect_res = inspect.getcallargs(fun,*args,*kwargs)
        print('inspect的返回值: %s' %inspect_res)
        if inspect_res.get('name') == 'root':
            res = fun(*args,**kwargs)
            return res
        else:
            print('not root user!')
    return wrapper

@is_admin
def add_user(name):
    print('添加用户信息...')


def del_user(name):
    print('删除用户信息...')

add_user('root')

结果为:
inspect的返回值: {'name': 'root'}
添加用户信息...

练习三: 编写装饰器required_types, 条件如下:
1). 当装饰器为@required_types(int,float)确保函数接收到的
每一个参数都是int或者float类型;
2). 当装饰器为@required_types(list)确保函数接收到的每一>个参数都是list类型;
3). 当装饰器为@required_types(str,int)确保函数接收到的每
一个参数都是str或者int类型;
4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类

import functools


def required_types(*kinds):
    def required_ints(fun):
        @functools.wraps(fun)
        def wrapper(*args,**kwargs):
            for i in args:
                if not isinstance(i,kinds):
                    print('TypeError:参数为',kinds)
                    break
            else:
                res = fun(*args,**kwargs)
                return res
        return wrapper
    return required_ints

@required_types(float,float)
def add (a,b):
    return a + b
print (add(1.1,1.9))

结果为:3

猜你喜欢

转载自blog.csdn.net/qq_44236589/article/details/88949914
今日推荐