python 函数式编程包_Python 函数式编程 闭包

AstralWind 的博客上有对函数式编程很好地讲解,一下做一些节选

1.1. 什么是函数式编程?

函数式编程使用一系列的函数解决问题。函数仅接受输入并产生输出,不包含任何能影响产生输出的内部状态。任何情况下,使用相同的参数调用函数始终能产生同样的结果。

在一个函数式的程序中,输入的数据“流过”一系列的函数,每一个函数根据它的输入产生输出。函数式风格避免编写有“边界效应”(side effects)的函数:修改内部状态,或者是其他无法反应在输出上的变化。完全没有边界效应的函数被称为“纯函数式的”(purely functional)。避免边界效应意味着不使用在程序运行时可变的数据结构,输出只依赖于输入。

可以认为函数式编程刚好站在了面向对象编程的对立面。对象通常包含内部状态(字段),和许多能修改这些状态的函数,程序则由不断修改状态构成;函数式编程则极力避免状态改动,并通过在函数间传递数据流进行工作。但这并不是说无法同时使用函数式编程和面向对象编程,事实上,复杂的系统一般会采用面向对象技术建模,但混合使用函数式风格还能让你额外享受函数式风格的优点。

1.2. 为什么使用函数式编程?

函数式的风格通常被认为有如下优点:

逻辑可证

模块化      函数式编程推崇简单原则,一个函数只做一件事情,将大的功能拆分成尽可能小的模块。小的函数更易于阅读和检查错误。

组件化      小的函数更容易加以组合形成新的功能。

易于调试   细化的、定义清晰的函数使得调试更加简单。当程序不正常运行时,每一个函数都是检查数据是否正确的接口,能更快速地排除没有问题的代码,定位到出现问题的地方。

易于测试    不依赖于系统状态的函数无须在测试前构造测试桩,使得编写单元测试更加容易。

更高的生产率   函数式编程产生的代码比其他技术更少(往往是其他技术的一半左右),并且更容易阅读和维护。

1.3. 如何辨认函数式风格?

支持函数式编程的语言通常具有如下特征,大量使用这些特征的代码即可被认为是函数式的:

函数是一等公民   函数能作为参数传递,或者是作为返回值返回。

匿名函数(lambda)  lambda表达式定义一个匿名的函数,如果这个函数仅在编码的位置使用到,你可以现场定义、直接使用:

lst.sort(lambda o1, o2: o1.compareTo(o2))

封装控制结构的内置模板函数

在Python里,过滤由一个名为filter的内置函数实现。有了这个函数,解释器就学会了如何“过滤”,而我们只需要把规则告诉它:

lst2 = filter(lambda n: n > 0, lst)

这个函数带来的好处不仅仅是少写了几行代码这么简单。

封装控制结构后,代码中就只需要描述功能而不是做法,这样的代码更清晰,更可读。因为避开了控制结构的干扰,第二段代码显然能让你更容易了解它的意图。

另外,因为避开了索引,使得代码中不太可能触发下标越界这种异常,除非你手动制造一个。

函数式编程语言通常封装了数个类似“过滤”这样的常见动作作为模板函数。唯一的缺点是这些函数需要少量的学习成本,但这绝对不能掩盖使用它们带来的好处。

部分内建函数介绍

1.reduce(function, iterable[, initializer])

1 defreduce_(function, lst, initial):2 result =initial3 for num inlst:4 result =function(result, num)5 return result

它的第二个参数可以是任何可迭代的对象(实现了__iter__()方法的对象);

如果不指定第三个参数,则第一次调用function将使用iterable的前两个元素作为参数。

由reduce和一些常见的function组合成了下面列出来的内置函数:

all(iterable) == reduce(lambda x, y: bool(x andy), iterable)

any(iterable)== reduce(lambda x, y: bool(x ory), iterable)

max(iterable[, args...][, key])== reduce(lambda x, y: x if key(x) > key(y) elsey, iterable_and_args)

min(iterable[, args...][, key])== reduce(lambda x, y: x if key(x) < key(y) elsey, iterable_and_args)

sum(iterable[, start])== reduce(lambda x, y: x + y, iterable, start)

2.map(function, iterable, ...)

defmap_(function, lst):

result=[]for item inlst:

result.append(function(item))return result

map还可以接受多个iterable作为参数,在第n次调用function时,将使用iterable1[n], iterable2[n], ...作为参数。

3.filter(function, iterable)

这个函数的功能是过滤出iterable中所有以元素自身作为参数调用function时返回True或bool(返回值)为True的元素并以列表返回

4.zip(iterable1, iterable2, ...)

这个函数返回一个列表,每个元素都是一个元组,包含(iterable1[n], iterable2[n], ...)。

例如:zip([1, 2], [3, 4]) --> [(1, 3), (2, 4)]

如果参数的长度不一致,将在最短的序列结束时结束;如果不提供参数,将返回空列表。

闭包(closure)

闭包是绑定了外部作用域的变量(但不是全局变量)的函数。大部分情况下外部作用域指的是外部函数。

闭包包含了自身函数体和所需外部函数中的“变量名的引用”。引用变量名意味着绑定的是变量名,而不是变量实际指向的对象;如果给变量重新赋值,闭包中能访问到的将是新的值。

闭包使函数更加灵活和强大。即使程序运行至离开外部函数,如果闭包仍然可见,则被绑定的变量仍然有效;每次运行至外部函数,都会重新创建闭包,绑定的变量是不同的,不需要担心在旧的闭包中绑定的变量会被新的值覆盖。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值