闭包

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. jsp脚本语法

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  2. du熊的机器人

    [du熊的机器人] Description du熊正在玩一个别人刚送给它的机器人.这个机器人只能在一个棋盘中行走,棋盘的左上角格子为(0, 0),右下角格子为(X, Y). du熊控制这个机器人从棋盘 ...

  3. varchar和Nvarchar区别(转)

    Unicode字符集就是为了解决字符集这种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示 如果还为了这个纠结,就直接看看后面的解说,做决定吧. 一般如果用到中文或者其 ...

  4. ios的@property属性和@synthesize属性(转)

    当你定义了一系列的变量时,需要写很多的getter和setter方法,而且它们的形式都是差不多的,,所以Xcode提供了@property 和@synthesize属性,@property用在 .h ...

  5. 95. Unique Binary Search Trees II (Tree; DFS)

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  6. Linux文件权限查看及修改命令chmod,chown

    查看权限 Linux文件访问权限分为可读,可写和可执行三种. 可用ls -l命令查看,例: ls -l或者 ll 显示为 -r--r--r--. 1 root root 21 Jan 5 23:02 ...

  7. vmware虚拟机开机报附件中的错误的解决办法

    Virtualized Inter VT-x/EPT is incompatible with this virtual machine configuration 在没有虚拟化msg.inter.h ...

  8. [leetcode]273. Integer to English Words 整数转英文单词

    Convert a non-negative integer to its english words representation. Given input is guaranteed to be ...

  9. js获得URL中的参数

    js获得URL中的参数 function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + &quo ...

  10. Java 设计模式系列(二)简单工厂模式和工厂方法模式

    Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...