python中装饰器的应用

1.装饰器:
"在不改变原函数的基础上,给函数增加功能"
把一个函数当作参数,返回一个替代版的函数
本质上:返回函数的函数

# 装饰器的概念

- 装饰器的实现是函数里面嵌套函数;
- 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;
- 装饰器需要传递一个函数, 返回值也是一个函数对象.

# 装饰器的应用场景
- 计时器
- 记录日志
- 用户登录验证
- 函数参数验证

 

"""

如图所示,函数func1输出时运用函数outer进行了装饰

运用装饰器还可以解决一些函数问题,如图所示,当输入年龄为负数时他会输出负值
#但是人的年龄没有负的,此时则需要运用还书装饰一下,当输入为负数时,系统自动默认为0

 

def desc(fun):
    def add_info():
        print '中秋快乐'
        fun()

#输入的函数
        print '一起happy'
    return add_info
# 语法糖
@desc            # 输入的相当于是login = desc(login)
def login():
    print 'login....'
@desc            
def logout():
    print 'logout....'
@desc
def savemoney():
    print '奖金...'
@desc
def transferMoney():
    print '转账....'
login()
logout()
savemoney()
transferMoney()

显示结果为

 

 

 

import functools         #functools模块用于高阶函数:作用与或者返回其它函数的函数。一般来说,对于该模块,任何可调用对象都可以视为一个函数。  
import time                  #引入时间模块

def log(kind): #kind = 'debug'
    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] 函数名:%s,运行时间:%.5f,运行的返回值结果%d' \
                  %(kind,time.ctime(),fun.__name__,end_time-start_time,res)
            return res
        return wrapper
    return add_log

# log('debug') 返回值:add_log
# add = add_log(add)
@log('debug')
def add(x,y):
    time.sleep(1)

#延时一秒执行
    return x+y
print add(1,2)

 

练习1

# 编写装饰器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(*kides):
    def required(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            for i in args:
                if isinstance(i, kides):
                    pass
                else:
                    print '函数所有的次参数并非', kides
                    break
            else:
                res = fun(*args, **kwargs)
                return res

        return wrapper

    return required

@required_types(str,str)
def add(a, b):
    return a + b

print add('hello','python')

 

 

练习2

需求:验证用户登陆的装饰器is_login
    1.如果用户登陆成功,则执行被装饰的函数
    2.如果用户登陆不成功,则执行登陆函数

"""
import functools

login_users = ['admin', 'root']


def is_login(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        # 判断要写博客的这个用户是否登陆成功
        if kwargs.get('name') in login_users:
            res = fun(*args, **kwargs)
            return res
        else:
            res = login()
            return res
    return wrapper


@is_login
def writeBlog(name):
    return '编写博客'


def login():
    return '登陆。。。'

print writeBlog(name='admin')

 

练习3

 

编写装饰器required_ints, 条件如下:
#     1). 确保函数接收到的每一个参数都是整数;
#     2). 如果参数不是整形数, 打印 TypeError:参数必须为整形


import functools


def required_ints(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        for i in args:
            if isinstance(i,int):
                pass
            else:
                print '函数的所有参数并非整型'
                break
        else:
            res = fun(*args, **kwargs)
            return res

    return wrapper


@required_ints
def add(a, b):
    return a + b


@required_ints
def myMax(a, b, c, d):
    return max(a, b, c, d)


print myMax(1,2,3,4.0)

 

练习4

# 创建装饰器, 要求如下:
# 1. 创建add_log装饰器, 被装饰的函数打印日志信息;
# 2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx

"""
import functools
import time

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,运行时间:%.5f,运行的返回值结果%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
print add(1,2)

练习5

带有多个装饰器的函数

# 需求: 用户登陆验证的装饰器is_login
# #       1). 如果用户登陆成功, 则执行被装饰的函数;
# #       2). 如果用户登陆不成功, 则执行登陆函数

# #需求: 判断登陆用户是否未管理员is_admin(此处管理员只有一个为:admin用户)
# #      1).如果用户为管理员, 则执行被装饰的函数;
# #      2).如果用户不是管理员, 则报错;

"""
import functools

login_users = ['admin', 'root']

def is_admin(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        if kwargs.get('name') == 'admin':
            res = fun(*args,**kwargs)
            return res
        else:
            return 'Error:您没有权限访问该网站'
    return wrapper


def is_login(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        # 判断要写博客的这个用户是否登陆成功
        if kwargs.get('name') in login_users:
            res = fun(*args, **kwargs)
            return res
        else:
            res = login()
            return res
    return wrapper


@is_login
@is_admin
def writeBlog(name):
    return '编写博客'


def login():
    return '登陆。。。'

print(writeBlog(name='root'))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值