修饰符基础——闭包

什么是闭包呢?标准的概念大家可以看wikipedia上的解释

举个例子:

  def do_add(base):
def add(increase):
return base + increase
return add

do_add函数里嵌套了一个内层函数add,这个内层函数就是一个闭包,其实可以也不用管这个“闭包”的概念,先来看下这种模式解决些什么问题.

调用do_add函数:a = do_add(23),由于内层的函数add里的逻辑用到了do_add函数的入参,而这时这个入参base绑定了值23,由于do_add函数返回的是函数add,所以这时的a其实就是内部的add绑定了23的函数add;同理可知,b = do_add(44),这里的b就是内部add绑定了44的函数add,a和b这两个add函数是不相同的,因为内部add绑定的值不同,只是两个函数的模板相同罢了,这时我们执行a(100)得到结果是123,b(100)得到结果是144。这样做有什么用呢?其实可以这样看:我们可以把a = do_add(23)和b = do_add(44)看成是配置过程,23和44是配置信息,a(100)和b(100)根据不同的配置获得不同的结果,这样我们就可以解决开发中“根据配置信息不同获得不同结果”的问题

而修饰符实际上就是闭包一种形式,只是配置过程参数是所修饰的一个函数,并且用@符号代替了a=do_add(23)这样的配置方式,下面看一下修饰符的用法

修饰符用法

修饰符无参数,原函数无参数

    import time  

    def timeit(func):
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper @timeit
def foo():
print 'in foo()' foo()

如上代码:对所修饰函数运行时间的进行统计,最后修饰过的 foo() 等价于 foo=timeit(foo) 而timeit返回wrapper,归根到底真正执行的是wrapper

在实际应用中,函数很少没有参数,所以我们看看foo有参数的情况下,修饰符怎么用

修饰符无参数,原函数有参数

    import time  

    def timeit(func):
def wrapper(args):
start = time.clock()
func(args)
end =time.clock()
print 'used:', end - start
return wrapper @timeit
def foo(arg):
print 'in foo(),arg is' + arg
foo("aaaaa")

上述过程可以简化如下:

[decorated] foo(‘aaaaa’)   =>   timeit(foo)(‘aaaaa’)  =>  wrapper(‘aaaaa’)  =>  [real] foo(‘aaaaa’)

如果修饰符函数也有参数,又怎么用呢?

修饰符有参数,原函数有参数

    import time  

    def timeit(s):
def wrapper1(func)
def wrapper2(args):
print "the decorator's arg is"+s
start = time.clock()
func(args)
end =time.clock()
print 'used:', end - start
return wrapper2
return wrapper1 @timeit(s="hello")
def foo(arg):
print 'in foo(),arg is' + arg
foo("aaaaa")

__同理,就是多加了一层闭包。 __

应用多个修饰符

这个记住一个结论就好了,就是修饰符从离原函数最近的开始包裹,最外层的修饰符最后包裹

应用举例——Fibonacci数列

    def memoize(f):
cache = {}
def helper(x):
if x not in cache:
cache[x] = f(x)
return cache[x]
return helper @memoize()
def fib(n):
if n in (0, 1):
return n
else:
return fib(n - 1) + fib(n - 2)

参考文献

1.http://zh.wikipedia.org/wiki/闭包_(计算机科学)

2.http://programmingbits.pythonblogs.com/27_programmingbits/archive/50_function_decorators.html

3.http://www.python.org/dev/peps/pep-0318/

4.http://www.cnblogs.com/Jerry-Chou/archive/2012/05/23/python-decorator-explain.html

5.http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html

python——修饰符的更多相关文章

  1. 【转载】 python修饰符@

    @符号在python语言中具有特殊含义,用来作为修饰符使用, @修饰符有点像函数指针,python解释器发现执行的时候如果碰到@修饰的函数,首先就解析它,找到它对应的函数进行调用,并且会把@修饰下面一 ...

  2. python 修饰符(转载)

    首先一个修饰符的实例: #!/usr/bin/env python def run(fn): def do_hello(): print "begin..." fn() print ...

  3. Python 修饰符, 装饰符

    1, 看到@时候, 程序已经开始执行了. 所以@实际上是立即执行的 2, @后面的跟着函数名, 该函数(f1)是之前定义过的.  再后面跟着一个函数(f2), f2是f1的入口. 那么执行顺序是,  ...

  4. Python 修饰符

    def hello(fn):    def wrapper():        print "hello"        fn()        print "goodb ...

  5. python @修饰符的几种用法

    http://www.360doc.com/content/17/0715/16/10408243_671545922.shtml http://www.cnblogs.com/Egbertbaron ...

  6. Python 修饰符@用法

    def funA(desA): print("It's funA") def funB(desB): print(desB( )) print("It's funB&qu ...

  7. 【转载】Python 描述符简介

    来源:Alex Starostin 链接:www.ibm.com/developerworks/cn/opensource/os-pythondescriptors/ 关于Python@修饰符的文章可 ...

  8. Python 中的@修饰符作用

    在Python 2.4以上的的函数中偶尔会看到函数定义的上一行有@functionName的修饰,这一下这个语法细节,其实这有点像C语言带参数的宏操作,解释器读到这样的修饰之后,会先解析@后的内容,直 ...

  9. @修饰符--python中的装饰器

    装饰器模式可以在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职责,也能够处理那些可以撤销的职责.经常用于日志记录.性能测试等场合. 想象一下这个很常见的场景,你写了一个方法只提供给以登陆的 ...

随机推荐

  1. 基于BeanNameViewResolver解析器,自定义视图

    概述 基于spring-mvc自定义视图,以BeanNameViewResolver作为解析器,以满足特殊需求. 本文以输出多个pdf文件的压缩文件,供前台下载的需求为例:但是不提供服务层实现. 实现 ...

  2. Spring源码分析之Bean的加载流程

    spring版本为4.3.6.RELEASE 不管是xml方式配置bean还是基于注解的形式,最终都会调用AbstractApplicationContext的refresh方法: @Override ...

  3. Bzoj2818 Gcd(莫比乌斯反演)

    题面 题意都在题目里面了 题解 你可以把题意看成这个东西 $$ \sum_{i=1}^n\sum_{j=1}^m\mathbf f(gcd(i,j)) $$ 其中$\mathbf f(n)$为$是否是 ...

  4. 洛谷——P2799 国王的魔镜

    P2799 国王的魔镜 题目描述 国王有一个魔镜,可以把任何接触镜面的东西变成原来的两倍——只是,因为是镜子嘛,增加的那部分是反的.比如一条项链,我们用AB来表示,不同的字母表示不同颜色的珍珠.如果把 ...

  5. Visual Studio找不到adb.exe错误解决

    Visual Studio找不到adb.exe错误解决 错误信息:Cannot find adb.exe in specified SDK path.出现这种情况,是因为没有安装Android SDK ...

  6. 内存分哪些区 C++,ios,java

    韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com C/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)—由编译器自动分配释放,存 ...

  7. Erlang学习记录(三)——表达式大集合

    Erlang中的表达式必须以.结束才会去执行.如果不加.你在编译环境下按多少次Enter,表达式都不会执行,表达式之间可以用,分隔,以.结尾后所有的表达式都会执行,但是只有最后一个以.结尾的表达式会在 ...

  8. Codeforces Beta Round #2 B. The least round way dp

    B. The least round way 题目连接: http://www.codeforces.com/contest/2/problem/B Description There is a sq ...

  9. KVM工具libvirt、virsh、virt-manager的简单介绍

    KVM虚拟化中libvirt是目前使用最为广泛的对KVM虚拟机进行管理的工具和应用程序接口,而且一些常用的虚拟机管理工具(virsh.virt-install.virt-manager等)和云计算框架 ...

  10. Understanding how SQL Server executes a query

    https://www.codeproject.com/Articles/630346/Understanding-how-SQL-Server-executes-a-query https://ww ...