python中decorator装饰器

语法示例:

@decorator

什么是装饰器:

问题:
定义一个函数后
在运行时动态增加功能
又不想改动函数本身的代码

示例:

# 希望对下列函数调用增加log功能,打印出函数调用:
def f1(x):
return x*
def f2(x):
return x*x
def f3(x):
return x*x*x

方法1:直接修改原函数的定义

def f1(x):
print('call f1')
return x*
def f2(x):
print('call f2')
return x*x
def f3(x):
print('call f3')
return x*x*x

有没有更简单的方法?

高阶函数
. 可以接受函数作为参数
. 可以返回函数
是否可以接受一个函数,对其进行包装,然后返回一个新函数?

方法2:通过高阶函数返回新函数(装饰器函数):

def f1(x):
return x*
def new_fn(f):
def fn(x):
print('call'+f.__name__+'()')
return f(x)
return fn

调用1:

g1 = new_fn(f1)
print( g1() )

调用2:

f1 = new_fn(f1)
print( f1() )

装饰器:

python内置@语法就是为了简化装饰器调用

@new_fn
def f1(x):
return x*

等同于:

def f1(x):
return x*
f1 = new_fn(f1)

装饰器的作用:

可以极大简化代码,避免每个函数编写重复性的代码
打印日志:@log
检测性能:@performance
数据库事务:@transaction
URL路由:@post('/register')

装饰器示例:

1. 如果自定义函数存在两个形参,上述装饰器函数内部固定写了一个形参,会出现错误怎么办:

@new_fn
def add(x,y):
return x+y
# 这里会出现错误,所以需要更改 new_fn 函数如下:
def new_fn(f):
def fn(*args, **kwargs):
print('call'+f.__name__+'()')
return f(*args, **kwargs)
return fn

2. 请编写一个@performance,它可以打印出函数调用的时间。计算函数调用的时间可以记录调用前后的当前时间戳,然后计算两个时间戳的差。

import time
def performance(f):
def fn(*args, **kw):
t1 = time.time()
r = f(*args, **kw)
t2 = time.time()
print 'call %s() in %fs' % (f.__name__, (t2 - t1))
return r
return fn @performance
def factorial(n):
return reduce(lambda x,y: x*y, range(, n+))
print factorial()

3.上述装饰器函数只能接受一个函数参数,如果装饰器函数需要传入额外的参数怎么办?

@log('DEBUG')
def my_func():
pass

把上面的定义翻译成高阶函数的调用,就是:

my_func = log('DEBUG')(my_func)

上面的语句看上去还是比较绕,再展开一下:

log_decorator = log('DEBUG')
my_func = log_decorator(my_func)

上面的语句又相当于:

log_decorator = log('DEBUG')
@log_decorator
def my_func():
pass

所以,带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收my_func并返回新函数:

def log(prefix):
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator @log('DEBUG')
def test():
pass
print test()

上述第二个例子:@performance只能打印秒,请给 @performace 增加一个参数,允许传入's'或'ms':

import time
import functools
def performance(unit):
def perf_decorator(f):
@functools.wraps(f)
def wapper(*args, **kw):
t1 = time.time()
r = f(*args, **kw)
t2 = time.time()
t = (t2 - t1) * if unit=='ms' else (t2 - t1)
print 'call %s() in %f %s' % (f.__name__, t,unit)
return r
return wapper
return perf_decorator @performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(, n+))
print factorial()
print factorial.__name__

完善的装饰器写法:

【python基础学习】基础重点难点知识汇总的更多相关文章

  1. Python基础1:一些小知识汇总

    一.#!usr/bin/env python 脚本语言的第一行,指定执行脚本的解释器. #!/usr/bin/python 是告诉操作系统执行这个脚本的时候,调用/usr/bin下的python解释器 ...

  2. Oracle 数据库 基础学习 (一) SQL基本知识

    Oracle 从零开始,不知所措.要掌握一种技能,最好的方式是先学会怎么使用它,然后再深入学习,先有样子,再有技术.   一,什么是数据库? 为什么需要数据库? 数据库实质上是一个信息的列表,或者是一 ...

  3. Python新手学习基础之数据类型——字符串的切片截取

    切片截取是python中字符串常见的一些操作,我们会在这篇文章里详细介绍,切片截取的作用是获取子字符或子字符串. 实际上,我们要做的就是使用索引,用冒号分隔两个索引,形式为:变量[头下标:尾下标],冒 ...

  4. Python新手学习基础之初识python——与众不同1

    Python是什么? 首先我们先简单介绍下python这门语言,Python是一种解释性的脚本语言,它不需要像C/C++那样先编译再执行,也不像JS那样可以在浏览器上直接执行.它为我们提供的基础代码库 ...

  5. js学习重点难点知识总结 (巩固闭包、原型、原型链)

    学习重点知识总结   1.闭包知识点巩固        闭包函数:                    1.可以实现函数外部访问函数内部的变量                     2.在Java ...

  6. Python新手学习基础之初识python——与众不同2

    看完了Python的缩进,现在来看看Python的标识符.引号和注释. 标识符 关于Python的标识符,其实不是与众不同,只是有一定的规则. 标识符是编程时使用的名字.在Python中,标识符有几点 ...

  7. Python新手学习基础之数据结构-列表1

    创建一个列表 讲完了序列,我们现在来讲讲Python中最常见的一种序列数据类型--列表. 列表创建的语法是: list_name = [item1, item2, item3, .......] 列表 ...

  8. Python新手学习基础之数据结构-序列1

    序列概念 序列,顾名思义就是有顺序的列,在Python里序列类型的数据结构包括字符串,列表和元组.既然都是序列类型,说明他们有很多共通点,他们的每一个元素都可以通过指定的偏移量方式(索引操作)来获得, ...

  9. Python新手学习基础之数据结构-对数据结构的认知

    什么是数据结构? 数据结构是指:相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成. 举个列子来理解这个数据结构: 数据可以比作是书本, 数据结构相当于书架,书存放在书架上, ...

随机推荐

  1. 线下AWD平台搭建以及一些相关问题解决

    线下AWD平台搭建以及一些相关问题解决 一.前言 文章首发于tools,因为发现了一些新问题但是没法改,所以在博客进行补充. 因为很多人可能没有机会参加线下的AWD比赛,导致缺乏这方面经验,比如我参加 ...

  2. 推荐一些github上的免费好书

    本文转载自公众号:跟着小一写bug.  熬夜等于慢性自杀,那熬夜和喜欢的人说话,算不算是慢性殉情?        晚上好 小一来啦 有木有想哀家 其实今晚小一有个拳击课 可是 由于项目明天要演示 调一 ...

  3. Jmeter CSV参数带汉字处理

    问题1:请求参数中有汉字,在windows上调测压测没有问题,直接把参数文件上传到linux 服务器上进行分布式压测时发现参数取出后为乱码,linux上后台查看文件也是乱码 处理方法: 初步想到是因为 ...

  4. document.forms使用

    定义:document.forms返回form表单的集合,包含了当前DOM结构中所有的form表单. 语法: . 获取当前DOM结构中的第一个form表单. document.forms[] . 获取 ...

  5. Intel重大漏洞之Meltdown和Spectre

    史上最大漏洞危机:影响所有 iPhone.Android.PC 设备,修复困难重重 近日,英特尔的日子可并不好过. 作为全球知名芯片制造商,任何有关英特尔芯片漏洞的问题都会导致全球上百万设备遭受牵连. ...

  6. php门面模式(facade pattern)

    书上不全的代码,我自己补全的. <?php /* The facade pattern is used when we want to simplify the complexities of ...

  7. 微信开发:"errcode": -1000,"errmsg": "system error"错误的解决办法

    最近在微信开发使用微信公众平台接口调试工具时遇到错误. 错误再现:使用appid及appsecret在该测试工具中获取access_token,检查问题时,校验全部通过,但是无法获取access_to ...

  8. GC线程是不是守护线程

    是 线程的话分为守护线程和非守护线程(即用户线程) 只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作; 只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作,守护线程 ...

  9. CSS Cross-Browser Inline-Block

    低版本的IE,火狐 不支持  Inline-Block 属性,想要达到目的我们需要多做一些额外的工作 , 参考页面为:https://blog.mozilla.org/webdev/2009/02/2 ...

  10. SparkStreaming 性能、稳定、容错与语义

      怎样提高Spark Streaming的性能 1.创建多个接收器 待定:: 2.调节每一个batch interval的数据块的数量,其实就是调整上面第二个问题中提到的配置spark.stream ...