闭包

1.作用域L_E_G_B(局部、内嵌、全局...):

 x=10#全局

 def f():
a=5 #嵌套作用域
def inner():
count = 7 #局部变量
print a
return 1

从内往外寻找 a 。

2.高阶函数

a.函数名可以作为参数输入

b.函数名可以作为返回值

3.闭包

 def outer():
x=10
def inner(): #条件1 inner是内部函数
print(x) #条件2 外部环境的一个变量 return inner #结论: 内部函数inner就是一个闭包 outer()()#调用inner
#同上
f = outer()#获得inner
f()#调用执行inner #不能直接调用inner,因为inner为局部变量,全局无法调用

执行结果

10
10 Process finished with exit code 0

第10行,获得inner变量,第11行执行inner函数,而执行inner函数时(在外部执行),其中x变量既不属于inner函数内部变量,也不属于全局变量,按理应该报错却没报错,这种现象称为闭包。

定义:如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。

在内部函数里(inner函数中),对在外部作用域的变量(x)进行引用(print),那么内部函数(inner)就被认为是闭包。

装饰器

 import time

 def foo():
print("foo.....")
time.sleep(2) def bar():
print("bar.....")
time.sleep(3) def show_time(f): #函数名作参数
start = time.time()
f()
end = time.time()
print("spend %s" % (end - start)) show_time(bar)

函数名作参数,减少重复代码。

执行结果:

bar.....
spend 3.0022976398468018 Process finished with exit code 0

但是以上方法改变了调用方式,加上所需时间功能后,不是直接用foo,而是用show_time,这样对所有使用foo函数的代码都需修改,违背了封闭开放原则。

 import time

 def foo():
print("foo.....")
time.sleep(2) def bar():
print("bar.....")
time.sleep(3) def show_time(f): #函数名作参数 ,装饰器
def inner():
start = time.time()
f()
end = time.time()
print("spend %s" % (end - start))
return inner foo = show_time(foo)
foo()

show_time即为装饰器,inner函数为闭包,f函数名变量即为外部作用域变量。

执行结果:

foo.....
spend 2.00213360786438 Process finished with exit code 0

但是以上方法还需要自己赋值,不够简便、优雅。

优雅的写法:

 import time

 def show_time(f): #函数名作参数 ,装饰器
def inner():
start = time.time()
f()
end = time.time()
print("spend %s" % (end - start))
return inner @show_time # foo = show_time(foo), 给foo函数添加一个计算所需时间的功能
def foo():
print("foo.....")
time.sleep(2) #foo = show_time(foo)
foo()

11行,给foo函数添加一个计算所需时间的功能,@show_time,可理解为foo = show_time(foo)。

执行结果:

foo.....
spend 2.002133369445801 Process finished with exit code 0

被装饰函数参数(功能函数加参数):

 import time

 def show_time(f): #函数名作参数 ,装饰器
def inner(x, y):
start = time.time()
f(x, y)
end = time.time()
print("spend %s" % (end - start))
return inner @show_time # add = show_time(add), 给add函数添加一个计算所需时间的功能
def add(a, b):
print(a + b)
time.sleep(1) #foo = show_time(foo)
add(1, 2)

执行结果:

3
spend 1.0010321140289307 Process finished with exit code 0

不定长参数:

 import time

 def show_time(f): #函数名作参数 ,装饰器
def inner(*x, **y):
start = time.time()
f(*x, **y)
end = time.time()
print("spend %s" % (end - start))
return inner @show_time
def add(*a, **b): # a为元组
sums = 0
for i in a:
sums += i
print(sums)
time.sleep(1) add(1, 2, 5, 7, 9)#不定长参数

其中a为元组。

执行结果:

24
spend 1.0011086463928223 Process finished with exit code 0

装饰器参数:

 import time

 def logger(flag=''):#默认空

     def show_time(f):  # 函数名作参数 ,装饰器
def inner(*x, **y):
start = time.time()
f(*x, **y)
end = time.time()
print("spend %s" % (end - start))
if flag == 'true':
print('日志记录')
return inner
return show_time def show_time(f): #函数名作参数 ,装饰器
def inner(*x, **y):
start = time.time()
f(*x, **y)
end = time.time()
print("spend %s" % (end - start))
return inner @logger('true') # 相当于@show_time,不过有了一个flag变量,相当于闭包
def add(*a, **b): # a为元组
sums = 0
for i in a:
sums += i
print(sums)
time.sleep(1) add(1, 2, 5, 7, 9)#不定长参数 @logger()
def bar():
print("bar......")
time.sleep(3) bar()

装饰器加参数flag,决定是否输出日志,此时show_time为闭包。

执行结果:

24
spend 1.001152515411377
日志记录
bar......
spend 3.00311541557312

Python装饰器(函数)的更多相关文章

  1. python 装饰器函数基础知识

    1.装饰器的本质--一个闭包函数 2.装饰器的功能--在不改变原函数及其调用方式情况下对原函数功能进行拓展 3.带参数和返回值的装饰器 def timer(func): @wraps(func) #使 ...

  2. python基础篇_004_装饰器函数

    python装饰器函数 1.装饰器函数引导 功能:计算函数执行时长 import time """ 方式一: 函数首位添加时间,差值就是函数执行时间 缺点:每个函数都要加 ...

  3. Python 装饰器(Decorators) 超详细分类实例

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

  4. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  5. Python装饰器、内置函数之金兰契友

    装饰器:装饰器的实质就是一个闭包,而闭包又是嵌套函数的一种.所以也可以理解装饰器是一种特殊的函数.因为程序一般都遵守开放封闭原则,软件在设计初期不可能把所有情况都想到,所以一般软件都支持功能上的扩展, ...

  6. python装饰器1:函数装饰器详解

    装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 先混个眼熟 谁可以作为装饰器(可以将谁编写成装饰器): 函数 方法 实现了__call__的可调用类 装饰器可以去装饰谁(谁可以被装饰): 函 ...

  7. python基础(8)-装饰器函数&进阶

    从小例子进入装饰器 统计一个函数执行耗时 原始版本 import time # time模块有提供时间相关函数 def do_something(): print("do_something ...

  8. 万恶之源 - Python装饰器及内置函数

    装饰器 听名字应该知道这是一个装饰的东西,我们今天就来讲解一下装饰器,有的铁子们应该听说,有的没有听说过.没有关系我告诉你们这是一个很神奇的东西 这个有多神奇呢? 我们先来复习一下闭包 def fun ...

  9. python装饰器中@wraps作用--修复被装饰后的函数名等属性的改变

    Python装饰器(decorator)在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,Python的functools包中提供了一个叫wraps的de ...

  10. python学习——装饰器函数

    一.装饰器函数的作用是什么 答:装饰器函数是在不修改原函数及其调用方式的情况下对原函数功能进行扩展 对于搞python开发的人来说,函数占据了至关重要的地位.都说学好函数你就可以去找工作了,好了,假如 ...

随机推荐

  1. update svn cache 慢

    eclipse 打开了一个工程,就进行了update svn cache,弄了2个多小时了还是在进行.观察这个过程在空文件夹上也进行了不少时间,我感觉到可能方法错了.试了下关闭SVN--> sv ...

  2. springmvc 请求无法到达controller,出现404

    今天在配置SpringMVC时,访问项目一直出现404,无法访问. 报错: The origin server did not find a current representation for th ...

  3. 59. Spiral Matrix II (Array)

    Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For ...

  4. 使用Log4J监控系统日志邮件警报

    使用Log4J监控系统日志邮件警报 前言 在系统上线后,有时候遇到系统故障,这时候就可以登录服务器查看系统日志来排查问题.但是需要登录服务器,下载查找相关异常日志比较麻烦.而且没有监控的话,也无法实时 ...

  5. 有关jQuery valid 验证多个同name属性的input的问题

    今天遇到需要动态添加多个同name属性的input框,用jQuery valid进行验证时,没有指定不同的id,验证只会在第一个显示提示信息,因为jQuery valid显示的提示信息是根据每个inp ...

  6. C语言日志处理

    一.简介 zlog是一个高可靠性.高性能.线程安全.灵活.概念清晰的纯C日志函数库,在效率.功能.安全性上大大超过了log4c,并且是用c写成的,具有比较好的通用性. 二.安装 下载 https:// ...

  7. 宽字符、多字节、unicode、utf-8、gbk编码转化

    今天遇到一个编码的问题,困惑了我很长时间,所以就简要的的了解了一下常用的编码类型. 我们最常见的是assic编码,它是一种单字节编码,对多容纳256个字符. 我们在编程的时候经常遇到unicode,u ...

  8. python教学视频

    3 X王的 链接: http://pan.baidu.com/s/1bW2UrO 密码: quit4 django 链接: http://pan.baidu.com/s/1o8UsNDS 密码: 8x ...

  9. SpringCloud之服务注册-eureka

    类似于DUBBO 的zookeeper, SpringCloud本身提供一套服务注册中心--eureka 与zookeeper的区别在于 1:zookeeper本身就是一个应用,安装即可用:eurek ...

  10. C语言 void 万能类型

    C中 void类型其实是一种万能类型, 也就是说 我们的 void 可以代表任意一种类型,也就是说他的范围要比具体的一种类型要宽广, 例如: int *p = NULL;void *ptr = p; ...