Python进阶(六):函数式编程

函数式编程

定义

    函数式编程是一种编程范式,将电脑运算视为函数的计算

特点

  • 把计算视为函数
  • 代码简洁方便阅读容易理解
  • 允许有变量
  • 支持高阶函数(函数作为变量)、闭包(返回函数)和匿名函数

使用

# 将函数作为参数
import math 
def add(x, y, f):
	return f(x) + f(y)

print(add(-1, 9, abs))       # ==> 10
print(add(4, 16, math.sqrt)) # ==> 6.0


'''map()函数
接收一个函数f和一个list,并依次把函数f作用在list的每个元素上,同时返回一个迭代器,可以依次迭代得到原来list元素处理后的结果
'''
def formatter(x):
    return x[0].upper() + x[1:].lower()

for item in map(formatter, ['john', 'TIMY', 'DaniEl']):
    print(item)     # ⇒ John Timy Daniel


'''reduce()函数
接收一个函数f和一个list,对list的每个元素反复调用函数f,并返回最终结果,可以接收第三个参数作为初始值
Python2中可以直接使用,Python3中需要在functools包中引入
'''
from functools import reduce

def f(x, y):
    return x * y

print(reduce(f, [1, 3, 5, 7, 9]))   # ⇒ 945


'''filter()函数
接收一个函数f和一个list,通过函数f对每个元素进行判断,返回True或False,filter()根据判断结果自动过滤掉不符合条件的元素并返回一个迭代器,可以迭代出所有符合条件的元素
'''
import math

def is_integer(x):
    r = int(math.sqrt(x))
    return math.pow(r, 2) == x

for item in filter(is_integer, range(1,101)):
    print(item)   # ⇒ 1 4 9 16 25 36 49 64 81 100


'''sorted()函数
默认从小到大进行排序,当list每一个元素是容器时,则会以第一个元素来排序,返回一个新的list
如果需要指定排序的字段,key参数值是一个函数,接收待排序列表的元素作为参数并返回对应需要排列的字段
如果需要倒序,则需要指定reverse参数为True
'''
def k(item):
    return item.lower()

name = ['boom', 'about', 'Dog', 'Large']
print(name)                 # ⇒ ['boom', 'about', 'Dog', 'Large']
newName = sorted(name, key=k)
print(newName)              # ⇒ ['about', 'boom', 'Dog', 'Large']


'''返回函数
在函数内部可以定义子函数,同时可以把子函数返回
返回函数时不能带括号,返回函数值时则需要
'''
from functools import reduce

def f(x, y):
    return x * y

def calc_prod(list_):
    def prod():
        return reduce(f, list_, 1)
    return prod

p = calc_prod([1,2,3,4,5])
print(p())        # ⇒ 120


'''闭包
内层函数引用了外层函数的变量,并返回内层函数的结果
注意:返回函数不要引用任何循环变量或者后续会发生变化的变量
'''
def count():
    fs = []
    for i in range(1, 4):
        def f(j):
            def g():
                return j * j
            return g
        k = f(i)
        fs.append(k)
    return fs

f1, f2, f3 = count()
print(f1(), f2(), f3())      # ⇒ (1, 4, 9)


'''匿名函数
匿名函数使用lambda关键字进行定义,lambda x,y: x + y,就可以完成函数的定义,冒号前表示匿名函数的参数,冒号后则是一个表达式,不用写return,返回值就是该表达式的结果
'''
name = ['boom', 'about', 'Large', 'Dog']
print(sorted(name, key=lambda x:x.lower()))  # ⇒ ['about', 'boom', 'Dog', 'Large']


''''无参数的decorator
本质上是一个高阶函数,接收一个函数作为参数,返回一个新函数
使用@语法,可以避免手动编写代码
'''
# 只含一个参数
def log(f):
    def fn(x):
        print('call ' + f.__name__ + '()...')
        return f(x)
    return fn
# 含有任意个参数
def log(f):
    def fn(*args, **kwargs):
        print('call ' + f.__name__ + '()...')
        return f(*args, **kwargs)
    return fn

# 输出函数运行时间
import time 

def performance(f):
    def fn(*args, **kwargs):
        t1 = time.time()
        r = f(*args, **kwargs)
        t2 = time.time()
        print('call %s() in %fs' % (f.__name__, (t2-t1)))
        return r
    return fn
    
@performance
def add(x, y):
    return x + y
add(1, 2)      # ⇒ call add() in 0.000003s        3

@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
factorial(10)  # ⇒ call factorial() in 0.004084s


'''有参数的decorator
带参数的decorator首先返回一个decorator函数,再让这个decorator函数接收一个函数并返回新函数,相当于是在原有的二层函数里面,增加了一层嵌套
'''
import time 

def performance(param):
    def performance_decorator(f):
        def fn(*args, **kwargs):
            t1 = time.time()
            r = f(*args, **kwargs)
            t2 = time.time()
            if param == 's':
                print('call %s() in %fs' % (f.__name__, (t2-t1)))
            if param == 'ms':
                print('call %s() in %fms' % (f.__name__, (t2-t1)*1000))
            return r
        return fn
    return performance_decorator
    
@performance('ms')
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
    
factorial(10)      # ⇒ call factorial() in 3.329039ms   call factorial() in 0.003894s


'''偏函数
创建一个调用另外一个部分参数或变量已经预置的函数                                
partial可以将参数多的函数变成参数少的新函数,缺的参数需要指定默认值
'''
from functools import partial

sorted_ignore_case = partial(sorted, key=lambda x: x.lower())
print(sorted_ignore_case(['boom', 'about', 'Large', 'Dog'])) # ⇒ ['about', 'boom', 'Dog', 'Large']

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值