- 函数是对程序逻辑进行结构化或过程化的一种编程方法(标题行相当于函数声明, 代码块相当于函数定义)
- 元祖语法上不需要一定带上圆括号, 所以在
return
中看起来像是在返回多个对象(对象返回数目:0:None, 1:object, >1:tuple) - 特性: 可以把参数放进一个元祖(非关键字参数)或字典(关键字参数)中, 比显式地把参数放表面要好得多
函数调用的完整语法:
func(位置参数, 关键字参数, *元祖, **字典)
- 名字错误是当访问没有初始化识别符时才产生的异常(过去有前向引用的问题)
-
内部/内嵌函数:在函数体内创建另外一个函数对象(方式:
def
内def
,lambda
), 整个函数体都在外部函数的作用域如果内部函数的定义包含了在外部函数里定义的对象的引用, 内部函数会被称为闭包(closure)
闭包常用于安装计算、隐藏状态、在函数对象和作用域中随意的切换
-
装饰器实际就是函数, 可有/无参数, 它定义了某个函数并在定义内的某处嵌入了对目标函数的调用或至少一些引用(本质上引用了AOP[面向切面编程]概念)
通常用于包装一个函数, 在包装的环境下在合适的时机调用它, 比如引入日志、记时逻辑、事务 P277的例子有闭包和装饰器的概念
- 所有对象都是通过引用来传递的, 函数也不例外, 函数可以作为参数传入到其他函数中(例如实现一个类型转换,有点像
map
) - python函数的形式参数有:位置参数、关键字参数、默认参数 (如果没有按正确的顺序给出参数, 会引发语法错误)
- 用
*
(非关键字变长参数)和**
(关键字变长参数)来允许函数接收在函数声明中定义的形参之外的参数 *
接收一个不定数目的非关键字参数(作为元祖),**
接收一个不定数目的关键字参数(作为字典), 位置要在形式参数之后-
用
lambda
表达式可以返回可调用的函数对象,lambda[args, *args]:expression
, 允许放参数lambda创建后如果没有引用保存下来, 计数会回到零, 然后被垃圾回收掉
- 函数对象相关内建函数:
apply()
(已淘汰)过滤filter(func, seq)
映射map(func,seq*)
折叠reduce(二元func, seq, [init])
map
、lambda
和列表解析有很多时候可以互换map(None, seq1, seq2)
等价于zip(seq1, seq2)
- 二元函数: 接收两个值作为输入,进行一些计算然后返回一个值作为输出(近似Currying[柯里化]概念)
- 偏函数应用(PFA):能够将带任意数量(顺序)的参数的函数转换成另一个带剩余参数的函数对象(Currying的泛化, 像lisp中的序对)
这个特征可以通过
functools
模块调用: 创建PFA:add1 = partial(add, 1)
,add1(x)
等价于add(1, x)
(放关键字参数时注意位置) -
声明适用的程序的范围被称为声明的作用域, 在一过程中,如果名字出在过程的声明之内, 称为局部变量
局部变量:依赖于定义它们的函数现阶段的活动状态(如函数完成->框架被释放->变量离开作用域)
全局变量:除非被删除, 否则一直存在, 所有函数都可访问
作用域指出了从用户代码的哪些物理位置可以访问到这些名字
- 在一个函数体内
global
过的全局变量的值可以在函数体内被覆盖(改变了函数外的全局变量) - python支持多个函数嵌套级别,匹配静态嵌套的作用域(在2.1前只能访问函数的局部作用域和全局作用域)
- 定义在外部函数内但由内部函数引用或者使用的变量被称为自由变量
- 回调就是函数, 闭包也是函数, 但是它们能携带一些额外的作用域
- 当需要一个必须有自己作用域的简单回调函数时, 比起用类,闭包会更适合
func.func_closure
追踪闭包变量 P299例子- 定义在函数内的变量有局部作用域, 在一个模块中最高级别的变量有全局作用域
- 如果一个新的调用能在相同过程中较早的调用(在结束之前开始), 那么该过程就是递归
-
协同程序: 可以运行的独立函数调用, 可以暂停或者挂起, 并可以从程序离开的地方继续或者重新开始(过程中状态是完整的)
生成器: 挂起返回出中间值并多次继续的协同程序(
yield
:能暂停执行并返回一个中间的结果), 它允许值(或异常)能传回到一个将继续的函数中 -
生成器与迭代器类似, 用
next()
向下取值, 当到达一个真正的返回或者函数结束没有更多的值返回时, 一个StopIteration
异常就会抛出应用:当迭代一个巨型数据, 想要在途中处理插入/抓取一块数据时(或是返回给调用者信息),生成器会提供一个安全的处理数据的环境(保留挂起时的状态)
- 生成器特性:同迭代器
next()
双向动作send()
(向generator
发送值以及返回接收值) 退出生成器close()
- Currying(柯里化):是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术
温故知新,高级复读机