廖雪峰python学习笔记——函数式编程

廖雪峰python学习笔记——函数式编程

  1. 变量可以指向函数
a=abs
a(-2)
#输出2
  1. 高级函数就是一个可以把一个函数当成参数的函数
def add(x,y,f):
    return f(x)+f(y)
add(-3,-5,abs)
#输出8

map函数

map()是Python内置的高阶函数,它接收一个f和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。

reduce函数

reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。感觉这个函数比较难以理解,并且作用不大。
reduce(函数名,链表[,第一个默认值])

filter函数

filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。

#删除None和空字符串
def is_not_empty(s):
    return s and len(s.strip()) > 0
filter(is_not_empty, ['test', None, '', 'str', '  ', 'END'])

str.strip()就是trim方法。

sorted排序

sorted函数可以对list进行排序

sorted([26,5,12])

当然,sorted函数也可以接收一个比较函数来实现自定义排序。

def reversed_cmp(x,y):
    if x>y:
        return -1
    if xreturn 1
    return 0
    #或者使用下面这种写法
    #return cmp(x, y)
sorted([27,56,8], reversed_cmp)

***cmp比较大小:***cmp(s1.lower(), s2.lower())

返回函数

即返回值是一个函数。
返回函数可以实现的一个功能就是,延迟执行。我们将该函数返回,当需要的时候再调用它。

def f():
    print 'call f()...'
    # 定义函数g:
    def g():
        print 'call g()...'
    # 返回函数g:
    return g

闭包

在函数内部定义的函数和外部定义的函数是一样的,只是他们无法被外部访问。

一个内层函数如果引用了外层函数的变量(即使是外层函数的变量当做内层函数的参数也算),并且返回内层函数的话,那么这种称为闭包。
如果内层函数引用了外层函数的变量,并且内层函数在运行之前,外层函数的变量发生的变化,那么这个内层函数的运行结果是有问题的。
如:
希望一次返回3个函数,分别计算1x1,2x2,3x3:

def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs
f1, f2, f3 = count()
print f1(), f2(), f3()

实际返回的是3个9
修改上面实现:
它可以正确地返回一个闭包g,g所引用的变量j不是循环变量,因此将正常执行。

def count():
    fs = []
    for i in range(1, 4):
        def f(j):
            def g():
                return j*j
            return g    
        fs.append(f(i))
    return fs
f1, f2, f3 = count()
print f1(), f2(), f3()

匿名函数

如:

map(lambda x:x*x,[1,2,3,4,5,6])
#结果[1,4,9,16,25,36]

lambda表示匿名函数,:前面的x表示参数,后面表示表达式。
上面匿名函数等同于:

def f(x):
    return x*x

匿名函数的缺点:只能有一个表达式,不写return,返回值就是表达式。

装饰器

decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。

编写无参数decorator

请编写一个@performance,它可以打印出函数调用的时间。

import time

def performance(f):
    def fn(*args, **kw):
        t1=time.time()#获取当前时间
        r=f(*args, **kw) #*args, **kw确保了无论factorial有多少个参数都可以正常调用
        t2=time.time()
        print 'call %s() in %fs' % (f.__name__, (t2 - t1))  # f.__name__返回函数的名字
        return r
    return fn  #这里返回了一个新的函数,这个新函数返回的是新添加的功能+原来的函数

@performance   #@performance就相当于简写了factorial=performance(factorial)
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))

print factorial(10)

编写带参数decorator

其实就是在原来的performance函数的外面有嵌套了一层函数,新添加的函数接收参数。
调用改变:@performance变为了@performance(args)

**import time

def performance(unit):
    def performance1(f):
        def fn(*args, **kw):
            t1=time.time()#获取当前时间
            r=f(*args, **kw) #*args, **kw确保了无论factorial有多少个参数都可以正常调用
            t2=time.time()
            print '[%s]call %s() in %fs' % (unit, f.__name__, (t2 - t1))  # f.__name__返回函数的名字
            return r
        return fn  #这里返回了一个新的函数,这个新函数返回的是新添加的功能+原来的函数
    return performance1

@performance('ms')   #@performance就相当于简写了factorial=performance(factorial)
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))

print factorial(10)**

完善Decorator

# -*- coding:utf-8 -*-
def f1(x):
    print 'call',x
print f1.__name__#打印结果是f1
#有decorator的情况下,再打印函数名
def log(f):
    def wrapper(*args, **kw):
        print 'call...'
        return f(*args, **kw)
    return wrapper
@log
def f2(x):
    print 'call f2',x
print f2.__name__#打印结果是wrapper
#由于decorator返回的新函数函数名已经不是'f2',而是@log内部定义的'wrapper'。这对于那些依赖函数名的代码就会失效。

Python内置的functools可以把原来函数的必要属性一个一个复制到新函数上。

#3.functools复制函数信息
#有decorator的情况下,再打印函数名
def log3(f):
    @functools.wraps(f) #将f函数的所有属性信息拷贝到wrapper方法上
    def wrapper(*args, **kw):
        print 'call...'
        return f(*args, **kw)
    return wrapper
@log3
def f3(x):
    print 'call f3',x
print f3.__name__#打印结果是wrapper

偏函数

有一个函数f1,需要很多个参数,使用比较麻烦。现在我们创建一个函数f2,f2调用f1,但是f2有一些参数是默认的。所以我们可以通过使用较少的参数调用f2来达到使用很多个参数调用f1相同的功能。
functools.partial就是帮助我们实现这一个功能的。

# -*- coding:utf-8 -*-
#偏函数
import functools
int2 = functools.partial(int, base=2)
print int2('10000'),int('10000',2)
print int2('101001'),int('101001',2)

你可能感兴趣的:(python)