# 装饰器 - @ - 拿到内层函数的引用 - 直接使用内层函数

# 增强加法函数,输出被调用过及调用的参数

def add(x, y):

print("call fun {}, {}+{}".format(add.__name__, x, y)) # 输出到控制台

return x + y

print(add(4, 5))

def add(x, y, file=None):

print("call fun {}, {}+{}".format(add.__name__, x, y), file = file) # 输出到文件

return x + y

print(add(4, 5))

# print 耦合太高

# print 不属于加法业务

# print 叫侵入式代码

# 1 嵌套方式,避免侵入式代码

print('------------------------')

def add(x, y):

return x + y

def logger(fn):

print('begin')

x = fn(4, 5)

print('end')

return x

print(logger(add))

# 2

def add1(x, y):

return x + y

def add2(x, y, z):

return x + y + z

def add3(x, y, *args, z, **kwargs):

return x + y + z

def logger(fn, *args, **kwargs): # 位置参数*args元组, 关键字参数**kwargs字典

print('begin')

x = fn(*args, **kwargs)

print('end')

return x

print(logger(add1, 4, 5))

print(logger(add2, 4, 5, 6))

print(logger(add3, 4, z=5, y=6))

# 3 柯里化

def add1(x, y):

return x + y

def add2(x, y, z):

return x + y + z

def add3(x, y, *args, z, **kwargs):

return x + y + z

def logger(fn):

def _logger(*args, **kwargs):

print('begin')

x = fn(*args, **kwargs)

print('end')

return x

return _logger

foo = logger(add1)

print(foo(10, 10))

print(logger(add1)(10, 100))

add1 = logger(add1)

print(add1(10, 1000))

# 装饰器 @ ***

def logger(fn):

def _logger(*args, **kwargs):

print('begin')

x = fn(*args, **kwargs)

print('end')

return x

return _logger # 返回内层函数的引用**

@logger # 等价于add1 = logger(add1)

def add1(x, y):

return x + y

print(add1(10, 10000))

# 装饰器

# 无参装饰器

# 它是一个函数

# 有一个函数作为它的形参

# 返回值也是一个函数

# 可以使用@functionname方式,简化调用

# 装饰器是高阶函数,即传入函数,又返回函数

import datetime

import time

def logger(fn):

def wrap(*args, **kwargs):

# before 功能增强

print('args={}, kwargs={}'.format(args, kwargs))

start = datetime.datetime.now()

result = fn(*args, **kwargs)

# after 功能增强

duration = datetime.datetime.now() - start

print('function {} took {}s.'.format(fn.__name__, duration.total_seconds()))

return result

return wrap # 返回内层函数的引用**

@logger # 等价于 add = logger(add)

def add(x, y):

print('call add')

time.sleep(2)

return x + y

print(add(10, 10000))

# 装饰器理解 - 避免侵入式

# 装饰器函数 > 前置功能增强 > 被增强函数 > 后置功能增强

# 装饰器函数可以随意更换

# 文档字符串

# 在函数语句块的第一行,且吸管式多行文本,使用三引号

# 惯例是首字母大写,第一行写概述,空一行,第三行写详细描述

# 可以使用特殊属性__doc__访问这个文档

def add(x, y):

"""

This is a function

:param x:

:param y:

:return:

"""

result = x + y

return result

print(add(10, 10))

print(add.__name__, add.__doc__, sep='\n')

print('----------------------------------')

# 文档字符串和装饰器

# 解决被装函数的文档字符串无法显示问题

import datetime

import time

def copyProperties(src, dest): # 包装函数和被包装函数字符文档统一

dest.__name__ = src.__name__

dest.__doc__ = src.__doc__

def logger(fn):

def wrap(*args, **kwargs):

"""

This is wrapper

"""

# before 功能增强

print('args={}, kwargs={}'.format(args, kwargs))

start = datetime.datetime.now()

result = fn(*args, **kwargs)

# after 功能增

duration = datetime.datetime.now() - start

print('function {} took {}s.'.format(fn.__name__, duration.total_seconds()))

return result

copyProperties(fn, wrap)

return wrap # 返回内层函数的引用**

@logger # add = logger(add)

def add(x, y):

"""

This is a function

:param x:

:param y:

:return:

"""

result = x + y

return result

print(add(10, 10000))

print(add.__name__, add.__doc__, sep='\n')

# 带参装饰器***

import datetime

import time

def copyProperties(src): # 包装函数和被包装函数字符文档统一

def copyWrap(dest):

dest.__name__ = src.__name__

dest.__doc__ = src.__doc__

return dest

return copyWrap

def logger(fn):

# @copyProperties(fn)

# 1 先不看@符号,返回copyWrap

# 2 @copyProperties(fn) 将其下面的函数(logWrap)作为参数,再拿到logWrap对象

@copyProperties(fn) # wrap = copyWrap(logger.wrap) 带参装饰器***

def logWrap(*args, **kwargs):

"""

This is wrapper

"""

# before 功能增强

print('args={}, kwargs={}'.format(args, kwargs))

start = datetime.datetime.now()

result = fn(*args, **kwargs)

# after 功能增

duration = datetime.datetime.now() - start

print('function {} took {}s.'.format(fn.__name__, duration.total_seconds()))

return result

return logWrap # 返回内层函数的引用**

@logger # add = logger(add)

def add(x, y):

"""

This is a function

:param x:

:param y:

:return:

"""

result = x + y

return result

print(add(10, 10000))

print(add.__name__, add.__doc__, sep='\n')

# 通过copyProperties函数将被包装函数的属性覆盖掉包装函数

# 凡是被装饰的函数都需要复制这些属性,这个函数很通用

# 可以将复制属性的函数构建成装饰器函数,带参装饰器

# 过滤执行时间过长的函数**

import datetime

import time

def logger(time):

def __logger(fn):

def wrap(*args, **kwargs):

# before 功能增强

start = datetime.datetime.now()

result = fn(*args, **kwargs)

# after 功能增强

duration = (datetime.datetime.now() - start).total_seconds()

if duration > time:

print('function {} took too long time -> {}s.'.format(fn.__name__, duration))

return result

return wrap # 返回内层函数的引用**

return __logger

@logger(3) # 等价于 add = logger(3)(add),其中logger(3)返回的是__logger

def add(x, y):

print('call add')

time.sleep(5)

return x + y

print(add(4, 5))

# 过滤执行时间在一定范围内的函数**

import datetime

import time

def logger(time1, time2):

def __logger(fn):

def wrap(*args, **kwargs):

# before 功能增强

start = datetime.datetime.now()

result = fn(*args, **kwargs)

# after 功能增强

duration = (datetime.datetime.now() - start).total_seconds()

if duration > time1 and duration < time2:

print('function {} took too long time -> {}s.'.format(fn.__name__, duration))

return result

return wrap # 返回内层函数的引用**

return __logger

@logger(3, 10) # 等价于 add = logger(3)(add),其中logger(3)返回的是__logger

def add(x, y):

print('call add')

time.sleep(6)

return x + y

print(add(4, 5))

# 带参装饰器

#  它是一个函数

#  函数作为它的形参

#  返回值是一个不带参的装饰器函数

#  使用@functionname(参数列表)方式调用

#  可以看到在装饰器外层又加了一层函数

# 实践:替换print,以便输出到其他存储***

import datetime

import time

def copyProperties(src): # 包装函数和被包装函数字符文档统一

def copyWrap(dest):

dest.__name__ = src.__name__

dest.__doc__ = src.__doc__

return dest

return copyWrap

def logger(duration, func=lambda name, delta:print('function {} took too long time -> {}s.'.format(name, delta))):

def __logger(fn):

# @copyProperties(fn)

# 1 先不看@符号,返回copyWrap

# 2 @copyProperties(fn) 将其下面的函数(logWrap)作为参数,再拿到logWrap对象

@copyProperties(fn) # wrap = copyWrap(logger.wrap) 带参装饰器***

def logWrap(*args, **kwargs):

"""

This is wrapper

"""

# before 功能增强

start = datetime.datetime.now()

result = fn(*args, **kwargs)

# after 功能增

delta = (datetime.datetime.now() - start).total_seconds()

if delta > duration:

func(fn.__name__, delta)

return result

return logWrap # 返回内层函数的引用**

return __logger

@logger(3) # add = logger(add)

def add(x, y):

"""

This is a function

:param x:

:param y:

:return:

"""

time.sleep(5)

result = x + y

return result

print(add(10, 10000))

python装饰器测试_python 装饰器相关推荐

  1. python 装饰器分类_Python 装饰器(Decorators) 超详细分类实例

    Python装饰器分类 Python 装饰器函数: 是指装饰器本身是函数风格的实现; 函数装饰器: 是指被装饰的目标对象是函数;(目标对象); 装饰器类 : 是指装饰器本身是类风格的实现; 类装饰器 ...

  2. python 装饰器实现_Python装饰器系列01 - 如何正确地实现装饰器

    虽然人们能利用函数闭包(function clouser)写出简单的装饰器,但其可用范围常受限制.多数实现装饰器的基本方式会破坏与内省(Introspection)的关联性. 可大多数人会说:who ...

  3. python 开闭原则_Python 装饰器@,对函数进行功能扩展操作示例【开闭原则】

    本文实例讲述了Python 装饰器@,对函数进行功能扩展操作.分享给大家供大家参考,具体如下: 装饰器可以对原函数进行功能扩展,但还不需要修改原函数的内容(开闭原则),也不需要修改原函数的调用. de ...

  4. python装饰器教学_Python装饰器学习(九步入门)

    这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 # -*- coding:gbk -*- '''示例1: 最简单的函数,表示调用了两次 ...

  5. python装饰器性能_python装饰器的特性原理详解

    这篇文章主要介绍了python装饰器的特性原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 今天发现了装饰器的另一种用法,下面就先上代码: d ...

  6. python装饰器应用_Python装饰器实现方法及应用场景详解

    应用场景: 1.授权(Authorization) 装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint).它们被大量使用于Flask和Django web框架中.这里是一个 ...

  7. 装饰器python的通俗理解_Python装饰器的通俗理解

    在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过思考和查阅才能略有领悟,我希望以下的内容会对你有帮助,我也努力通过通俗的方式使得对Py ...

  8. python装饰器理解_Python装饰器理解(新手)

    本文介绍Python其中一个功能--装饰器 只做简单介绍, 可以帮助新手理解装饰器, 没有完整的装饰器代码 装饰器本质上就是一个函数,在不修改源代码,调用方法的前提下,用来给其他函数添加功能的函数 知 ...

  9. python装饰器理解_python装饰器理解

    现在我们来看看如何从一些最基础的方式来理解Python的装饰器.英文讨论参考Here. 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解 ...

最新文章

  1. 优化 Web 服务器计算机和特定应用程序的配置文件以符合您的特定需要
  2. 15 年腾讯老兵谈技术人成长之路
  3. 一个神经元的价值和一个神经病的坚持
  4. iOS开发之--Masonry多个平均布局
  5. window7环境下安装neo4j server版本踩坑记录
  6. Javaweb编程中的乱码问题
  7. react leaflet_如何使用Leaflet在React中轻松构建地图应用
  8. 计算机核心手稿,梁思成建筑手稿曝光:在没有计算机的年代,他的认真细致令人敬佩...
  9. 飞机大战HTML5游戏源码,基于Canvas制作的网页版飞机大战游戏+飞机大战手机端
  10. Java进阶篇(六)——Swing程序设计(上),java面试题,java基础笔试题,BAT
  11. Oracle数据库报错【ORA-12514 】TNS 监听程序当前无法识别连接描述符中请求服务
  12. 云计算年度技术盛典,腾讯Techo Park开发者大会将在京召开
  13. java dom4j api_详解Java解析XML的四种方法(推荐使用DOM4J,因为for Java)
  14. 关于unity如何制作mmo
  15. linux命令halt之后怎么开启,Linux中halt命令起什么作用呢?
  16. 小程序快速入门:wxml的使用
  17. adsl密码查看器,宽带密码查看器,无广告,绿色版
  18. mac查看图片下一张
  19. 计算机网络位置设置工作组,工作组设置【处置步骤】
  20. 简单点教你python文件处理

热门文章

  1. Delphi Open Tools Api实例研究(二)
  2. 尺度不变特征变换(SIFT算法)Matlab程序代码测试例子的说明(Lowe的代码)
  3. 基于 c++ 语言的简易 vim 编辑器
  4. OO2019第一次作业总结
  5. 关于 数据库 my_slq的 安装及其卸载
  6. Stream - Web大文件上传插件
  7. android 选择多选图片
  8. SQL Server 2008 R2 中英文 开发版/企业版/标准版 链接地址
  9. 狗屎的Easy UI ,链接页面出错!搞了我一上午!
  10. 地震勘探原理名词解释