Python函数式编程

缘来释你 2020-11-11 21:53:59
编程 Python 函数 博客园


Python函数式编程

函数是可重用的程序代码段,在Python中有常用的内置函数,例如len()、sum()等。 在Pyhon模块和程序中也可以自定义函数,使用函数可以提高编程效率

1. 函数式编程概述

1.1 什么是函数式编程?

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

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

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

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

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

  • 逻辑可证

这是一个学术上的优点:没有边界效应使得更容易从逻辑上证明程序是正确的(而不是通过测试)。

  • 模块化

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

  • 组件化

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

  • 易于调试

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

  • 易于测试

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

  • 更高的生产率

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

2. 函数式风格

2.1 迭代器(Iterator)

迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。

创建一个迭代器:

把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。
__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。
__next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。

示例:

创建一个返回数字的迭代器,初始值为 1,逐步递增 1:

2.2 生成器(generator)

在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。

示例:

使用 yield 实现斐波那契数列:

补充:yield 简述

yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始。带有 yield的函数不再是一个普通函数,而是一个生成器generator,可用于迭代。

yield好处:

1.不会将所有数据取出来存入内存中,而是返回了一个对象,可以通过对象获取数据,用多少取多少,可以节省内容空间。
2.除了能返回一个值,还不会终止循环的运行;

通过next()可以恢复Generator执行,直到下一个yield。send()可以传递yield的值,send()在一定意义上与 next()作用相似的,next()和send(None)作用是一样的。注意:生成器刚启动时(第一次调用),请使用next()语句或是send(None),不能直接发送一个非None的值,否则会报TypeError,因为没有yield语句来接收这个值。

示例:

 2.3 列表推导式(列表解析)和生成器表达式

列表解析(List comprehensions)

列表解析式是将一个可迭代对象(如列表)转换成另一个列表的工具。在转换过程中,可以指定元素必须符合某一条件,并按照指定的表达式进行转换,才能添加至新的列表中。

语法:
[expression for iter_var in iterable1]
[expression for iter_var2 in iterable2 ... for iter_varN in iterableN]
[expression for iter_var in iterable1 if condition]
执行:
迭代iterable中所有的元素,每一次迭代都把iterable中的内容放到iter_var对象中,然后把这个对象应用到表达式expression中,生成一个列表。

示例:

生成器表达式(Generator expressions)

不创建列表,只是返回一个生成器。这个生成器在每次计算出一个条目后,才把这个条目产生出来。所以在处理大量数据时更有优势。

语法:
(expression for iter_var in iterable1)
(expression for iter_var2 in iterable2 ... for iter_varN in iterableN)
(expression for iter_var in iterable1 if condition)
执行:
迭代iterable中所有的元素,每一次迭代都把iterable中的内容放到iter_var对象中,然后把这个对象应用到表达式expression中,生成一个生成器。

 2.4 装饰器

2.4.1 闭包

闭包的定义:

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

自由变量:

闭包所引用的外部作用域变量称为自由变量。闭包中的引用的自由变量只和具体的闭包有关联,闭包的每个实例引用的自由变量互不干扰。一个闭包实例对其自由变量的修改会被传递到下一次该闭包实例的调用。

闭包操作自由变量所需要的注意事项:

1.如果自由变量是可变对象(list,map...这里没有列出tuple是因为tuple是不可改变对象),那么闭包可以更新自由变量。

2.如果自由变量是不可变对象(数值,字符窜,tuple...),那么闭包不可以更新自由变量。

示例:

2.4.2 装饰器

装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景,装饰器是解决这类问题的绝佳设计。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码到装饰器中并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

简单装饰器示例:

定义了一个打印出方法名及其参数的装饰器

import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
return func(*args, **kwargs)
return wrapper

使用语法糖@调用装饰器

@log
def test(p):
print(test.__name__ + " param: " + p)
test("I'm a param")

输出:

call test():
args = I'm a param
test param: I'm a param

带参数的装饰器

携带了参数的装饰器将有三层函数,示例如下

import functools
def log_with_param(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('call %s():' % func.__name__)
print('args = {}'.format(*args))
print('log_param = {}'.format(text))
return func(*args, **kwargs)
return wrapper
return decorator
@log_with_param("param")
def test_with_param(p):
print(test_with_param.__name__)

输出:

call test_with_param():
args = I'm a param
log_param = param
test_with_param

 注:@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

2.5 偏函数

 

3. 高阶函数

3.1 高阶函数定义

python中如果将一个函数名传送给另一个函数作为形参,那么就成这个函数为高阶函数。

示例:

3.2 常用内置高阶函数

3.2.1 匿名函数

python 使用 lambda 来创建匿名函数。
• lambda只是一个表达式,函数体比def简单很多。
• lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
• lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
• 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
语法
lambda函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression

示例:

3.2.2 map

map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的 Iterator。

语法
map() 函数语法:
map(function, iterable, ...)
参数
function -- 函数
iterable -- 一个或多个序列
返回值
存放结果的迭代器

  示例:

3.2.3 reduce

reduce() 函数会对参数序列中元素进行累积。
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

语法
reduce() 函数语法:
reduce(function, iterable[, initializer])
参数
• function -- 函数,有两个参数
• iterable -- 可迭代对象
• initializer -- 可选,初始参数
返回值
返回函数计算结果

示例:

3.2.4 filter

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

语法
filter() 方法的语法:
filter(function, iterable)
参数
• function -- 判断函数。
• iterable -- 可迭代对象。
返回值
过滤后的迭代器

示例:

筛选出所有含字符串 “str” 的单词

3.2.5 sorted

sorted() 函数对所有可迭代的对象进行排序操作。

sort 与 sorted 区别:

sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。

list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

语法
sorted 语法:
sorted(iterable, cmp=None, key=None, reverse=False)
参数说明:
iterable -- 可迭代对象。
cmp -- 比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。
key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
返回值
返回重新排序的列表

示例:

3.2.6 zip

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的zip类型对象。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

语法
zip 语法:
zip([iterable, ...])
参数说明:
iterabl -- 一个或多个迭代器;
返回值
返回一个zip类型对象

示例:

3.3 高阶函数的组合使用

 

 

注:博客部分内容转载于 Python函数式编程指南(一):概述

版权声明
本文为[缘来释你]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/keh123000/p/13958632.html

  1. 利用Python爬虫获取招聘网站职位信息
  2. Using Python crawler to obtain job information of recruitment website
  3. Several highly rated Python libraries arrow, jsonpath, psutil and tenacity are recommended
  4. Python装饰器
  5. Python实现LDAP认证
  6. Python decorator
  7. Implementing LDAP authentication with Python
  8. Vscode configures Python development environment!
  9. In Python, how dare you say you can't log module? ️
  10. 我收藏的有关Python的电子书和资料
  11. python 中 lambda的一些tips
  12. python中字典的一些tips
  13. python 用生成器生成斐波那契数列
  14. python脚本转pyc踩了个坑。。。
  15. My collection of e-books and materials about Python
  16. Some tips of lambda in Python
  17. Some tips of dictionary in Python
  18. Using Python generator to generate Fibonacci sequence
  19. The conversion of Python script to PyC stepped on a pit...
  20. Python游戏开发,pygame模块,Python实现扫雷小游戏
  21. Python game development, pyGame module, python implementation of minesweeping games
  22. Python实用工具,email模块,Python实现邮件远程控制自己电脑
  23. Python utility, email module, python realizes mail remote control of its own computer
  24. 毫无头绪的自学Python,你可能连门槛都摸不到!【最佳学习路线】
  25. Python读取二进制文件代码方法解析
  26. Python字典的实现原理
  27. Without a clue, you may not even touch the threshold【 Best learning route]
  28. Parsing method of Python reading binary file code
  29. Implementation principle of Python dictionary
  30. You must know the function of pandas to parse JSON data - JSON_ normalize()
  31. Python实用案例,私人定制,Python自动化生成爱豆专属2021日历
  32. Python practical case, private customization, python automatic generation of Adu exclusive 2021 calendar
  33. 《Python实例》震惊了,用Python这么简单实现了聊天系统的脏话,广告检测
  34. "Python instance" was shocked and realized the dirty words and advertisement detection of the chat system in Python
  35. Convolutional neural network processing sequence for Python deep learning
  36. Python data structure and algorithm (1) -- enum type enum
  37. 超全大厂算法岗百问百答(推荐系统/机器学习/深度学习/C++/Spark/python)
  38. 【Python进阶】你真的明白NumPy中的ndarray吗?
  39. All questions and answers for algorithm posts of super large factories (recommended system / machine learning / deep learning / C + + / spark / Python)
  40. [advanced Python] do you really understand ndarray in numpy?
  41. 【Python进阶】Python进阶专栏栏主自述:不忘初心,砥砺前行
  42. [advanced Python] Python advanced column main readme: never forget the original intention and forge ahead
  43. python垃圾回收和缓存管理
  44. java调用Python程序
  45. java调用Python程序
  46. Python常用函数有哪些?Python基础入门课程
  47. Python garbage collection and cache management
  48. Java calling Python program
  49. Java calling Python program
  50. What functions are commonly used in Python? Introduction to Python Basics
  51. Python basic knowledge
  52. Anaconda5.2 安装 Python 库(MySQLdb)的方法
  53. Python实现对脑电数据情绪分析
  54. Anaconda 5.2 method of installing Python Library (mysqldb)
  55. Python implements emotion analysis of EEG data
  56. Master some advanced usage of Python in 30 seconds, which makes others envy it
  57. python爬取百度图片并对图片做一系列处理
  58. Python crawls Baidu pictures and does a series of processing on them
  59. python链接mysql数据库
  60. Python link MySQL database