函数
参数
可变参数
*args
接收若干个位置参数组成tuple, 参数个数可以为0**kwargs
接收若干个关键字参数组成dict
keyword only参数
*
号参数后面的普通参数,传入时只能以关键字方式传入
例: def fn(*,x,y)
表示x,y为keyword only参数
参数定义时顺序:
位置参数(无默认值参数,默认值参数) -> *arges
参数 -> kwargs only
参数 -> **kwargs
参数
对应形参类型(按可接收实参形式分类)
- POSITIONAL_ONLY python没有实现
- POSITIONAL_OR_KEYWORD
- VAR_POSITIONAL
- KEYWORD_ONLY
- VAR_KEYWORD
传参
非可变参数没有默认值,就必须传入对应值,按位置传入参数必须放在按关键字传入参数之前
参数解构: *args
, **kwargs
参数默认值
函数对象的默认值放在函数属性中,这个属性伴随着函数对象的整个生命周期
func.__defaults__
使用tuple保存所有位置值参数的默认值
func.__kwdefaults__
使用字典保存所有keyword-only参数的默认值
默认值如果使用可变类型(list),就可能被修改, 解决方法有两个:
1. x = x[:] 影子拷贝可变类型,重定义,不影响默认值
2. 将默认值设为None(不可变类型),函数内部判断,满足条件,就赋值为可变类型([]
)
作用域
全局作用域: 模块顶层定义的变量
局部作用域: 仅在函数和类内部可见
自由变量:未在本地作用域中定义的变量
global x
申明本局部作用域内的x为全局变量, 减少global的使用
nonlocal val
: 表示声明在上级的某一级作用域中定义,但在不能是全局作用域中定义的变量
函数中的加等异常
var+=1
抛出赋值前被使用异常
因为python中赋值即定义, var = var + 1, 等号右边先算, 但var使用的是本地刚定义的var
变量名的查找顺序是LEGB ,由内向外
Local -> Enclosing -> Global -> Build-in
闭包Enclosing
内层函数引用到外层函数的自由变量,就形成闭包, 内层函数被外层函数返回, 自由变量只能被内层函数访问到
def foo():
var = 0
def bar():
nonlocal var
var += 1
return var
return bar
闭包可以用在装饰器中, 实现单例模型,
递归Recursion
函数直接或间接递归调用自身, 递归一定要有退出条件
当一个逻辑, 重复执行相同的步骤, 只是传入参数值不同时, 就可以使用递归
所有递归都可以转换成循环, 递归是最符合人的思维的逻辑, 递归并不难, 难的是将递归转换成循环
函数执行流程:
依次压栈,创建栈帧,后进先出FILO,依次退出(Return),Return最外层结果
递归不宜过深:
因为压栈会消耗大量系统资源
python作了保护性限制, 查看解释器最大递归深度sys.getrecursionlimit()
修改递归最大深度sys.setrecursionlimit(2000)
, 超出递归限制, 抛出recursionError
匿名函数lambda
单行函数,只有一条return语句的函数可以写成lambda的形式
lambda表达式既是函数的定义又是函数的引用
例:函数中返回一个lambda函数
def inc():
def counter():
n = 0
while True:
n += 1
yield n
c = counter()
return lambda :next(c)
foo = inc()
print(foo())
print(foo())
解析式 和 生成器
解析式 是立即计算, 返回结果
- 列表解析式
[x for x in range(10) if x>5]
, if条件可省略 - 集合解析式
{x for x in range(10)}
- 字典解析式
{x:(x,x+1) for x in range(10)}
可迭代对象 iterable, 拥有__iter__
方法的对象, 例:list, tuple等
迭代器 iterator, iter(iterable)
生成迭代器, 可以使用next(iterator)
函数
生成器 generator, 是特殊的迭代器, 特点: 惰性求值(需要是时候才计算), 只能迭代一次
- 生成器表达式
(x for x in range(10)
生成器函数
yield
表示函数执行暂停到这里,并返回yield后面的值
next(iterator\[, default])
函数使生成器函数继续执行,只到下一个yield,如果函数执行结束都找不到yield,则抛出StopIteration, 可以有缺省值,防止报错
Generator函数可以使用return语句, return值不会被返回, 仅表示生成器结束执行
yield from iterable
等价于 iter(iterable)
python使用生成器实现协程coroutine,是在用户空间调度函数的一种实现,比进程,线程轻量级
高阶函数
函数也是对象,可调用的对象, 函数可以作为普通变量、参数、返回值等等
高阶函数
数学概念 y=g(f(x))
数学中定义高阶函数满足以下条件至少一个:
- 接受一个或多个函数作为参数
- 输出一个函数
内置高阶函数sorted、map、filter, max等
柯里化 指的是将原来接受两个参数的函数变成新的接受一个参数的函数,形成嵌套函数,外部函数负责传入部分参数,并返回内部函数名,内部函数接收剩余参数
装饰器Decorator
装饰器就是一个python解释器的语法糖, 使用@
符号和一个可调用对象, 放在需要被增强的函数或类上, 被包装对象作为参数传入, 并将返回值赋给被包装对象的引用
装饰器使用后, 原函数属性会发生改变, 使用functools.wraps, 复制原函数属性
装饰器分为无参装饰器和带参装饰器
装饰器的用途:
装饰器是AOP面向切面(方面)编程 Aspect Oriented Programming 的思想的体现
关注点分离, 减少耦合,在不修改原来代码的前提下,给程序动态添加功能,
日志、监控、权限、设计、参数检查、路由等处理