函数式编程

高阶函数

  1. 变量可以指向函数

    print(abs(-10)) # 10
    abs_func=abs
    print(abs_func(-10)) # 10
  2. 函数名也是变量
    例如 abs就是一个指向获取绝对值的函数,我们可以试着将abs指向其它对象,这时abs也就无法完成获取绝对值

  3. 传入参数
    函数可以接收另外一个函数作为参数

    def my_funcparam_func(x, y, f):
       return f(x)+f(y)
    print(my_funcparam_func(10,-10,abs)) #20

map/reduce

  1. map用法
    map将传入的参数依次作用域每个元素,将结果作为Iterator返回

    r1=map(my_func_xx,[1,2,3,4,5])
    list1=list(r1) #因为返回的时Iterator惰性序列,使用list将整个序列计算返回list
    print(list1) # [1, 4, 9, 16, 25]
  2. reduce用法
    reduce把一个函数作用在一个序列上,这个函数接收两个参数,将结果继续和下一个元素做累计运算

    from functools import reduce
    def my_func_add(x, y):
    return x+y
    list2=reduce(my_func_add,[1,2,3,4])
    print(list2) #10

    filter

filter将传入函数依次作用于每个元素,然后根据返回值为True或者False,决定保留或者丢弃该元素

    def my_is_odd(x):
        return x%2==0
    #返回的还是Iterator的惰性序列
    list3=list(filter(my_is_odd, [1,2,4,5,6]))
    print(list3)  #[2, 4, 6]

排序

sorted函数

list4=[1, 2,-4,0,-3]
#直接用sorted函数排序
sorted(list4) # [-4, -3, 0, 1, 2]
sorted(['bob', 'about', 'Zoo', 'Credit']) #['Credit', 'Zoo', 'about', 'bob']
#用关键字排序
sorted(list4, key=abs) #[0, 1, 2, -3, -4]
#反向排序 
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)

默认对字符串的排序,按照ASCII码大小比较,
key指定的函数作用域list的每个元素.并根据返回结果进行排序

返回函数

函数作为结果值进行返回

def my_lazy_sum(*args):
    def my_sum():
        sum=0
        for x in args:
            sum+=x
        return sum
    return my_sum

my_f=my_lazy_sum(1,2,3,4)
my_f() #10

在函数内部又定义了函数,内部函数可以引用外部函数的参数和局部变量,当外部函数返回内部函数时,参数和变量都保存在返回的函数中,这就是闭包

闭包

注意:返回的函数并不会立即执行,而是直到调用才执行,因此函数内用到的变量是执行时的变量值,为了避免:返回函数时,不要饮用任何循环变量或后续会变化的变量

匿名函数

lambda关键字表示匿名函数,冒号前为函数参数
匿名函数也可以作为返回值

my_f2=lambda x: x*x
print(my_f2(2)) #4

装饰器

函数有__name__属性,可以拿到函数的名字

def my_func_now(x):
    return x*3

name=my_func_now.__name__
print(name) #my_func_now

定义一个装饰器decorator

def my_custom_decorator(func):
    def my_wrapper(*args, **kw):
        print("call %s()"%func.__name__)
        return func(*args, **kw)
    return my_wrapper

用装饰器装饰一个函数

@my_custom_decorator #相当于执行了my_log=my_custom_decorator(my_log)
def my_log():
    print("my_log_func")

my_log() 
#call my_log()
# my_log_func

在执行my_log函数不仅会执行函数本身,还会运行装饰器的my_wrapper函数

decorator还可以传入参数,就需要更复杂的3层嵌套

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator
    
@log('execute') #3层嵌套相当于:  now = log('execute')(now)
def now():
    print('2015-3-25')
#execute now():
#2015-3-25

当需要在装饰器中获取到真正执行的函数名称时,我们可以使用Python内置的functools.wraps

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__) #此时获取到的name为装饰的函数名称,而不是wrapper
        return func(*args, **kw)
    return wrapper

偏函数

使用functools.partial将函数的某些参数固定住(设置默认值),返回一个新的函数

import functools

int2=functools.partial(int, base=2)
print(int2("100"))  #4

实际functools.partial接受三个参数:函数对象、*args**kw,会将*args参数部分自动加到函数对象的左边,而将**kw一部分自动加到右边