楔子

前提,我有一段代码(一个函数)。

import time
def run_time():
time.sleep(0.1)
print('我曾踏足山巅')

需求1:现在,我想计算这段代码的运行时间。

我可以这样做:

import time
def run_time():
start_time = time.time()
time.sleep(0.1)
print('我曾踏足山巅')
end_time = time.time()
run_t = end_time - start_time
print('运行时间为:',run_t)
run_time()

此时,需求是可以实现的。

需求2:不想如此麻烦

如果有很多个类似的函数需要计算运行时间,那这种方法就会显得特别繁琐。

我们可以不修改源代码,再定义一个计算时间的函数,将需要被计算时间的函数名作为参数传进去,

直接调用函数进行计算运行时间,就不需要每个函数里面都加入相同代码了。

下面进行升级:

import time
def run_time():
time.sleep(0.1)
print('我曾踏足山巅')
def run_time1():
time.sleep(1)
print('也曾堕入低谷')
def calculation(f):
start_time = time.time()
f()
end_time = time.time()
run_t = end_time - start_time
print('运行时间为:', run_t)
#直接调用函数进行计算
calculation(run_time)
calculation(run_time1)

需求3:我还想要不修改调用方式直接实现时间的计算。

即还是直接调用原函数,但是能同时实现原功能以及时间计算的功能。

由此,我们引入装饰器函数的概念。

python装饰器

装饰器的定义

python装饰器就是用来拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数。

使用python的好处就是不用更改原函数代码的前提下给函数增加新的功能。

装饰器的特点

不修改被装饰函数的调用方式,不修改被装饰函数的源代码。

实例:实现

备注:语法糖

import time
def run_time(f): #装饰器函数
def inner():
start_time = time.time()
f()
end_time = time.time()
run_t = end_time - start_time
print('运行时间为:', run_t)
return inner
# func = run_time(func)#不修改函数调用方式,添加新功能
@run_time#语法糖,代替赋值调用,等价于上一行代码
def func():
time.sleep(0.1)
print('hello world')
func()

可以看出,在不改变原函数调用方式的情况下,也实现了运行时间的计算。

原函数的源码没有改变,调用方式没有改变,并且追加了新的运行时间计算功能。

装饰器的返回值

如果被装饰的参数有返回值。

import time
#装饰器必定要是一个闭包函数
def run_time(f):
def inner():
start = time.time()
func_retrun = f() # func_return = func() 变量接收被装饰函数的返回值
end = time.time()
print('被装饰函数运行时间为:',end - start)
return func_retrun
return inner
@run_time
#被装饰函数
def func():
time.sleep(0.1)
print('hello world')
return '这是被装饰函数返回值'
# func = run_time(func) #结果:func = inner
s = func()
print(s)

装饰器的参数

一、位置参数

#带有参数的函数装饰器
def wrapper(f):
def inner(a):
print('装饰器增加的额外内容:hello world')
return f(a)#返回被装饰函数的返回值
# f(a)
return inner
@wrapper
def func(a):
print('被装饰函数的参数输入:',a)
return '被装饰函数的返回值:was a day'
s = func('once before,a little ...')
print(s)

二、默认参数

#此装饰器 wrapper 实现增加时间戳功能
import time
def wrapper(f):
def inner(a,b,c = 'default'):#在这里加默认参数,还有动态参数亦如是
print(time.asctime())
r = f(a,b,c)
return r
return inner
@wrapper
def func(a,b,c ):
print(a,b,c)
return '被修饰函数返回值'
s = func(1,2)
print(s)

三、动态参数

注:其实下例中的被装饰函数并没有用到参数。不过你可以根据需求自己来进行试验,不再赘述。

# 此装饰器 wrapper 实现增加时间戳功能
import time
def wrapper(f):
def inner(*args,**kwargs):
print(time.asctime())
r = f(*args,**kwargs)
return r
return inner
@wrapper
def func2():
print(''' 三更灯火五更鸡,
正是男儿读书时。
黑发不知勤学早,
白首方恨读书迟。''')
r1 = '''这首诗深入浅出,自然流畅,富含哲理。核心是“黑发早勤学,白首读书迟”。
从学习的时间这一角度立意,劝勉年轻人不要虚度光阴,要及早努力学习,免得将来后悔。'''
return r1
s = func2()
print(s)

装饰器的功能和固定结构

装饰器的主要功能

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

装饰器的固定结构

def wrapper(f):#装饰器函数,f是被装饰函数
def inner(*args,**kwargs):
'''执行函数之前要做的'''
r = f(*args,**kwargs)
'''执行函数之后要做的'''
return r#解释器原则,从上至下,返回值最后才进行输出
return inner
@wrapper #之后要使用装饰器函数的时候,直接调用就可以了

pass

python学习日记(函数--装饰器)的更多相关文章

  1. Python学习日记(九) 装饰器函数

    1.import time a.time.time() 获取到当前的时间,返回值为浮点型 import time print(time.time()) #1565422783.6497557 b.ti ...

  2. python学习日记(装饰器的补充)

    如何返回被装饰函数的函数名及注释? 问题及实现 先看典型的装饰器: def wrapper(f):#装饰器函数,f是被装饰函数 def inner(*args,**kwargs): '''执行函数之前 ...

  3. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  4. python 修改的函数装饰器

    把好的代码记录下来 方便以后学习 修改的函数参数装饰器 from functools import wraps import time import logging def warn(timeout) ...

  5. Python学习笔记012——装饰器

    1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...

  6. python学习笔记:装饰器2

    python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...

  7. python二 总结--函数-- 装饰器

    装饰器是什么? 有什么用? 为什么要用? 真的有用吗? 1.装饰器: 装饰器: 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能. 原则:1.不能修改被装饰的函数的源代码          ...

  8. Python中的@函数装饰器到底是什么?

    在解释@函数装饰器之前,先说一下,类中的类方法和静态方法. 在Python中完全支持定义类方法.静态方法.这两种方法很相似,Python它们都使用类来调用(ps:用对象调用也可以). 区别在于:Pyt ...

  9. python语法基础-函数-装饰器-长期维护

    ######################################################### # 装饰器 # 装饰器非常重要,面试Python的公司必问, # 原则:开放封闭原则 ...

  10. python 进阶篇 函数装饰器和类装饰器

    函数装饰器 简单装饰器 def my_decorator(func): def wrapper(): print('wrapper of decorator') func() return wrapp ...

随机推荐

  1. c++入门之再次探讨类属性

    精辟博文:https://blog.csdn.net/msdnwolaile/article/details/51923859(转载,仅供学习|!)

  2. JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数

    jvm调优主要针对堆内存,堆内存分为:新生区.养老区和永久区 永久区存放的是系统jdk自身的interface和class的元数据,所以唯有新生区和养老区具有优化空间. 新生区:伊甸区和幸存者区.所有 ...

  3. PHP开发web应用安全总结

    XSS跨站脚本 概念:恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的. 危害: 盗取用户COOKIE信息. 跳转 ...

  4. 【问题解决方案】Git bash进入多层子目录问题(通配符问题留坑)

    cd进入指定路径下:cd 斜杠 斜杠 方法一: 1- 撇丿,不是"那",盘符前面要加上 / (d盘前面也加,不加也行) 2- 路径名不区分大小写 3- 不用空格 4- 如果目录名中 ...

  5. js-跨域源资源共享(CORS)

    ### 一. CORS(Cross-Origin Resource Sharing,跨域源资源共享) 基本思想:使用自定义HTTP头部让浏览器与服务器进行沟通 发送请求时,需附加一个Origin头部 ...

  6. java 代理模式(静态代理、动态代理、Cglib代理) 转载

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

  7. [转帖]IP /TCP协议及握手过程和数据包格式中级详解

    IP /TCP协议及握手过程和数据包格式中级详解 https://www.toutiao.com/a6665292902458982926/ 写的挺好的 其实 一直没闹明白 网络好 广播地址 还有 网 ...

  8. Laravel设置软删除及其恢复系列操作

    软删除及其相关实现 在模型类中要使用SoftDeletestrait并设置$date属性数组 <?php namespace App\Models; use Illuminate\Databas ...

  9. java随笔2 变量类定义

    如果要定义变量为对象,就要创建此对象对应的java类, 且定义的类型为类名,且都为private

  10. CSS硬件加速的好与坏

    本文翻译自Ariya Hidayat的Hardware Accelerated CSS: The Nice vs The Naughty.感谢Kyle He帮助校对. 每个人都痴迷于60桢每秒的顺滑动 ...