- 💡 函数就是面向过程的程序设计的基本单元,函数式编程就是一种抽象程度很高的编程范式
- 纯粹的函数式编程语言编写的函数没有变量,输入是确定的输出就是确定的
-
高阶函数
函数名其实就是指向函数的变量,变量可以指向函数,函数的参数能接收便来金
-
map/reduce
map
map()
函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回map()
作为高阶函数,事实上把运算规则抽象了,可以计算任意复杂的函数def f(x):
return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
list(r) #[1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce
reduce()
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素做累积计算reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
filter
filter()
也接收一个函数和一个序列,把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃- 注意到
filter()
函数返回的也是一个Iterator
,也就是一个惰性序列,所以只有在取filter()
结果的时候,才会真正筛选并返回下一个筛出的元素,需要用list()
函数获得所有结果并返回list ```python def is_odd(n): return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
结果: [1, 5, 9, 15]
<a name="bHtOm"></a>
#### sorted
- `sorted()`可以对list进行排序,是一个高阶函数,可以接收一个`key`函数来实现自定义的排序,第三个参数是`reverse=True`
<a name="M5otG"></a>
### 返回函数
```python
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
- 在函数
lazy_sum
中又定义了函数sum
,并且sum
可以引用外部函数的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)” - 每次调用都会返回一个新函数,即使传入相同的参数,用
==
判断则返回False
```python def count(): fs = [] for i in range(1, 4):
return fsdef f():
return i*i
fs.append(f)
f1, f2, f3 = count() f1() #9 f2() #9 f3() #9
def count(): def f(j): def g(): return j*j return g fs = [] for i in range(1, 4): fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f() return fs f1() #1 f2() #4 f3() #9
- 💡 返回闭包时要牢记,返回函数不要引用任何循环变量,或者后续会发生变化的变量。如果一定要引用,则**再创建一个函数并用该函数的参数绑定循环变量当前的值**
- 💡 使用闭包时,对外层变量赋值前,需要先使用`nonlocal`声明该变量不是当前函数的局部变量
```python
def createCounter():
x = 0
def counter():
nonlocal x
x = x + 1
return x
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('测试失败!')
匿名函数
匿名函数
lambda x: x * x
,冒号前面的x表示函数参数,只能有一个表达式,不用写return
。因为函数没有名字,不必担心函数名冲突装饰器
在代码运行期间动态增加功能的方式称之为“装饰器”,本质上,
decorator
就是一个返回函数的高阶函数- 如果
decorator
本身需要传入参数,那就需要编写一个返回decorator
的高阶函数 ```python import functools def log(text): def decorator(func):
return decorator@functools.wraps(func) #将func的函数名绑定为wrapper函数名
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
@log(‘execute’) def now(): print(‘2015-3-25’)
相当于
now = log(‘execute’)(now)
<a name="RpBGY"></a>
### 偏函数
- `functools.partial`的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单
- 创建偏函数时,实际上可以接收函数对象、`*args`和`**kw`这三个参数
```python
int2 = functools.partial(int, base=2)
int2('10010')
#相当于
kw = { 'base': 2 }
int('10010', **kw)