[TOC]
学 python3 也有一段时间了,关于函数式编程也看了很多遍,总是记不住,大概因为平时也忘记用。
整理了网上部分教程。
因为是针对Python写的,直接偷懒参考了廖雪峰老师的分类方法。
主要通过实例来直观地呈现
函数式编程
函数式编程主要用了映射的思维,思维方式区别于面对对象编程(OOP属于一种过程式编程)
从名字上大概可以体会到,编程过程中更多会考虑到映射关系,方便了编写。
高阶函数
函数本身可以赋值给变量,操作有:传入,赋值,返回值等等
map/reduce
与其他语言类似,map 表示映射的关系。
map 的返回值是 map 类型
def f(x):
return x+1
lst=list(map(f,[1,2,3,4,5]))
# lst is [2,3,4,5,6]
reduce 用于累积计算。有点像累加器
def f(x,y):
return x+y
x=reduce(f,[1,2,3,4])
# x is 10
第一个函数一定要接收两个参数。
filter
英文即为过滤器
和map用法几乎一样,作用于每个元素,但他实现的是保留或筛选的过滤功能
用法如筛奇数:
def check(n):
return n%2
x=filter(check,[1,2,3,4])
# x is [1,3]
sorted
很好理解,就像 c++ 的 sort 一样,关键在于实现 cmp 一样的 key 函数
reverse 函数 True 为从大到小,False 为从小到大。
key 函数作用于每个元素。
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
返回函数
函数可以作为返回值
def calc_sum(*args):
ax = 0
for n in args:
ax = ax + n
return ax
f=calc_sum([1,2,3])
f()
# f为函数
# f()才为 6
简单地理解就是增加了一个返回函数的功能。
闭包
谈谈自己的理解:Python中的闭包 闭包的实质
闭包用面向对象的思想中封装的思想去理解,还涉及到全局变量和局部变量的关系
从这两点去理解闭包就不难,但是不好写。
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
f1(),f2(),f3() # 9,9,9
上面的代码中之所以不是 1 4 9 是因为
返回的函数并没有立刻执行,而是直到调用了f()才执行
当调用f()时,变量i已经被修改为3了
用闭包返回一个计数器函数,每次调用它返回递增整数:
def createCounter():
x=[0]
def counter():
x[0]+=1
return x[0]
return counter
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
counterB = createCounter()
if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:
print('测试通过!')
else:
print('测试失败!')
x 不能赋值为0,否则会报错:
local variable 'x' referenced before assignment
意思是 x 在 createCounter 这个函数内是一个局部变量, counter 函数内的 x 又是新开的局部变量,所以显示第二个没有声明。
而 list 是可以这样子对里面元素进行操作的。
匿名函数
就是 lambda 用法,一个实例就可以学会了
L=list(filter(lambda x: x % 2,[1,2,3,4,5]))
装饰器
[译] 12步轻松搞定python装饰器
装饰器属于闭包的应用
看一段代码
>>> 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 就是一个装饰器,decorated 是 foo 经过 outer 装饰器“加强”后的新函数
和上面讲到的闭包其实没差别,区别在于现在传递的参数是一个函数,而不是普通变量。因此取名“装饰器”,用于装饰函数。
foo=outer(foo)
意思就是本身经过装饰,上面的用法可以用@
标识符来应用,等价于:
def outer():
//todo...
@outer
def foo():
//todo...
写到这里突然想起来Java
里面的的@Override
重写方法,也就很好理解了。
偏函数
偏函数平时看到比较少,在模块functools.partial
中。
简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数
,调用这个新函数会更简单。
例子用到了 int
,max
的偏函数使用方法。
# 二进制转十进制
int2 = functools.partial(int, base=2)
# 多个数取 max
max2 = functools.partial(max, 10)
max2(5, 6, 7)
# 等价于下面
args = (10, 5, 6, 7)
max(*args)
# answer is 10