职业:python装饰器

http://blog.csdn.net/ablo_zhou/article/details/5471952

Python 2.4以后,增加了@符号修饰函数对函数进行修饰,python3.0/2.6又增加了对类的修饰。

我现在使用的python版本,支持对class的修饰:

zhouhh@zhouhh-home:~$ python

Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15)

[GCC 4.4.1] on linux2

Type "help", "copyright", "credits" or "license" for more information.

@修饰符挺像是处理函数或类之前进行预处理。

语法示例:

@dec1

@dec2

def test(arg):

    pass

其效果类似于

dec1(dec2(test(arg)))

修饰函数还可以带参数。

@dec1(arg1,arg2)

def test(testarg)

效果类似于

dec1(arg1,arg2)(test(arg))

[]

http://blog.csdn.net/guang11cheng/article/details/51179410

示例1

def minus(f):

    print 'minus'

    f()

def plus(f):

    print 'plus'

    f()

def test(a):

    if a > 3 :

        return plus

    else :

        return minus

@test(5)

def xxx():

    print 'ok'

解释器首先会解释@符号后面的代码,如果如上面的代码类似,那么test(5)将被执行,因为test参数5大于3,所以会返回函数指针plus(可以用C的这个名字来理解),plus将下一行的函数指针xxx当作参数传入,直到执行完成。最后结果将输出‘plus’和‘ok’。 有时候可能是下面这种形式:

示例2

def minus(f):

    print 'minus'

    f()

@minus

def xxx():

    print 'ok'

minus因为本身已经是一个函数指针,所以会直接以xxx作为参数传入,结果会输出‘minus’和‘ok’。

--wjt:是不是说,如果一个函数的入参是另一个函数(实例2),或者一个函数的返回值是另一个带函数参数的函数(实例1),那么这个函数就可以被@。?

即被@的函数,其需要有能力接收的起下一行的函数进入自己的函数体中。?

果真如此。那么装饰器其实并没有什么神秘的,无非就是一个语法:

语法示例:

@dec1

@dec2

def test(arg):

    pass

其效果类似于

dec1(dec2(test(arg)))

只需要遵守其语法。实质按上面蓝色字体讲的理解即可。

即装饰器:(1)形式上要求即被@的函数,其需要有能力接收的起下一行的函数进入自己的函数体中;(2)实质执行上效果类似于dec1(dec2(test(arg)))。

下面的例子我分析出的结果正确,说明我的理解到位:

def f1(arg):

    print "f1"

    rl = arg()

    print rl

    return rl + "f1"

@f1

def f2(s = ""):

    print "f2"

    return s + "f2r"

print "start"

D:\Users\wangjiangtao517>python D:\wangjt\zsq.py

f1

f2

f2r

start

--------------------------------------------------------------------

《一步一步详解装饰器》

http://python.jobbole.com/81683/

6. 嵌套函数

Python允许创建嵌套函数。这意味着我们可以在函数里面定义函数而且现有的作用域和变量生存周期依旧适用。

def outer():

    x = 1

    def inner():

        print x # 1

    inner() # 2

outer()

1

这个例子有一点儿复杂,但是看起来也还行。想一想在#1发生了什么:python解释器需找一个叫x的本地变量,查找失败之后会继续在上层的作用域里面寻找,这个上层的作用域定义在另外一个函数里面。对函数outer来说,变量x是一个本地变量,但是如先前提到的一样,函数inner可以访问封闭的作用域(至少可以读和修改)。在#2处,我们调用函数inner,非常重要的一点是,inner也仅仅是一个遵循python变量解析规则的变量名,python解释器会优先在outer的作用域里面对变量名inner查找匹配的变量.

7. 函数是python世界里的一级类对象

显而易见,在python里函数和其他东西一样都是对象。

issubclass(int, object) # all objects in Python inherit from a common baseclass

True

def foo():

    pass

foo.__class__ # 1

<type 'function'>

issubclass(foo.__class__, object)

True

函数在python里面就是对象,和其他的东西一样,也许这样描述会太学院派太官方了点:在python里,函数只是一些普通的值而已和其他的值一毛一样。这就是说你可以把函数像参数一样传递给其他的函数或者说从函数了里面返回函数!如果你从来没有这么想过,那看看下面这个例子:

def add(x, y):

    return x + y

def sub(x, y):

    return x - y

def apply(func, x, y): # 1

    return func(x, y) # 2

apply(add, 2, 1) # 3

3

apply(sub, 2, 1)

1

把函数当做返回值:

def outer():

    def inner():

        print "Inside inner"

    return inner # 1

foo = outer() #2

>>> foo

<function inner at 0x03912DF0> --- 显示变量 foo 的值(是一个函数)

>>> foo()

Inside inner  ---执行了函数inner()

这个例子看起来也许会更加的奇怪。在#1处我把恰好是函数标识符的变量inner作为返回值返回出来。这并没有什么特殊的语法:”把函数inner返回出来,否则它根本不可能会被外界所调用。“还记得变量的生存周期吗?每次函数outer被调用的时候,函数inner都会被重新定义,如果它不被当做变量返回的话,每次执行过后它将不复存在。

在#2处我们捕获返回值 – 函数inner,将它存在一个新的变量foo里。我们能够看到,当对变量foo进行求值,它确实包含函数inner,而且我们能够对他进行调用。初次看起来可能会觉得有点奇怪,但是理解起来并不困难是吧。

8. 闭包

def outer(x):

    def inner():

        print x # 1

    return inner

print1 = outer(1)

print2 = outer(2)

print1()

1

print2()

2

9. 装饰器

装饰器其实就是一个闭包,把一个函数当做参数然后返回一个替代版函数.

def outer(some_func):

    def inner():

        print "before some_func"

        ret = some_func() # 1

        return ret + 1

    return inner

def foo():

    return 1

decorated = outer(foo) # 2

decorated()

before some_func

2

仔细看看上面这个装饰器的例子。我们定义了一个函数outer,它只有一个some_func的参数,在他里面我们定义了一个嵌套的函数inner。inner会打印一串字符串,然后调用some_func,在#1处得到它的返回值。在outer每次调用的时候some_func的值可能会不一样,但是不管some_func的之如何,我们都会调用它。最后,inner返回some_func() + 1的值 – 我们通过调用在#2处存储在变量decorated里面的函数能够看到被打印出来的字符串以及返回值2。

我们可以认为变量decorated是函数foo的一个装饰版本,一个加强版本。事实上如果打算写一个有用的装饰器的话,我们可能会想愿意用装饰版本完全取代原先的函数foo,这样我们总是会得到我们的”加强版“foo。想要达到这个效果,完全不需要学习新的语法,简单地赋值给变量foo就行了:

foo = outer(foo)

foo # doctest: +ELLIPSIS

<function inner at 0x>

现在,任何怎么调用都不会牵扯到原先的函数foo,都会得到新的装饰版本的foo

--------------------------------

《closure(闭包)》

https://www.cnblogs.com/Pierre-de-Ronsard/archive/2012/08/20/2647812.html

closure概念:在一个内部函数中,对外部作用域的变量进行引用,那么内部函数就被认为是closure(闭包)

自由变量:定义在外部函数内,被内部函数引用或者使用的变量为自由变量

函数func_closure 在函数被调用前和调用后使用,效果是一样的

https://segmentfault.com/a/1190000007321972

用比较容易懂的人话说,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。看例子。

def make_printer(msg):

    def printer():

        print msg  # 夹带私货(外部变量)

    return printer  # 返回的是函数,带私货的函数

printer = make_printer('Foo!')

printer()

支持将函数当成对象使用的编程语言,一般都支持闭包。比如Python, JavaScript。

我个人认为,闭包存在的意义就是它夹带了外部变量(私货),如果它不夹带私货,它和普通的函数就没有任何区别。同一个的函数夹带了不同的私货,就实现了不同的功能。其实你也可以这么理解,闭包和面向接口编程的概念很像,可以把闭包理解成轻量级的接口封装。

ef tag(tag_name):

    def add_tag(content):

        return "<{0}>{1}</{0}>".format(tag_name, content)

    return add_tag

content = 'Hello'

add_tag = tag('a')

print add_tag(content)

# <a>Hello</a>

add_tag = tag('b')

print add_tag(content)

# <b>Hello</b>

在这个例子里,我们想要一个给content加tag的功能,但是具体的tag_name是什么样子的要根据实际需求来定,对外部调用的接口已经确定,就是add_tag(content)。如果按照面向接口方式实现,我们会先把add_tag写成接口,指定其参数和返回类型,然后分别去实现a和b的add_tag。

但是在闭包的概念中,add_tag就是一个函数,它需要tag_name和content两个参数,只不过tag_name这个参数是打包带走的。所以一开始时就可以告诉我怎么打包,然后带走就行。

--------------------

《format函数》

https://www.cnblogs.com/chunlaipiupiupiu/p/7978669.html

python中format函数用于字符串的格式化

通过关键字

1 print('{名字}今天{动作}'.format(名字='陈某某',动作='拍视频'))#通过关键字

2 grade = {'name' : '陈某某', 'fenshu': '59'}

3 print('{name}电工考了{fenshu}'.format(**grade))#通过关键字,可用字典当关键字传入值时,在字典前加**即可

通过位置

1 print('{1}今天{0}'.format('拍视频','陈某某'))#通过位置

2 print('{0}今天{1}'.format('陈某某','拍视频'))

填充和对齐^<>分别表示居中、左对齐、右对齐,后面带宽度

1 print('{:^14}'.format('陈某某'))

2 print('{:>14}'.format('陈某某'))

3 print('{:<14}'.format('陈某某'))

4 print('{:*<14}'.format('陈某某'))

5 print('{:&>14}'.format('陈某某'))#填充和对齐^<>分别表示居中、左对齐、右对齐,后面带宽度

精度和类型f精度常和f一起使用

1 print('{:.1f}'.format(4.234324525254))

2 print('{:.4f}'.format(4.1))

进制转化,b o d x 分别表示二、八、十、十六进制

print('{:b}'.format(250))

print('{:o}'.format(250))

print('{:d}'.format(250))

print('{:x}'.format(250))

千分位分隔符,这种情况只针对与数字

print('{:,}'.format(100000000))

print('{:,}'.format(235445.234235))

--------------------

《案例》

[]

http://blog.sina.com.cn/s/blog_6fe87f870101d9cm.html

'@'符号用作函数修饰符必须出现在函数定义前一行,不允许和函数定义在同一行。也就是说@A def f(): 是非法的。 只可以在模块或类定义层内对函数进行修饰。一个修饰符就是一个函数,它将被修饰的函数做为参数,并返回修饰后的同名函数或其它可调用的东西。

下面不懂:

###################################

def spamrun(fn):

    def sayspam(*args):

        print "spam,spam,spam"

    return sayspam

@spamrun

def useful(a,b):

    print a**2+b**2


useful(3,4)

###################################

D:\Users\wangjiangtao517>python D:\wangjt\zsq.py

spam,spam,spam

###################################

def spamrun(fn):

    def sayspam(*args):

        print "spam,spam,spam"

    return sayspam

#@spamrun

def useful(a,b):

    print a**2+b**2


useful(3,4)

###################################

D:\Users\wangjiangtao517>python D:\wangjt\zsq.py

25

###################################

def spamrun(fn):

    def sayspam(*args):

        print "spam,spam,spam"

    #return sayspam

#@spamrun

def useful(a,b):

    print a**2+b**2


useful(3,4)

###################################

D:\Users\wangjiangtao517>python D:\wangjt\zsq.py

Traceback (most recent call last):

  File "D:\wangjt\zsq.py", line 10, in <module>

    useful(3,4)

TypeError: 'NoneType' object is not callable

实例

def decorator(fn):

    def test(*args):

        print "My god!"*3

        return fn(*args)

    return test

@decorator

def other(a,b):

    print a**2+b**2

if __name__=="__main__":

    other(4,3)

    other(3,4)


结果:

My god!My god!My god!

25

My god!My god!My god!

25

注释掉//print return fn(*args)

结果是:

My god!My god!My god!

My god!My god!My god!

要想使other函数能正常运行,必须加返回值,@decorator是一个statement,会将other函数当作参数传入来执行test方法

------------------

《主线程、子线程主线程、子线程》

用装饰器实现子线程执行10分钟还没返回被主线程kill掉?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容