廖雪峰--python教程:笔记四-函数式编程

函数式编程:


概念:是一种抽象程度很高的编程方式,允许将一个函数作为参数传入另一个函数,还允许返回一个函数。

接下来介绍:

map/reduce,filter,stored函数,返回函数,匿名函数,装饰器,偏函数

map函数:

问题:如果我想对一个列表[1,2,3,4,5,6,7,8,9]中的每一个元素求其平方:

L = [1,2,3,4,5,6,7,8,9]

def f(L):
    l = []
    for i in L:
        l.append(i*i)
    return l

我们需要编写一个函数,然后作用在这个列表L上,有没有更简洁的写法呢?是有的,可以用map函数

L = [1,2,3,4,5,6,7,8,9]
def f(x):
    return x*x

l = map(f,L)
print(list(l))

map()函数接收两个参数:第一个是函数名,第二个是Iterable,并将结果作为Iterator返回。(Iterable,Iterator的概念,请参考https://www.cnblogs.com/double-lin/p/9757953.html)

reduce函数

reduce是将函数f作用在序列[x1,x2,x3...]上,并且函数f接收两个参数:

reduce(f,[x1,x2,x3,x4]) = f(f(f(x1,x2),x3),x4)

from functools import reduce

def fn(x,y):
    return 10*x +y

reduce(fn,[1,2,3])

练习一:利用map()函数,把用户输入的不规范的英文名字,变为首字母为大写,其他小写的规范名字。输入:['adam','LISA','barT'],输出:['Adam','Lisa','Bart']。

#/usr/bin!
'''
首先,定义一个函数能够将字符串转变为,首字母大写其余小写;然后再将map函数作用在这个包含字符串的list集合上
'''
def toUpperLower(s):
    # 字符串长度
    m = len(s)
    first = s[0].upper()
    end = s[1:m].lower()
    return (first+end)

print(list(map(toUpperLower,['adam','LISA','barT'])))

 练习二:Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积:

#/usr/bin!
from funtools import reduce
def prod(L):
    def fn(x,y):
        retrun(x*y)
    return reduce(fn,L)

练习三:利用map()和reduce()编写一个str2float()函数,把字符串'123.456'转换为浮点型123.456

from functools import reduce

DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}

def char2num(s):
    return DIGITS[s]

def strToFloat(s):
    s = s.split('.')
    if s[0]=='':
        first = 0.0
    else:
        first = reduce(lambda x,y: x*10 + y,map(char2num,s[0]))
    l = list(reversed(s[1]))
    l.append('0')
    end = reduce(lambda x,y: x*(1e-1) + y,map(char2num,l))
    return (first+end)

print(strToFloat('.213'))

filter函数

python的内置函数filter函数和map函数类似,接收两个参数:函数和序列,和map()不同的是,filter()把函数以此作用在列表元素上,然后根据返回值是True还是False,来决定是否保留。

练习四:回数是从左往右数和从右往左数都是一样的数,利用filter()函数,来筛选出来回数:

def is_palindrome(num):
    s = str(num)
    if len(s)==1:
        return int(s)
    elif len(s)%2 == 0:
        for i in range(0,len(s)//2):
            if s[i] != s[len(s)-i-1]:
                return
        return int(s)
    else:
        for j in range(0,len(s)//2):
            if s[j] != s[len(s)-j-1]:
                return
        return int(s)

output = filter(is_palindrome, range(1, 1000))
print('1~1000:', list(output))

if list(filter(is_palindrome, range(1, 200))) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]:
    print('测试成功!')
else:
    print('测试失败!')

sorted函数

排序:sorted()也是一个高阶函数,可以用key=接收自定义的函数,和reverse=True或者False(默认False)逆序

练习五:假设我们用一组tuple来表示学生的名字和成绩:L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)],请用sorted()函数对列表L分别按名字和成绩排序:

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
    return t[0]

def by_score(t):
    return t[1]

sorted(L,key=by_name)
sorted(L,key=by_score)

匿名函数:

通过使用lambda关键字,来定义一个简单的函数,lambda x: x*x

冒号前的变量x是参数,返回结果x*x,冒号后,只能有一个表达式

练习六: 请用匿名函数改造下列代码:

def is_odd(n):
    return n % 2 == 1

L = list(filter(is_odd,range(1,20)))

#使用匿名函数
L = list(filter(lambda n: n%2==1,range(1,20)))

返回函数:

函数作为结果值,返回。

练习七:利用闭包返回一个计数器函数,每次调用它返回一个递增整数:

参考:https://www.cnblogs.com/cccmon/p/7930550.html

s = 0 #设置全局变量
def createCounter():   
    def counter():
        global s #引用全局变量
        s = s+1
        return s
    return counter
counterA = createCounter()
print(counterA()) #每次调用子函数,都是会保留上次s的值进行计算的
def createCounter():
    s = [0] 
    def counter():
        s[0] = s[0]+1
        return s[0]
    return counter

 装饰器:

在动态执行函数的时候,我们希望在不改变原来函数代码的下,动态增强该函数的功能,如在调用的时候打印一下该函数的开始执行提示。

练习八:写一个装饰器log,使其即满足:

@log

def f():

  pass

又满足:

@log('execute')

def f():

  pass

import functools


def log(param):
    if callable(param):
        def wrapper(*args, **kw):
            print('%s function()' % (param.__name__))
            param(*args, **kw)

        return wrapper

    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (param, func.__name__))
            return func(*args, **kw)

        return wrapper

    return decorator

偏函数:

就是使调用函数的时候更简单一点:

 import functools
 int2 = functools.partial(int, base=2)
 int2('1000000')
#输出: 64

猜你喜欢

转载自www.cnblogs.com/double-lin/p/9831194.html