函数是组织好的、可重复使用的、功能单一的代码段
函数有输入(参数)和输出(返回值)
在Python中,函数是一等对象(First Class)
一、函数参数
- 位置参数
- 关键字参数
是位置参数还是关键字参数,取决于函数调用时参数给定的方式
- 默认参数
定义的时候可以设定默认参数,调用的时候如果不指名改参数,执行时会调用默认参数
默认参数通常和关键字参数结合使用,会得到美好的结果
- 可变参数(传递列表作为参数)
可变参数是一个packing的过程
- 可变关键字参数(传递字典作为参数)
可变参数函数在定义的时候就决定了参数是位置参数还是关键字参数
可变位置参数和可变关键字参数可以同时定义,
但是可变位置参数要在前可变关键字参数之前。
- 参数解包(unpacking的过程)
lst = [1, 2]
def add(x, y):
return x + y
add(*lst)
前条件:要解包的参数列表要和函数定义的参数列表相匹配
将lst列表作为可变参数列表传递给add函数,按照位置参数一一对应给定参数
类似的,字典一样可以解包,调用的时候类似于关键字参数
二、默认函数的坑
- 每执行一次,lst都会append一个1进来
def fn(lst=[]):
lst.append(1)
print(lst)
改进如下:
def fn(lst=None): #如果是可变类型的默认参数,都应该赋初值为None
if lst is None:
lst = [] #赋值操作相当于创建心变了,这里定义的lst跟函数体之外的lst不是同一个对象
lst.append(1)
print(lst)
三、作用域与全局变量
- 作用域:变量的生效范围
- 局部变量:在函数体内定义的变量,作用域为定义此变量的函数体
- 全局变量:定义在函数体之外的变量
1、内置函数:locals() 可以列出当前所有的局部变量
2、内置函数:globals()可以列出全局变量
四、生成器(含有yield关键字的函数)
def iterator(x):
i = 0
while i < x:
yield i
i += 1
当执行到yield的时候,本函数暂停,再次轮到该函数执行的时候,从yield的地方继续执行
yield可以实现异步和协程
def iterator():
lst = [1, 2, 3, 4, 5]
yield from lst
五、高阶函数
- 函数是一等对象
高阶函数:接收函数作为参数传递进来的函数
def sort(compare, *args): #compare是一个函数的名称
ret = []
for item in args:
for index, value in enumrate(ret): #同时返回列表中的元素及其索引
if compare(item, value):
ret.insert(index, value)
break
else:
ret.append(item)
return ret
def compare1(x, y): #按照从大到小的顺序排列
return x >= y
def compare2(x, y): #按照从小到大的顺序排列
return x <= y
内置函数filter、map也是高阶函数
标准库reduce也是高阶函数
六、函数作为返回值
def make_inc(f=1):
def inc(x): #inc函数:返回给定参数加上外层函数的参数的和
return x + f
return inc #返回inc函数
make_inc(11)(2) #结果是13(外层函数给定的参数是11,内层函数的参数是2)
上面这种调用方式,称为“柯里化”
柯里化其实是将 fn(x, y) 的方式转变成 fn(x)(y) 的方式
def bigger(x):
def inner(y):
return x > y
return inner
#过滤比5 大的数(可以手动指定过滤标准)
filter(bigger(5), range(10))
#如果要过滤出比3大的数,在调用的时候,只需要将5改成3即可,非常方便!
functools库中的partial方法,可以固定某些参数,在不用修改原函数的情况下实现“柯里化”(数据库连接函数,使用partial十分方便)
七、装饰器
装饰器本质就是一个接受函数作为参数,并且返回值也是函数的一个高阶函数。
返回的函数对传入的函数执行前后增加了一些语句,即做了一些装饰。
import time
from functools import wraps
def timeit(process_time=False):
cacl = time.clock if process_time else time.time
def inner(fn)
@wraps(fn) # 更新wraps
def wrap(*args, **kwargs):
start = cacl()
ret = fn(*args, **kwargs)
print(cacl() - start)
return ret
return wrap
return inner
@timeit(True)
def test(*args, **kwargs)
print('test')
八、装饰器的应用
- Flask框架就是用装饰器来做路由
- Django框架很多地方也使用了装饰器
# 权限认证
import functools
def auth(allow_list): # 定义允许执行fn函数的成员列表
def inner(fn):
@functools.wraps(fn)
def wrap(user_name, *args, **Kwargs):
if user_name in allow_list:
return fn(user_name, *args, **kwargs)
return 'Not allowed!'
return wrap
return inner
@auth(['zhang3', 'li4', 'wang5'])
def private_operate(user_name):
print('Do something...')
九、Lambda表达式
语法规则:lambda 参数列表:表达式
参数之间用逗号隔开,表达式的计算结果直接返回,不需要return语句
lambda表达式只能写在一行,也叫单行函数(或匿名函数)
lambda x, y : x >= y
# 也可以将lambda表达式赋值给一个接收变量
func = lambda x, y, z : x + y + z
网友评论