• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >python > Python装饰器的函数式编程详解

Python装饰器的函数式编程详解

作者:hebedich 字体:[增加 减小] 来源:互联网

hebedich 通过本文主要向大家介绍了python函数式编程,函数式编程,函数式编程语言,javascript函数式编程,js函数式编程等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西。虽然好像,他们要干的事都很相似——都是想要对一个已有的模块做一些“修饰工作”,所谓修饰工作就是想给现有的模块加上一些小装饰(一些小功能,这些小功能可能好多模块都会用到),但又不让这个小装饰(小功能)侵入到原有的模块中的代码里去。但是OO的Decorator简直就是一场恶梦,不信你就去看看wikipedia上的词条(Decorator Pattern)里的UML图和那些代码,这就是我在《 从面向对象的设计模式看软件设计》“餐后甜点”一节中说的,OO鼓励了——“厚重地胶合和复杂层次”,也是《 如此理解面向对象编程》中所说的“OO的狂热者们非常害怕处理数据”,Decorator Pattern搞出来的代码简直就是OO的反面教程。

Python 的 Decorator在使用上和Java/C#的Annotation很相似,就是在方法名前面加一个@XXX注解来为这个方法装饰一些东西。但是,Java/C#的Annotation也很让人望而却步,太TMD的复杂了,你要玩它,你需要了解一堆Annotation的类库文档,让人感觉就是在学另外一门语言。

而Python使用了一种相对于Decorator Pattern和Annotation来说非常优雅的方法,这种方法不需要你去掌握什么复杂的OO模型或是Annotation的各种类库规定,完全就是语言层面的玩法:一种函数式编程的技巧。如果你看过本站的《函数式编程》,你一定会为函数式编程的那种“描述你想干什么,而不是描述你要怎么去实现”的编程方式感到畅快。(如果你不了解函数式编程,那在读本文之前,还请你移步去看看《函数式编程》) 好了,我们先来点感性认识,看一个Python修饰器的Hello World的代码。

Hello World

下面是代码:

文件名:hello.py

def hello(fn):
    def wrapper():
        print "hello, %s" % fn.__name__
        fn()
        print "goodby, %s" % fn.__name__
    return wrapper
@hello
def foo():
    print "i am foo"
foo()
</div>

当你运行代码,你会看到如下输出:

[chenaho@chenhao-air]$ python hello.py
hello, foo
i am foo
goodby, foo
</div>

你可以看到如下的东西:

1)函数foo前面有个@hello的“注解”,hello就是我们前面定义的函数hello

2)在hello函数中,其需要一个fn的参数(这就用来做回调的函数)

3)hello函数中返回了一个inner函数wrapper,这个wrapper函数回调了传进来的fn,并在回调前后加了两条语句。

Decorator 的本质
对于Python的这个@注解语法糖- Syntactic Sugar 来说,当你在用某个@decorator来修饰某个函数func时,如下所示:

@decorator
def func():
    pass
</div>

其解释器会解释成下面这样的语句:

func = decorator(func)
</div>

尼玛,这不就是把一个函数当参数传到另一个函数中,然后再回调吗?是的,但是,我们需要注意,那里还有一个赋值语句,把decorator这个函数的返回值赋值回了原来的func。 根据《函数式编程》中的first class functions中的定义的,你可以把函数当成变量来使用,所以,decorator必需得返回了一个函数出来给func,这就是所谓的higher order function 高阶函数,不然,后面当func()调用的时候就会出错。 就我们上面那个hello.py里的例子来说,

@hello
def foo():
    print "i am foo"
</div>

被解释成了:

foo = hello(foo)
</div>

是的,这是一条语句,而且还被执行了。你如果不信的话,你可以写这样的程序来试试看:

def fuck(fn):
    print "fuck %s!" % fn.__name__[::-1].upper()
@fuck
def wfg():
    pass
</div>

没了,就上面这段代码,没有调用wfg()的语句,你会发现, fuck函数被调用了,而且还很NB地输出了我们每个人的心声!

再回到我们hello.py的那个例子,我们可以看到,hello(foo)返回了wrapper()函数,所以,foo其实变成了wrapper的一个变量,而后面的foo()执行其实变成了wrapper()。

知道这点本质,当你看到有多个decorator或是带参数的decorator,你也就不会害怕了。

比如:多个decorator

@decorator_one
@decorator_two
def func():
    pass
</div>

相当于:

func = decorator_one(decorator_two(func))
</div>

比如:带参数的decorator:

@decorator(arg1, arg2)
def func():
    pass
</div>

相当于:

func = decorator(arg1,arg2)(func)
</div>

这意味着decorator(arg1, arg2)这个函数需要返回一个“真正的decorator”。

带参数及多个Decrorator
我们来看一个有点意义的例子:

html.py

def makeHtmlTag(tag, *args, **kwds):
    def real_decorator(fn):
        css_class = " class='{0}'".format(kwds["css_class"]) \
                                     if "css_class" in kwds else ""
        def wrapped(*args, **kwds):
            return "<"+tag+css_class+">" + fn(*args, **kwds) + "</"+tag+">"
        return wrapped
 &nbs

您可能想查找下面的文章:

  • 总结Python编程中函数的使用要点
  • Python函数式编程指南(四):生成器详解
  • Python函数式编程指南(三):迭代器详解
  • Python函数式编程指南(二):从函数开始
  • Python函数式编程指南(一):函数式编程概述
  • 利用Fn.py库在Python中进行函数式编程
  • 用Python进行基础的函数式编程的教程
  • Python装饰器的函数式编程详解

相关文章

  • python3简单实现微信爬虫
  • Python中is与==判断的区别
  • Python读取图片属性信息的实现方法
  • python下如何让web元素的生成更简单的分析
  • 独特的python循环语句
  • 在Python中使用列表生成式的教程
  • python操作sqlite的CRUD实例分析
  • 操作Windows注册表的简单的Python程序制作教程
  • Python爬虫代理IP池实现方法
  • 整理Python中的赋值运算符

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • tensorflow estimator 使用hook实现finetune方式
    • python optparse模块使用实例
    • 巧用Python装饰器 免去调用父类构造函数的麻烦
    • Python Matplotlib库入门指南
    • Python标准库之sqlite3使用实例
    • 分享一个常用的Python模拟登陆类
    • python通过urllib2爬网页上种子下载示例
    • Ubuntu 16.04 LTS中源码安装Python 3.6.0的方法教程
    • Python编程实现输入某年某月某日计算出这一天是该年第几天的方法
    • Python警察与小偷的实现之一客户端与服务端通信实例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有