匿名函数
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。
关键字lambda表示匿名函数,冒号前面的x表示函数参数。
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
#匿名函数lambda x: x * x实际上就是
def f(x):
return x * x
匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果
匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
>>> f = lambda x: x * x
>>> f
<function <lambda> at 0x101c6ef28>
>>> f(5)
25
同样,也可以把匿名函数作为返回值返回,比如
def build(x, y):
return lambda: x * x + y * y
练习
请用匿名函数改造下面的代码:
def is_odd(n):
return n % 2 == 1
L = list(filter(is_odd, range(1, 20)))
L = list(filter(lambda x : x % 2 == 1, range(1,20)))
提示:以下是本篇文章正文内容,下面案例可供参考
装饰器
函数对象有一个__name__属性,可以拿到函数的名字
>>> def now():
... print('2015-3-25')
...
>>> f = now
>>> f()
2015-3-25
>>> now.__name__
'now'
>>> f.__name__
'now'
假设我们要增强now()
函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()
函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
decorator就是一个返回函数的高阶函数,定义一个能打印日志的decorator,可以定义如下:
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2015-3-25')
log()
是一个decorator,返回一个函数。所以,原来的now()
函数仍然存在,只是现在同名的now变量指向了新的函数。于是调用now()
将执行新函数,即在log()
函数中返回的wrapper()
函数。
wrapper()
函数的参数定义是(*args, **kw)
,因此,wrapper()
函数可以接受任意参数的调用。在wrapper()
函数内,首先打印日志,再紧接着调用原始函数
>>> now()
call now():
2015-3-25
decorator本身需要传入参数,自定义log文本
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
三层嵌套decorator用法如下:
@log('execute')
def now():
print('2015-3-25')
#执行结果如下:
>>> now()
execute now():
2015-3-25
# >>> now = log('execute')(now)
但是函数也是对象,它也有_name_等属性,但经decorator装饰之后的函数,_name_已经从’now’变成了’wrapper’。所以,需要把原始函数的__name__等属性
复制到wrapper()
函数中,否则,有些依赖函数签名的代码执行就会出错。
可以使用Python内置的functools.wraps
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
针对带参数的decorator
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
练习
请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间:
# 请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间:
# -*- coding: utf-8 -*-
import time, functools
def metric(fn):
@functools.wraps(fn) #把原始函数的属性复制到新函数中
def wrapper(*args, **kw):
start_t = time.time() #返回当前的时间戳(浮点秒数)
result = fn(*args, **kw) #调用函数
end_t = (time.time()-start_t) * 1000 #返回调用后时间戳,进行计算
print('%s executed in %s ms' % (fn.__name__, end_t))
return result
return wrapper
偏函数
在介绍函数参数的时候,我们讲到,通过设定参数的默认值,可以降低函数调用的难度。而偏函数也可以做到这一点。
int()
函数可以把字符串转换为整数,int()
函数还提供额外的base
参数,默认值为10。如果传入base
参数,就可以做N进制的转换:
>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565
functools.partial
就是帮助我们创建一个偏函数的,不需要我们自己定义int2()
,可以直接使用下面的代码创建一个新的函数int2
:
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
functools.partial
把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单