# Python函数式编程

python中万物皆对象，因此可以像处理平常变量一样方便的处理函数对象。下面介绍一些常用的基于python的函数式编程api。

## 1.偏函数

偏函数的作用是给函数的参数指定默认参数。

```python
import functools
int('12345', base=8)
>>> 5349
int2 = functools.partial(int, base=2)
int2('1000000')
>>> 64
```

简单总结`functools.partial`的作用就是，把一个函数的某些参数给固定住（也就是设置默认值），返回一个新的函数，调用这个新函数会更简单。上面的int2函数就是将base置为2的int函数。

最后，需要说明的是创建偏函数时，实际上可以接收函数对象、`*args`和`**kw`这3个参数，当传入： `max2 = functools.partial(max, 10)` 然后调用： `max2(5, 6, 7)` 此时，10会作为`*args`的一部分加到左边，相当于

```python
args = (10, 5, 6, 7)
max(*args)
```

然后结果自然是10。而之前的base=2则是通过`**kw`传入的。

## 2.装饰器

装饰器的作用在于对已有函数进行封装，并添加一些额外的功能

```python
def inner(f):
    def wrapper(*args, **kwargs):
        rv = f(*args, **kwargs)
        print("tic toc!")
        return rv
    return wrapper
```

上面定义了一个inner装饰器，它构建一个函数对象wrapper，然后在里面实现了调用原始函数f后打印“tic toc!”的功能。

**分析一下这段代码的组成：**&#x20;

f是要被装饰的函数，wrapper是装饰器返回的函数。因此wrapper能够接受的参数必须包含被修饰函数f 所能够接受的参数。如果想要新增参数，只要对wrapper函数添加额外的参数即可。但是如果wrapper函数缺少f函数必须传入的参数，调用就会报错。 通过这样的方式，我们不光可以让f函数具备额外的功能，还可以使它可以接受更多的参数。

```python
def inner(f):
    def wrapper(a, b, c):
        print(c)
        return f(a, b)
    return wrapper

@inner
def f(a, b):
    print(a+b)
    return a+b

# 原始的f只能接受2个参数，被修饰后可以接受3个参数
f(1, 2, 10)
>>>10
>>>3
```

事实上，装饰器本身也可以传入参数：

```python
def ntimes(n):
  def inner(f):
    def wrapper(*args, **kwargs):
      for _ in range(n):
        rv = f(*args, **kwargs)
      return rv
    return wrapper
  return inner
```

上面的装饰器inner，接受函数f作为参数进行装饰，返回wrapper。而外围的ntimes接受传入的参数n控制函数的执行次数，起到修饰这个装饰器inner的作用。

```python
@ntimes(3)
def add(x, y):
  print(x + y)
  return x + y
```

输出的语句表明该代码确实执行了 3 次。
