python学习之高阶函数

高阶函数

本文中所指的高阶函数,是可以接收函数作为参数传入或者将函数作为返回值,这就是函数式编程,是一种高度抽象的编程范式。
常见的内置高阶函数包括:map,reduce,filter,sorted,用法下面以 sorted 举例。

sorted(['1','33','2'],key=int) # 返回 ['1', '2', '33']

其余内置函数用法可以参考我的文章:python学习之序列推导式与常用内置高级函数和模块

闭包与装饰器

当一个函数a的返回为另一个函数时,该函数程序结构称为闭包,需要注意的是,返回的函数并未立即执行,返回函数中不要引用任何可能会变化的变量。

# 闭包举例
def a(*args):
    def b():
        sm = ''
        for i in args:
            sm += i
        return sm
    return b

x = a('11','22')
print(x()) # 返回 '1122'

闭包在日常应用中最多的就是 装饰器,它是一种多层嵌套的闭包结构。

def executes(notes):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s' % (notes))
            return func(*args, **kw)
        return wrapper
    return decorator

# 装饰器的使用
@executes('execute program...')
def test(arg):
    print(arg)

#执行被装饰函数test
>>> test('contents')
execute program...
contents

在传递函数的过程中,为了避免某些依赖函数(被修饰的函数)签名(例如 __name__ 属性等)的代码执行时出错,需要借助Python内置的 functools.wraps做处理。

import functools

def executes(notes):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print(notes)
            return func(*args, **kw)
        return wrapper
    return decorator
    

应用举例:计时功能的装饰器如下

def times(num):
    def wp(func):
        def wrap(*args):
            t1=time.time()
            for i in range(num):
                func(*args)
            print(func.__name__)
            print(time.time()-t1)
        return wrap
    return wp


@times(1000)
def test():
    a=[]
    for i in range(1000):
        a+=[i]

# 函数 test 执行1000次 所用的时间(秒)
test() # 0.144999980927 

以上是装饰器函数中包含参数的情况,如果不需要参数,可以减少 封装 层数。

def times(func):
    def wrap(*args):
        t1=time.time()
        func(*args)
        print(func.__name__)
        print(time.time()-t1)
    return wrap

@times
def test():
    a=[]
    for i in range(1000):
        a+=[i]

## 函数 test 执行1次 所用的时间(秒)
test() # 0.000999927520752

一个函数可以同时定义多个装饰器:

@a
@b
def f():
    pass

执行顺序是从里到外,由近及远,它等效于 f = a(b(f))

迭代器与生成器

迭代器是一个可以记住遍历的位置的对象,迭代器对象的访问从集合的第一个元素开始,直到所有的元素被访问。迭代器的两个基本方法:iter()next(),迭代是通过 for … in 来完成的。
凡是可作用于for循环的对象都是可迭代(Iterable)类型,凡是可作用于next()函数的对象都是迭代器(Iterator)类型,集合数据类型如list、dict、str等是Iterable但不是Iterator,但可以通过**iter()**函数转化为迭代器对象。

可迭代对象:实现了__iter__方法或者__getitem__方法(参数为从0开始的索引)的对象
迭代器:实现了__next__(返回下一个元素)和__iter__方法(返回迭代器本身)的对象。

from collections import Iterator

# 迭代器判断
>>> isinstance('abc', Iterator)
False
>>> isinstance(iter('abc'), Iterator)
True

生成器(generator)也是一类可迭代对象,generator保存的是算法,每次调用next()方法,就计算出下一个元素的值,直到计算出最后一个元素,抛出StopIteration的错误。
如果一个函数定义中包含 yield 关键字,那么这个函数就是一个生成器。变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

def test():
    print('aaa')
    yield 1
    print('bbb')
    yield 2

>>> a=test()
>>> next(a)
aaa
1
>>> next(a)
bbb
2
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

生成器中的传值
使用send方法实现传值

def filter_keyword(keyword):
    print('search for keyword: {}'.format(keyword))
    while True:
        inputs = (yield)
        if keyword in inputs:
            print('Found keyword.')
        else:
            print('No found')

a = filter_keyword('test')
next(a) #  输出 search for keyword: test
a.send('asdas') # 输出 No found
a.send('32123test') # 输出 Found keyword
a.close() # 关闭生成器

递归

递归就是函数内部会调用函数自身。

def fact(n):
    if n == 1:
        return 1
    return n * fact(n - 1)

递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致 栈溢出
理论上,所有的递归函数都可以写成 循环 的方式,所以可以通过循环进行替换。

def fact(n):
    r = 1
    for i in range(1, n+1):
        r *= i
    return r

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值