流畅的python:一等函数-Part2

把函数视作对象

6、函数注解

函数注解用于为函数声明中的参数和返回值附加元数据,例如下面代码的第一行

def repeat(text: str, max_len: 'int>0' = 80) -> str:
    if max_len < 80:
        return text + '-' * (80 - max_len)
    else:
        return text

函数声明中的各个参数可以在:之后增加注解表达式。如果参数有默认值,注解放在参数名和=号之间。如果想注解返回值,在)和函数声明末尾的:之间添加->和一个表达式。

Python对注解所做的唯一的事情是,把它们存储在函数的__annotations__属性里。仅此而已,Python不做检查、不做强制、不做验证,什么操作都不做。换句话说,注解对Python解释器没有任何意义。唯一的作用可能是供IDE、框架和装饰器等工具使用。就像下面的这个例子:

无注解

有注解

当没有注解的时候,IDE不知道text的数据类型,所以不会自动填充。

接下来,我们对内置的两个函数模块进行说明。

7、operator模块

  1. 运算符函数

operator模块为多个算术运算符提供了对应的函数,从而避免编写lambda a, b: a*b这种平凡的匿名函数,常见的有:

函数等价方式函数等价方式
operator.lt(a,b)a<boperator.abs(obj)abs(obj)
operator.gt(a,b)a>boperator.add(a,b)a+b
operator.le(a,b)a<=bfloodiv(a, b)a//b
operator.ne(a,b)a!=bmod(a, b)a%b
operator.eq(a,b)a==bmul(a, b)a*b
operator.ge(a,b)a>=bnge(obj)-obj
operator. is_(a, b)a is bpos(obj)+obj
sub(a, b)a-b

以连乘为例,以前可能使用的是

import functools
alist = range(1, 6)
print(functools.reduce(lambda a, b: a * b, alist))

但现在可以使用

print(functools.reduce(mul, alist))
  1. 索引函数itemgetter和attrgetter

itemgetter通常用于sort等高阶函数的key函数,比如下面的例子:

from operator import itemgetter
infor_2325 = [('zhao', 178, 72), ('wen', 176, 73), ('niu', 177, 70),
              ('li', 179, 66), ('ma', 176, 75)]
sorted(infor_2325, key=itemgetter(1), reverse=True)

上述代码实现了按第二字段进行排序,事实上,itemgetter(1)也等价于lambda line: line[1]:

each_height=itemgetter(1)
for pp in infor_2325:
    print(each_height(pp),end='/')
# 返回178/176/177/179/176/

所以最后一行代码这么写也是没问题的

sorted(infor_2325, key=lambda line: line[1], reverse=True)

当然也可以传入多个字段itemgetter(a,b),如果a字段一样的话,则会转到b字段进行比较。所获取的字段将会组织成元组的形式:

hei_weight=itemgetter(1,2)
for pp in infor_2325:
    print(hei_weight(pp),end='/')
# 返回(178, 72)/(176, 73)/(177, 70)/(179, 66)/(176, 75)/    

attrgetter和itemgetter的作用几乎一样,不过itemgetter是基于索引的取·值,而attrgetter是基于关键字的取值:

from collections import namedtuple
from operator import attrgetter
Each_pp = namedtuple('Each_pp', 'name height weight')
infor_tup = [
    Each_pp(name, height, weight) for name, height, weight in infor_2325
] # 构建一个具名元组
sorted(infor_tup, key=attrgetter('height'), reverse=True)
  1. methodcaller(选读)
    methodcaller创建的函数会在对象上调用参数指定的方法,大多数情况下用不着他,现在我们简单看一下他的用法:

    from operator import methodcaller
    s = 'when will we graduate'
    upcase = methodcaller('upper')  # 等价于s.upper()
    print(upcase(s))  # WHEN WILL WE GRADUATE
    hid_space = methodcaller('replace', ' ', '-')  # 等价于s.replace(' ','-')
    print(hid_space(s))  # when-will-we-graduate
    

8、functools模块

functools模块提供了一系列高阶函数,其中最为人熟知的或许是reduce,还记得reduce的用法吗?reduce() 函数会对参数序列中元素进行累积。用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果,最经典的例子就是我们刚刚讲到的连乘。

当然如果是连和,就大可不必使用reduce,sum()函数是一个更好的选择。

functools余下的函数中,最有用的是partial及其变体partialmethod。

以前计算器上有一个记忆加按键,不知道大家知不知道,就是一直加一个固定的数。functools.partial这个高阶函数就可以实现这个功能,用于部分应用一个函数。部分应用是指,基于一个函数创建一个新的可调用对象,把原函数的某些参数固定。比如下面这个例子:

# 记忆加3
from operator import add
from functools import partial
add3 = partial(add, 3)  # 固定add函数的一个值是3
[add3(x) for x in range(5)]

functools.partialmethod函数(Python 3.4新增)的作用与partial一样,不过是用于处理方法的。

——本章完——
欢迎关注我的微信公众号
扫码关注公众号

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值