python装饰器

装饰器:python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能

def say(age):
     print 'man is %d years old' % age

def outer(func):
    def inner(age):  #注意:当原函数有参数,装饰器的作用是为了操作原函数中的参数,所以给inner设置参数
        if age < 0:
            age = 0
        func(age)
    return inner

# "化妆过的函数"
say = outer(say)
# 其实是调用的新的函数
say(-10)

语法糖使用@标识符将装饰器直接应用与函数

格式:@装饰器的名字(外部函数的函数名)

注意:使用@之后,装饰器必须先被定义,然后再使用原函数,此时原函数也相当于被增加新功能

@desc这一句则是python中的一个语法糖,它告诉我们这里使用了装饰器,用desc函数来装饰login(),在不改变源代码的情况下,增加了两条print语句

def desc(fun):
    def add_info():
        print '欢迎光临'
        fun()
        print '欢迎下次光临'
    return add_info

#语法糖
@desc
def login():
    print 'login....'
login()

带有不定长参数的装饰器(应用更广泛)

上面的例子是最简单的装饰器,但是有一个问题,如果被装饰的函数需要传入参数,那么这个装饰器就坏了。因为返回的函数并不能接受参数。Python提供了可变参数*args和关键字参数**kwargs,有了这两个参数,装饰器就可以用于任意目标函数了。

装饰器的需求:获取每个函数的执行时间
    1).函数执行之前计算时间
    2).函数执行之后计算时间

通过此例子,我们也可发现python内置函数的运行效率远大于使用一些循环来的快

import time
import string
import random

li= [random.choice(string.ascii_letters) for i in range(100)]
def timeit(fun):
    def wrapper(*arges,**kwargs):  # 接收可变参数和关键字参数
        start_time=time.time()
        fun(*arges,**kwargs)
        end_time=time.time()
        print '运行时间为:%.6f' % (end_time - start_time)
    return wrapper
@timeit
def con_add():
    s=''
    for i in li:
        s+=(i+',')
    print s
@timeit
def join_add():
    print ','.join(li)
@timeit
def fun_list(n):
    print [2*i for i in range(n)]
@timeit
def fun_map(n):
    print list(map(lambda x:x*2,range(n)))
con_add()
join_add()
fun_list(50)
fun_map(50)

通过上面的例子会出现以下问题1:被装饰的函数有返回值的时候怎么办
                                                问题2:如何保留被装饰函数的函数名和帮助文档信息

问题1解决方法:

def timeit(fun):
    """这是一个装饰器材timeit"""
    #@functools.wraps(fun)
    def wrapper(*arges, **kwargs):  # 接收可变参数和关键字参数
        """这是一个wrpper函数"""
        # args:元组 kwargs:字典
        # 函数执行之前
        start_time = time.time()
        # 执行函数
        res = fun(*arges, **kwargs) #fun_list(50000)
        # 函数执行之后
        end_time = time.time()
        print '运行时间为:%.6f' % (end_time - start_time)
        return res
    return wrapper

问题2解决方法:import functools

import time
import functools

def timeit(fun):
    """这是一个装饰器材timeit"""
    @functools.wraps(fun)
    def wrapper(*arges, **kwargs):  # 接收可变参数和关键字参数
        """这是一个wrpper函数"""
        start_time = time.time()
        res = fun(*arges, **kwargs) #fun_list(50000)
        end_time = time.time()
        print '运行时间为:%.6f' % (end_time - start_time)
        return res
    return wrapper

@timeit
def fun_map(n):
    """这是fun_map函数"""
    return list(map(lambda x:x*2,range(n)))
print fun_map.__name__
print fun_map.__doc__

不加时,不会显示fun_map函数的名字和文档描述,默认显示的是wrapper函数的名字和文档描述

带有参数的装饰器:

import 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)

 带有多个装饰器的函数

需求: 用户登陆验证的装饰器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'))

装饰器练习

1.创建装饰器,要求如下:

 1).创建add_log装饰器,被装饰的函数打印日志信息

 2).日志的格式为:[字符串时间] 函数名:xxx,运行时间:xxx,返回值结果:xxx

def add_log(fun):
    @functools.wraps(fun)
    def inner(*args,**kwargs):
        start_time1 = time.time()
        res = fun(*args, **kwargs)
        end_time1= time.time()
        print '[%s] 函数名:%s,运行时间:%d,返回值结果:%d'%(time.ctime(),fun.__name__,end_time1-start_time1,res)
        return res
    return inner
@add_log
def add(x,y):
    time.sleep(1)
    return x+y
print add(2,3)

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

@required_ints
def add(a,b):
    return a+b
print add(2,3)
print add(2,3.5)

def required_types(*kind):
    def require(fun):
        @functools.wraps(fun)
        def wrapper(*args,**kwargs):
            for i in args:
                if isinstance(i,kind):
                    pass
                else:
                    print '函数所有的参数并非',kind
                    break

            else:
                res=fun(*args,**kwargs)
                return res

        return wrapper
    return require
@required_types(int,float)
def add(a,b):
    return a+b
print add('hello','world')
print add(2,3)

@required_types(list)
def add(a,b):
    return a+b
print add([1,2,3],[5,7,6])
print add(2,3)

python isinstance函数:

      判断元素是否是字符串、int型、float型

print isinstance(2.3,float) #判断是否为float型
print isinstance(123,int)   #判断是否为int型
print isinstance('abc',str)  #判断是否为string型
print isinstance(1.2,(int,str))  #判断是否为int或str型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值