Python【第四课】 装饰器
本篇内容
什么是装饰器
装饰器需要遵循的原则
实现装饰器的知识储备
高阶函数
函数嵌套
闭包函数
无参函数
- 装饰器示例
1.什么是装饰器
器即函数
装饰即修饰,意指为其他函数添加新功能
装饰器定义:本质就是函数,功能是为其他函数添加新功能
2.装饰器需要遵循的原则
1.不修改被装饰函数的源代码(开放封闭原则)
2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式
3.实现装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包
4.高阶函数
高阶函数定义:
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数
# 接收的参数是一个函数名
def count(func,num):
num=func(num)
print(num) count(abs,-10) # 输出
# 10
# 返回值是一个函数
def count():
print('输出数字的绝对值方法:')
return abs put=count()
print(put(-10)) # 输出
# 输出数字的绝对值方法:
# 10
高阶函数总结
1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能,
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
5.函数嵌套
之前写过,去看看吧,我觉得写得还挺好的。
函数基础:
http://www.cnblogs.com/40kuai/articles/6374356.html
6.闭包函数
闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个参数a, 内层函数依旧传入一个参数b, 内层函数使用a和b, 最后返回内层函数
函数是什么
地球人都知道:函数只是一段可执行代码,编译后就“固化”了,每个函数在内存中只有一份实例,得到函数的入口点便可以执行函数了。在函数式编程语言中,函 数是一等公民(First class value:第一类对象,我们不需要像命令式语言中那样借助函数指针,委托操作函数),函数可以作为另一个函数的参数或返回值,可以赋给一个变量。函数可 以嵌套定义,即在一个函数内部可以定义另一个函数,有了嵌套函数这种结构,便会产生闭包问题。如:
>>> def ExFunc(n):
sum=n
def InsFunc():
return sum+1
return InsFunc >>> myFunc=ExFunc(10)
>>> myFunc()
11
>>> myAnotherFunc=ExFunc(20)
>>> myAnotherFunc()
21
>>> myFunc()
11
>>> myAnotherFunc()
21
>>>
在这段程序中,函数InsFunc是函数ExFunc的内嵌函数,并且是ExFunc函数的返回值。我们注意到一个问题:内嵌函数InsFunc中 引用到外层函数中的局部变量sum,IronPython会这么处理这个问题呢?先让我们来看看这段代码的运行结果。当我们调用分别由不同的参数调用 ExFunc函数得到的函数时(myFunc(),myAnotherFunc()),得到的结果是隔离的,也就是说每次调用ExFunc函数后都将生成并保存一个新的局部变量sum。其实这里ExFunc函数返回的就是闭包。
引用环境
按照命令式语言的规则,ExFunc函数只是返回了内嵌函数InsFunc的地址,在执行InsFunc函数时将会由于在其作用域内找不到sum变量而出 错。而在函数式语言中,当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回。现在给出引用环境的定义就 容易理解了:引用环境是指在程序执行中的某个点所有处于活跃状态的约束(一个变量的名字和其所代表的对象之间的联系)所组成的集合。闭包的使用和正常的函 数调用没有区别。
由于闭包把函数和运行时的引用环境打包成为一个新的整体,所以就解决了函数编程中的嵌套所引发的问题。如上述代码段中,当每次调用ExFunc函数 时都将返回一个新的闭包实例,这些实例之间是隔离的,分别包含调用时不同的引用环境现场。不同于函数,闭包在运行时可以有多个实例,不同的引用环境和相同 的函数组合可以产生不同的实例。
6.1 闭包函数定义
python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).
>>>def addx(x):
>>> def adder(y): return x + y
>>> return adder
>>> c = addx(8)
>>> type(c)
<type 'function'>
>>> c.__name__
'adder'
>>> c(10)
18
结合这段简单的代码和定义来说明闭包:
如果在一个内部函数里:adder(y)就是这个内部函数,
对在外部作用域(但不是在全局作用域)的变量进行引用:x就是被引用的变量,x在外部作用域addx里面,但不在全局作用域里,
则这个内部函数adder就是一个闭包。
6.2 闭包函数的注意事项
1.闭包中是不能修改外部作用域的局部变量的
>>> def foo():
... m = 0
... def foo1():
... m = 1
... print m
...
... print m
... foo1()
... print m
...
>>> foo()
0
1
0
# 从执行结果可以看出,虽然在闭包里面也定义了一个变量m,但是其不会改变外部函数中的局部变量m。
2.以下这段代码是在python中使用闭包时一段经典的错误代码
def foo():
a = 1
def bar():
a = a + 1
return a
return bar
这段程序的本意是要通过在每次调用闭包函数时都对变量a进行递增的操作。但在实际使用时没有把参数传给闭包函数。
其他详细见:http://www.cnblogs.com/JohnABC/p/4076855.html
7.无参函数
无参装饰器=高级函数+函数嵌套
无参装饰器=高级函数+函数嵌套
基本框架
1 #这就是一个实现一个装饰器最基本的架子
2 def timer(func):
3 def wrapper():
4 func()
5 return wrapper
加上参数
1 def timer(func):
2 def wrapper(*args,**kwargs):
3 func(*args,**kwargs)
4 return wrapper
加上功能
import time
def timer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
func(*args,**kwargs)
stop_time=time.time()
print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
return wrapper
加上返回值
import time
def timer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
return res
return wrapper
使用装饰器
def cal(array):
res=0
for i in array:
res+=i
return res cal=timer(cal)
cal(range(10))
语法糖@
@timer #@timer就等同于cal=timer(cal)
def cal(array):
res=0
for i in array:
res+=i
return res cal(range(10))
小知识点:
# import functools
# @functools.wraps(func)
# 被装饰器调用过的函数帮助信息显示为装饰器的帮助信息
# 调入functools模块可以解决该问题
8.装饰器示例
抄袭地址:http://www.cnblogs.com/linhaifeng/articles/6140395.html
Python【第四课】 装饰器的更多相关文章
- Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化
本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解 ...
- python设计模式之内置装饰器使用(四)
前言 python内部有许多内建装饰器,它们都有特别的功能,下面对其归纳一下. 系列文章 python设计模式之单例模式(一) python设计模式之常用创建模式总结(二) python设计模式之装饰 ...
- python函数与方法装饰器
之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...
- 【笔记】Python基础五:装饰器
一,什么是装饰器 本质就是函数,功能是为其他函数添加附加功能 原则: 1,不修改被修饰函数的源代码 2,不修改被修饰函数的调用方式 例子: import time def timmer(func): ...
- Python高级--闭包与装饰器
前言:在Python中,闭包是一种非常有用的功能!它通常与装饰器一起搭配使用,可以在不改变被装饰函数的功能的基础上,完成更多的功能.如权限认证. 一.如何定义闭包 1.闭包就是两个嵌套的函数,外层函数 ...
- Python中利用函数装饰器实现备忘功能
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下 " ...
- guxh的python笔记三:装饰器
1,函数作用域 这种情况可以顺利执行: total = 0 def run(): print(total) 这种情况会报错: total = 0 def run(): print(total) tot ...
- python 3.x 的装饰器笔记
今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找.虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python ...
- python 中多个装饰器的执行顺序
python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...
- Python函数编程——闭包和装饰器
Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...
随机推荐
- emqtt 试用(六)系统主题
$SYS-系统主题 EMQ 消息服务器周期性发布自身运行状态.MQTT 协议统计.客户端上下线状态到 $SYS/ 开头系统主题. $SYS 主题路径以 "$SYS/brokers/{node ...
- JWT(JSON Web Token) 多网站的单点登录,放弃session
多个网站之间的登录信息共享, 一种解决方案是基于cookie - session的登录认证方式,这种方式跨域比较复杂. 另一种替代方案是采用基于算法的认证方式, JWT(json web token) ...
- less初学手记
less语言学习手记 工具下载 在less学习中,我们都会需要随时编译我们的less文件,查看生成的css样式表是否正确,以及是否符合我们的要求.推荐一款编译软件供大家下载使用:koala,本软件支持 ...
- spring1——IOC之原理
spring框架的核心是IOC和AOP. 控制反转--IOC是一种编程思想,在spring中指的是对象的装配和管理交给了spring容器.这样做的好处是降低了系统之间的偶合度,既调用者不用再去创建被调 ...
- 理解JavaScript中函数方法
1.函数声明和函数表达式 通过字面量创建函数的方式有两种函数声明和函数表达式: 函数声明: function sum(x, y) { var result = x + y; return result ...
- jacascript DOM节点——节点关系与操作
前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 节点关系 DOM可以将任何HTML描绘成一个由多层节点构成的结构.每个节点都拥有各自的特点.数据和方法,也 ...
- jmc远程连接windows环境tomcat
新人报道,先发个小贴赚点人气,本人目前还是小菜鸟,想要飞却怎么也飞不高,哈哈,转到正题,最近发现这个JMC挺好用的,而且也不用像Jprofile需要破解,本地连接挺方便的, 但配置服务器确实挺坑的,按 ...
- 如何在jenkins的maven项目中,用mvn命令行指定findbugs的黑名单规则文件
一:问题背景 最近在研究jenkins的过程中,针对maven项目,打算添加findbugs进行静态检查,但我不太想在项目的pom中进行修改,最好可以只修改jenkins的job配置,即配置外部化. ...
- java--Iterator迭代问题:集合并发访问异常
用Iterator对数组进行迭代后,如果在迭代过程中对数组进行增加元素操作(这里iterator本身没有提供增加操作方法)时,就会抛出并发访问异常: 异常如下: Exception in thread ...
- vim 去除代码行号并正常缩进代码
先命令模式下输入 :%s/[ \t]*\d\{1,4\}/ 即使用正则表达式替换 后命令模式下输入 gg 调到行首 v 进入可视化 G 调到行尾 = 所有代码正常缩进