python之装饰器函数

本章内容

引入

作为一个会写函数的python开发,我们从今天开始要去公司上班了。写了一个函数,就交给其他开发用了。

def func1():
    print(‘in func1‘)

季度末,公司的领导要给大家发绩效奖金了,就提议对这段日子所有人开发的成果进行审核,审核的标准是什么呢?就是统计每个函数的执行时间。

这个时候你要怎么做呀?

你一想,这好办,把函数一改:

import time
def func1():
    start = time.time()
    print(‘in func1‘)
    print(time.time() - start)

func1()

来公司半年,写了2000+函数,挨个改一遍,1个礼拜过去了,等领导审核完,再挨个给删了。。。又1个礼拜过去了。。。这是不是很闹心?

你觉得不行,不能让自己费劲儿,告诉所有开发,现在你们都在自己原本的代码上加上一句计算时间的语句?

import time
def func1():
    print(‘in func1‘)

start = time.time()
func1()
print(time.time() - start)

还是不行,因为这样对于开发同事来讲实在是太麻烦了。

那怎么办呢?你灵机一动,写了一个timer函数。。。

import time
def timer(func):
    start = time.time()
    func()
    print(time.time() - start)

def func1():
    print(‘in func1‘)

def func2():
    print(‘in func2‘)

timer(func1)
timer(func2)

这样看起来是不是简单多啦?不管我们写了多少个函数都可以调用这个计时函数来计算函数的执行时间了。。。尽管现在修改成本已经变得很小很小了,但是对于同事来说还是改变了这个函数的调用方式,假如某同事因为相信你,在他的代码里用你的方法用了2w多次,那他修改完代码你们友谊的小船也就彻底地翻了。

你要做的就是,让你的同事依然调用func1,但是能实现调用timer方法的效果。

import time
def timer(func):
    start = time.time()
    func()
    print(time.time() - start)

def func1():
    print(‘in func1‘)

func1 =timer  #要是能这样的就完美了。。。可惜报错
func1()

非常可惜,上面这段代码是会报错的,因为timer方法需要传递一个func参数,我们不能在赋值的时候传参,因为只要执行func1 = timer(func1),timer方法就直接执行了,下面的那句func1根本就没有意义。到这里,我们的思路好像陷入了僵局。。。

装饰器的形成过程

import time

def func1():
    print(‘in func1‘)

def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

func1 = timer(func1)
func1()

装饰器——简单版1

忙活了这么半天,终于初具规模了!现在已经基本上完美了,唯一碍眼的那句话就是还要在做一次赋值调用。。。

你觉得碍眼,python的开发者也觉得碍眼,所以就为我们提供了一句语法糖来解决这个问题!

import time
def timer(func):
    def inner():
        start = time.time()
        func()
        print(time.time() - start)
    return inner

@timer   #==> func1 = timer(func1)
def func1():
    print(‘in func1‘)

func1()

装饰器——语法糖

到这里,我们可以简单的总结一下:

  装饰器的本质:一个闭包函数

  装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

还有最后一个问题要解决,刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?

def timer(func):
    def inner(a):
        start = time.time()
        func(a)
        print(time.time() - start)
    return inner

@timer
def func1(a):
    print(a)

func1(1)

装饰器——带参数的装饰器

其实装饰带参的函数并不是什么难事,但假如你有两个函数,需要传递的参数不一样呢?

import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func1 = timer(func1)
def func1(a,b):
    print(‘in func1‘)

@timer   #==> func2 = timer(func2)
def func2(a):
    print(‘in func2 and get a:%s‘%(a))
    return ‘fun2 over‘

func1(‘aaaaaa‘,‘bbbbbb‘)
print(func2(‘aaaaaa‘))

装饰器——成功hold住所有函数传参

现在参数的问题已经完美的解决了,可是如果你的函数是有返回值的呢?

import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner

@timer   #==> func2 = timer(func2)
def func2(a):
    print(‘in func2 and get a:%s‘%(a))
    return ‘fun2 over‘

func2(‘aaaaaa‘)
print(func2(‘aaaaaa‘))

装饰器——带返回值的装饰器

刚刚那个装饰器已经非常完美了,但是正常我们情况下查看函数的一些信息的方法在此处都会失效

def index():
    ‘‘‘这是一个主页信息‘‘‘
    print(‘from index‘)

print(index.__doc__)    #查看函数注释的方法
print(index.__name__)   #查看函数名的方法

查看函数信息的一些方法

为了不让他们失效,我们还要在装饰器上加上一点来完善它:

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    ‘‘‘哈哈哈哈‘‘‘
    print(‘from index‘)

print(index.__doc__)
print(index.__name__)

装饰器——wraps demo

开放封闭原则

  1.对扩展是开放的

    为什么要对扩展开放呢?

    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

  2.对修改是封闭的

    为什么要对修改封闭呢?

    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

装饰器完美的遵循了这个开放封闭原则。

装饰器的主要功能和装饰器的固定结构

装饰器的主要功能:

在不改变函数调用方式的基础上在函数的前、后添加功能。

装饰器的固定格式:

def timer(func):
    def inner(*args,**kwargs):
        ‘‘‘执行函数之前要做的‘‘‘
        re = func(*args,**kwargs)
        ‘‘‘执行函数之后要做的‘‘‘
        return re
    return inner

装饰器的固定格式

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

装饰器的固定格式——wraps版

带参数的装饰器

假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

一个一个的取消掉? 没日没夜忙活3天。。。

过两天你领导想通了,再让你加上。。。

def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print(‘‘‘执行函数之前要做的‘‘‘)
            re = func(*args,**kwargs)
            if flag:
                print(‘‘‘执行函数之后要做的‘‘‘)
            return re
        return inner
    return timer

@outer(False)
def func():
    print(111)

func()

带参数的装饰器

原文地址:https://www.cnblogs.com/hxf175336/p/9241155.html

时间: 2024-08-30 15:30:50

python之装饰器函数的相关文章

python学习——装饰器函数

一.装饰器函数的作用是什么 答:装饰器函数是在不修改原函数及其调用方式的情况下对原函数功能进行扩展 对于搞python开发的人来说,函数占据了至关重要的地位.都说学好函数你就可以去找工作了,好了,假如你已经在某个公司上班了,想到马上就要过年了,那过年就意味着你可以向老板要年终奖金了,那凭什么老板要给你年终奖呢,你又能得到多少年终奖金呢.老板是这样说的,你给我至少写1000行代码,我来看一下你代码的执行时间,根据你的执行时间来评你的年终奖.好了,你知道既然要计算时间,学过函数的你就来实现一个计算函

【Python】装饰器实现日志记录

好的日志对一个软件的重要性是显而易见的.如果函数的入口都要写一行代码来记录日志,这种方式实在是太低效了,但一直没有找到更好的方法.后来用python写一些软件,了解到python的装饰器功能时,突然人品爆发,结合装饰器来记录日志那是绝对的简单有效! 下面简单演示一下用装饰器来协助记录Log,示例代码如下: [python] view plain copy print? #!/usr/bin/env python def trace_func(func): ''''' A decorate fun

如何用python的装饰器定义一个像C++一样的强类型函数

Python作为一个动态的脚本语言,其函数在定义时是不需要指出参数的类型,也不需要指出函数是否有返回值.本文将介绍如何使用python的装饰器来定义一个像C++那样的强类型函数.接下去,先介绍python3中关于函数的定义. 0. python3中的函数定义 举个例子来说吧,比如如下的函数定义: 1 def fun(a:int, b=1, *c, d, e=2, **f) -> str: 2 pass 这里主要是说几点与python2中不同的点. 1)分号后面表示参数的annotation,这个

python 之装饰器(用装饰器给现有函数增加新功能)

#!/usr/bin/env python # -*- coding: utf-8 -*- """ Created on Mon Nov 14 01:01:29 2016 @author: toby """ #知识点:装饰器 ''' #一.小粒子: #要求1.假如产品经历要求在每个函数之上执行之前都添加一个验证的功能,当然这里只是模拟而已,别当真哈! #已写好的现有函数如下,有1000个函数 def func1():     print 'fun

python全栈开发从入门到放弃之装饰器函数

1.函数名可以当作函数的参数 1 import time 2 def timmer(func): 3 #函数名可以当做函数的参数 4 def inner(): 5 start = time.time() 6 func() 7 end = time.time() 8 print(end - start) 9 return inner 10 11 def hahaha(): 12 time.sleep(0.1) 13 print('aaaa') 14 15 hahaha() 16 17 输出结果 1

Python装饰器函数

装饰器函数 这里定义了一个func函数,打印'我是func函数' def func(): print('我是func函数'); time.sleep(1); 假设,想要在func()函数的基础之上新增的一个功能,计算func函数执行所用的时间 import time;#时间模块,处理时间操作 #开闭原则,对扩展开放,对修改封闭 def func(): print('我是func函数'); time.sleep(1);#休眠一秒 #tools方法就是func方法的装饰器 def tool(): d

python的装饰器

装饰器 函数即对象 在python的里,函数和我们之前的[1,2,3],'abc',8等一样都是对象,而且函数是最高级的对象(对象是类的实例化,可以调用相应的方法,函数是包含变量对象的对象). 1 def foo(): 2 print('i am the foo') 3 bar() 4 5 def bar(): 6 print('i am the bar') 7 8 foo() 9 # def bar(): #报错 10 # print('i am the bar') 带着这个问题,我们聊一聊函

Python之装饰器、迭代器和生成器

在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思来谁就是对特定的建筑物内按照一定的思路和风格进行美化的一种行为,所谓“器”就是工具,对于python来说装饰器就是能够在不修改原始的代码情况下给其添加新的功能,比如一款软件上线之后,我们需要在不修改源代码和不修改被调用的方式的情况下还能为期添加新的功能,在python种就可以用装饰器来实现,同样在写

Python decorator装饰器

问题: 定义了一个新函数 想在运行时动态增加功能 又不想改动函数本身的代码 通过高阶段函数返回一个新函数 def f1(x): return x*2 def new_fn(f): #装饰器函数 def fn(x): print ('call ' + f.__name__ + '()') return f(x) return fn #方法1 g1 = new_fn(f1) print (g1(5)) #方法2 f1 = new_fn(f1) #f1的原始定义函数彻底被隐藏了 print (f1(5