系统学习编程笔记(二十一)

• 完成 Python 教程

6 函数式编程 (二)

  • sorted()函数也是一个高阶函数,它可以接收一个key函数来实现自定义的排序。
  • 高阶函数的抽象能力是非常强大的,而且核心代码可以保持得非常简洁。

练习:假设我们用一组tuple表示学生名字和成绩,请用sorted()对列表分别按名字排序:

# -*- coding: utf-8 -*-
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

# 请用sorted()对上述列表分别按名字排序
def by_name(t):
    return t[0].lower()

L2 = sorted(L, key=by_name)
print(L2)

# 再按成绩从高到低排序
def by_score(t):
    return -t[1]

L2 = sorted(L, key=by_score)
print(L2)
  •  高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

 在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

请再注意一点,当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数。

  • 注意到返回的函数在气定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。
  • 另一个问题就是,返回的函数没有立刻执行。
  • 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

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

def createCounter():
    n=0
    def counter():
        nonlocal n
        n = n + 1
        return n
    return counter
  • 一个函数可以返回一个计算结果,也可以返回一个函数。
  • 返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。
  • 关键字lambda表示匿名函数。
  • 匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
  • 匿名函数的一个好处是因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。
  • 函数对象都有一个__name__属性,可以拿到函数的名字。
  • 现在假设我们要增强一个函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

练习:请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间:

# -*- coding: utf-8 -*-
import time, functools
def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args,**kw):
        start=time.time()
        program=fn(*args,**kw)
        end=time.time()
        print("%s executed in %s ms"%(fn.__name__,end-start))
        return program
    return wrapper

# 测试
@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y;

@metric
def slow(x, y, z):
    time.sleep(0.1234)
    return x * y * z;

f = fast(11, 22)
s = slow(11, 22, 33)
if f != 33:
    print('测试失败!')
elif s != 7986:
    print('测试失败!')
  •  在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。
  • decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。
  • functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2。
    >>> import functools
    >>> int2 = functools.partial(int, base=2)
    >>> int2('1000000')
    64
    >>> int2('1010101')
    85
  • 简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
  • 当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值