python函数式编程

高阶函数

把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
与js相似,与c#中的委托一相似。

  • abs() 求一个数的绝对值
#模拟abs得到一个数的绝对值
def absFun(n):
    if n<0:
        return -n;
    return n
  • map(fn,list) 集合处理函数,作用到循环迭代对象的每个元素,返回新的对象
    fn是逐个处理元素的函数
#将list值全部转换成字符串,str是一个函数(字符串转int使用int())
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']
#首字母大小,其他小写,处理map的示例
def normalize(name):
    return name[0].upper()+name[1:].lower()
#等同于
lambda name:name[0].upper()+name[1:].lower()
  • reduce(fn,list) fn是函数需要两个参数,结果会累积,求和会用到
reduce(lambda x,y:x*y,L)

int()转换成整数,float()转换成浮点数,sum()求和,.index('.')符号.首次出现的下标,.upper()转换成大写,.lower()转换成小写

def str2float(s):
    n=s.index('.')
    s=s[:n]+s[n+1:]
    DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
    def char2num(x):
        return DIGITS[x]
    return reduce(lambda x,y:10*x+y,map(char2num,s))/(10**(len(s)-n))
  • filter() 筛选过滤元素
    标准的写法:
def not_empty(s):
    return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))

使用lambda便捷函数

def _not_divisible(n):
    return lambda x : x%n > 0
#等价于:
def _not_divisible(n):
    def suibian(x):
        return x%n>0
    return suibian
  • sorted()排序算法
    对集合排序,忽略大小写,反向
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']

用sorted()排序的关键在于实现一个映射函数。

#对字典姓名,第三个字母进行排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
    return t[0][2]

闭包

在一个函数内部定义另一个函数,它可以调用外部函数的参数和局部变量,就形成了闭包

def count2():
    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
#使用lambda简化
def count3():
    fs = []
    for i in range(1, 4):
        def f(j):
            return lambda: j*j
        fs.append(f(i))
    return fs
  • 在count2中j的值被传入f()中,但不会执行g函数,而是返回了函数g
  • 函数count2返回的是一个集合,每个元素都是一个函数
    执行结果:
>>> f1, f2, f3 = count2()
>>> f1()
1
>>> f2()
4

使用闭包和生成器结合起来,形成每次调用就+1的效果:

def createCounter():
    def dizeng ():
        a=1
        while True:
            yield a
            a =a+ 1
    def sd ():return next(g)#如果直接使用dizeng(),会导致多次执行该函数
    g = dizeng()#函数执行了一次,所以内部变量a只声明了一次,结果是一个生成器
    return sd#因调用方式,结果必须返回函数
#调用函数
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5

匿名函数

使用lambda x: x * x这样方式的就是一个匿名函数
x表示匿名函数的参数,:后面的是应用计算

  • 与普通函数应用方式一样,都可以作为变量或返回值
  • 因为没有名字,不必担心名称冲突的问题
  • 只能有一个表达式,返回值就是表达式的结果

装饰器

在函数的上面添加@函数名 的形式就是装饰器

#定义了一个执行函数前,自动打印日志的功能函数
def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
#定义一个应用函数
@log
def now():
    print('2015-3-25')
  • 执行now( )就相当于执行了log(now)( )
  • 除了@log标记,就是一个闭包函数的应用
  • 为了保持now函数的__name__属性不变,可以使用@functools.wraps(func)
import functools
def log(text):
    def decorator(func):
        @functools.wraps(func)#可保持得到的最终运行的函数__name__值仍是func的值
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator
#定义一个应用函数
@log('execute')
def now():
    print('2015-3-25')
  • 以上定义了一个带参数的log函数
  • 执行now( )就相当于执行了log('execute')(now)( )

偏函数

针对一些有默认值的函数,生成一个固定项的函数
如int(x,base=10)参数base默认是10,如下:

int2 = functools.partial(int, base=2)
>>> int2('1000000')
64

生成了一个新的函数int2,调用int2(二进制字符串),得到十进制数字

你可能感兴趣的:(python函数式编程)