流畅的python:5 一等函数

it2023-05-02  69

在 Python 中,函数是一等对象。编程语言理论家把“一等对象”定义为满足下述条件的程 序实体:

• 在运行时创建

• 能赋值给变量或数据结构中的元素

• 能作为参数传给函数

• 能作为函数的返回结果

 

5.1 把函数视作对象

@函数式编程的特点之一是使用高阶函数

5.2 高阶函数

@接受函数为参数,或者把函数作为结果返回的函数是高阶函数

@在函数式编程范式中,最为人熟知的高阶函数有 map、filter、reduce

map、filter和reduce的现代替代品

@使用列表推导式替代

5.3 匿名函数

@lambda 句法只是语法糖:与 def 语句一样,lambda 表达式会创建函数对象。这是Python 中几种可调用对象的一种。

5.4 可调用对象

@如果想判断对象能 否调用,可以使用内置的 callable() 函数

@Python 数据模型文档列出了 7 种可调用对象。

1:用户定义函数

2:内置ha

3:内置方法

4:类方法

5:类实例:如果类定义了 __call__ 方法,那么它的实例可以作为函数调用

6:生成器函数:使用 yield 关键字的函数或方法。调用生成器函数返回的是生成器对象。

@生成器函数还可以作 为协程

5.5 用户定义的可调用类型

@不仅 Python 函数是真正的对象,任何 Python 对象都可以表现得像函数。为此,只需实现 实例方法 __call__。

 

@下面讨论把函数视作对象处理的另一方面:运行时内省。

5.6 函数内省

@与用户定义的常规类一样,函数使用 __dict__ 属性存储赋予它的用户属性。

 

 

 

 

5.7 从定位参数到仅限关键字参数

@定义函数时若想指定仅限关键字参数,要把它们 放到前面有 * 的参数后面。如果不想支持数量不定的定位参数,但是想支持仅限关键字参 数,在签名中放一个 *。

5.8 获取关于参数的信息

@函数对象有个 __defaults__ 属性,它的值是一个元组,里面保存着定位参数和关键字参 数的默认值。仅限关键字参数的默认值在 __kwdefaults__ 属性中。然而,参数的名称在 __code__ 属性中,它的值是一个 code 对象引用,自身也有很多属性。

@参数名称在 __code__.co_varnames 中, 不过里面还有函数定义体中创建的局部变量。因此,参数名称是前 N 个字符串,N 的值由 __code__.co_argcount 确定。顺便说一下,这里不包含前缀为 * 或 ** 的变长参数。参数的 默认值只能通过它们在 __defaults__ 元组中的位置确定,因此要从后向前扫描才能把参数 和默认值对应起来。

@。inspect.signature 函数返回一个 inspect.Signature 对象,它有一个 parameters 属性,这是一个有序映射,把参数名和 inspect.Parameter 对象对应起来。各个 Parameter 属性 也有自己的属性,例如 name、default 和 kind。

@除了 name、default 和 kind,inspect.Parameter 对象还有一个 annotation(注解)属性, 它的值通常是 inspect._empty,但是可能包含 Python 3 新的注解句法提供的函数签名元数 据

@inspect.Signature 对象有个 bind 方法,它可以把任意个参数绑定到签名中的形参上,所 用的规则与实参到形参的匹配方式一样。框架可以使用这个方法在真正调用函数前验证参 数. Bind 方法与解释器使用的机制相同,就是用来验证参数的。

@框架和 IDE 等工具可以使用这些信息验证代码

 

5.9 函数注解

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

@signature 函数返回一个Signature 对 象, 它 有 一 个return_annotation 属性和一个 parameters 属性,后者是一个字典,把参数名映射到 Parameter 对象上。每个 Parameter 对象自己也有 annotation 属性,。示例 5-20 用到了这几个属性。

5.10 支持函数式编程的包

@得益于operator 和 functools 等包的支持,函数式编程风格也可以信手拈来。

5.10.1 operator模块

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

@operator 模块中还有一类函数,能替代从序列中取出元素或读取对象属性的 lambda 表达 式:因此,itemgetter 和 attrgetter 其实会自行构建函数。

@itemgetter 使用 [] 运算符,因此它不仅支持序列,还支持映射和任何实现 __getitem__ 方 法的类。

@attrgetter 与 itemgetter 作用类似,它创建的函数根据名称提取对象的属性。如果把 多个属性名传给 attrgetter,它也会返回提取的值构成的元组。此外,如果参数名中包 含 .(点号),attrgetter 会深入嵌套对象,获取指定的属性。(phm里面可以使用这个)

5.10.2 使用functools.partial冻结参数

@functools.partial 这个高阶函数用于部分应用一个函数。部分应用是指,基于一个函数创 建一个新的可调用对象,把原函数的某些参数固定。

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

5.11 本章小结

@Python 中常用的高阶函数有内置函数 sorted、min、max 和 functools. partial。

@Python 有 7 种可调用对象,从 lambda 表达式创建的简单函数到实现 __call__ 方法的类实 例。这些可调用对象都能通过内置的 callable() 函数检测。每一种可调用对象都支持使用 相同的丰富句法声明形式参

@

最新回复(0)