本文以 Python 2.7 为基础。

lambda 函数实现递归

方法一:传递一个 self 参数

求阶乘:

  1. frac = lambda self, x: self(self, x - 1) * x if x > 1 else 1
  2. print frac(frac, 4)

方法二(匿名函数实现递归):将一个完整的 lambda 函数体作为参数

求最大公因数:

  1. (lambda a, b, s = lambda a, b, f: f(b, a % b, f) if b else a: s(a, b, s))(3, 5)

由此可以用一行代码求多个数的最小公倍数:

  1. (lambda *args: reduce(lambda a, b: a * b / (lambda a, b, s = lambda a, b, f: f(b, a % b, f) if b else a: s(a, b, s))(a, b), args))(2, 3, 4)

Decorator

Decorator,修饰器,顾名思义就是对函数进行「修饰」(即添加一些功能)的语法糖。一个简单的例子如下:

  1. def transform(func):
  2. print 'Hello, '
  3. return func
  4.  
  5. @transform
  6. def world():
  7. print 'World!'
  8.  
  9. world()

通过在 world 函数的定义之前添加一句 @transform 完成 transform 函数对 world 函数的修饰,上面这段程序的运行结果是输出 'Hello, World!'

事实上,@transform 一句被解释为 world = transform(world),从中可以看出:

1. transform 函数的返回值应该是一个函数;

2. 在 @transform 时 transform 函数被执行了一次;

3. world 函数将会成为一个新的函数的实例(尽管在这个例子中它还是它本身)。

那么对上面的代码的实质有了一些解释:

1. 'Hello, '这部分实际上在 world 函数定义完成时输出,所以即使不调用 world 函数也会输出 'Hello, ' 这部分;

2. 'World!'这部分在调用 world 函数时输出;

3. 由于 world 函数本身的内容并没有发生变化,所以如果第二次调用 world,将只是输出 'World!'。

接下来看被修饰的函数被替换为新的函数实例的情况:

  1. def transform(func):
  2. def inside():
  3. print 'Hello,',
  4. func()
  5. return inside
  6.  
  7. @transform
  8. def world():
  9. print 'World!'
  10.  
  11. world()

对这段代码的解释:

1. 由于 transform 函数内部只是定义了另外一个函数而没有执行其他实际(输出)操作,所以 @transform 一句执行时并没有任何输出;

2. world 函数在 @transform 一句执行之后内容被替换为了 inside 函数的内容,而 inside 函数实际上执行了两部分内容:第一步是输出 'Hello, ',第二步是执行原来的 world 函数的内容,即输出 'World!'。所以新的 world 函数实际上也也是执行了这样两个输出;

3. 由于 world 函数的实际内容已经发生变化,所以如果第二次执行 world 函数输出的也是 'Hello, World!'。

Decorator 的好处:

「将函数的约束放置于接口处,使意图更加明了,同时又不增加调用者的负担。」(引用自http://blog.csdn.net/thy38/article/details/4471421  Python Decorator 的带参数用法也请参考此文。)


2017年8月3日更新:

带参数的 decorator:

  1. def wrapper(arg):
  2. def decorator(func):
    print arg
  3. return func
  4. return decorator
  5.  
  6. @wrapper("hello ")
    def func():
    print "world"

Multiple decorators apply in nested fashion, for example:

  1. @f1(arg)
  2. @f2
  3. def func(): pass

is roughly equivalent to

  1. def func(): pass
  2. func = f1(arg)(f2(func))

实际应用

Flask 中的 Flask.route()

  1. def route(self, rule, **options):
  2. def decorator(f):
  3. endpoint = options.pop('endpoint', None)
  4. self.add_url_rule(rule, endpoint, f, **options)
  5. return f
  6. return decorator

形如 @app.route 这样的写法实际上只是调用了 add_url_rule 方法。

实现 Multimethod

http://www.artima.com/weblogs/viewpost.jsp?thread=101605

本质

Decorator 的本质是 higher-order function call 的语法糖,其本身并没有什么强大之处, 只不过为函数变换提供了直观简单的语法结构。

[持续更新]Python 笔记的更多相关文章

  1. [持续更新] Python学习、使用过程中遇见的非代码层面知识(想不到更好的标题了 T_T)

    写在前面: 这篇博文记录的不是python代码.数据结构.算法相关的内容,而是在学习.使用过程中遇见的一些没有技术含量,但有时很令人抓耳挠腮的小东西.比如:python内置库怎么看.python搜索模 ...

  2. web开发工具flask中文英文书籍-持续更新

    web开发工具flask中文英文书籍-持续更新 python测试开发_AI命理关注 0.9222018.11.10 07:48:43字数 625阅读 885 python测试开发项目实战-目录 pyt ...

  3. python3.4学习笔记(六) 常用快捷键使用技巧,持续更新

    python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...

  4. BLE资料应用笔记 -- 持续更新

    BLE资料应用笔记 -- 持续更新 BLE 应用笔记 小书匠 简而言之,蓝牙无处不在,易于使用,低耗能和低使用成本.'让我们'更深入地探索这些方面吧. 蓝牙无处不在-,您可以在几乎每一台电话.笔记本电 ...

  5. Python开发【第二十三篇】:持续更新中...

    Python开发[第二十三篇]:持续更新中...

  6. 状压dp(状态压缩&&dp结合)学习笔记(持续更新)

    嗯,作为一只蒟蒻,今天再次学习了状压dp(学习借鉴的博客) 但是,依旧懵逼·································· 这篇学习笔记是我个人对于状压dp的理解,如果有什么不对的 ...

  7. 好用的函数,assert,random.sample,seaborn tsplot, tensorflow.python.platform flags 等,持续更新

    python 中好用的函数,random.sample等,持续更新 random.sample random.sample的函数原型为:random.sample(sequence, k),从指定序列 ...

  8. Python奇技淫巧 - 持续更新中....

    Python奇技淫巧 人生苦短,我用Python: 编程界这绝对不是一句空话,尤其是对于使用过多个语言进行工作的同学们来说,用Python的时间越长,越有一种我早干嘛去了的想法,没事,啥时候用Pyth ...

  9. LeetCode 题目的 Python 实现(持续更新中)

    Python-LeetCode 是一个使用 Python 语言解决 LeetCode 问题的代码库,库有以下几个方面需要注意: 所有题目都是 AC 的: 按照题目顺序,每 50 个放在一个目录下,方便 ...

随机推荐

  1. 第四篇:Spark SQL Catalyst源码分析之TreeNode Library

    /** Spark SQL源码分析系列文章*/ 前几篇文章介绍了Spark SQL的Catalyst的核心运行流程.SqlParser,和Analyzer,本来打算直接写Optimizer的,但是发现 ...

  2. oracle快速创建主键

    oracle中,有时我们会发现有一些表中,一些记录它们每个字段的数据 都是一样一样的,即重复数据,这种数据的不存在肯定是不对了. 究其原因,就是该表没有主键,给一个表创建主键,非常容易: alter ...

  3. .net 获取浏览器Cookie(包括HttpOnly)

    网上好不容易找到的,分享+收藏 一.接口文件 using System; using System.ComponentModel; using System.Net; using System.Run ...

  4. tp5.1升级

    # php think version v5.1.23 # composer update Loading composer repositories with package information ...

  5. iOS中的二维数组

    首先我们知道OC中是没有二维数组的,二维数组是通过一位数组的嵌套实现的,但是别忘了我们有字面量,实际上可以和C/C++类似的简洁地创建和使用二维数组.这里总结了创建二维数组的两种方法以及数组的访问方式 ...

  6. ajax实现用户注册

    需求分析 页面中给出注册表单: 在username input标签中绑定onblur事件处理函数. 当input标签失去焦点后获取 username表单字段的值,向服务端发送AJAX请求: djang ...

  7. MYSQL freedata 外联接

    主要是解决,不同生产系统里面,有不同的数据库. SQL 又不能夸系统查询表. 只能在一个系统里,可以跨不同的数据库查表. 所以会用映射 .FREEDATA 这种方式,这样A 系统 里的表更新之后,就可 ...

  8. C++复习13.虚析构函数知识

    C++ 虚析构函数 20131010 在C++中的虚函数作用是实现基于继承机制的多态,但是我们好像忽略了一种情况,就是虚析构函数.在C++继承机制中,虽然构造函数是不可以使用虚函数声明,但是析构函数是 ...

  9. MySQL + KeepAlived + LVS 单点写入主主同步高可用架构实验

    分类: MySQL 架构设计 2013-05-08 01:40 5361人阅读 评论(8) 收藏 举报 mysql 高可用 keepalive ㈠ 实战环境 服务器名· IP OS MySQL odd ...

  10. LeetCode OJ:Palindrome Partitioning(回文排列)

    Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...