lambda的用法
1. lambda定义后赋值给某个对象,其本质就是对这个赋值对象的函数定义。
multiply = lambda x,y:x*y #函数一
print(multiply(2,3)) #6
def multiply(x,y): #函数二
return x*y
如以上示例,赋值后其实就是把lambda内部的操作,取了个名字。
2. lambda,更改其他函数内部封装好的操作,比如
abs = lambda x : 'changed'
print(abs(-20)) #changed
abs本身是求绝对值的函数,但是经过lambda的赋值,将其内部封装都颠覆了,其本质是,函数名只是一个变量,它指向这个函数的操作,你也可以用其他的变量来指向这个函数的操作,要记住一点,python中一切皆是对象,如下所示,n指向了求绝对值的函数的操作,所以返回 2
n = abs
print(n(-2)) #2
3. 作为函数的返回内容,这里要详细讲一讲,首先说结论吧,返回一个匿名函数也就是lambda的本质就是闭包(closure)
def example(n):
def f(x):
return x%n > 0
return f
def example_(n):
return lambda x: x%n > 0
上面两个函数是等价的,闭包外部函数,返回内部嵌套函数的函数名称,在上面的例子中,f就是内部嵌套函数的函数名。
我们都知道在python中,对函数的调用,其实就是函数名+(),那么对内部嵌套函数的调用呢?
答案很清晰了,就是看它嵌套的层数,上述例子中的嵌套是一层,调用它,传入两个参数即可
print(example(3)(10))
#返回 True
这样理解起来就很清晰了,很简单。
比如作用在filter中。
re = filter(example_(3),list(range(1,10)))
print(list(re))
#[1, 2, 4, 5, 7, 8]
承接上面的代码,这里过滤出了对三取模大于0的数,example_函数只要传入一个参数就好了,内部的lambda的参数由后面的list对象迭代来提供。
装饰器
先上两个结论
1.装饰器是函数
2.装饰器的本质是闭包。
装饰器的功能就是对它 “装饰” 的函数的功能进行扩展补充,补充额外的功能,它最强大的地方,在于python给了提供了
@+装饰器名称的语法糖, 可以最大程度的加强代码的复用。
举个简单的例子:假设你在开发一款软件,那么这个软件肯定有很多的功能,你决定把他们每个功能不管是大小,都封装在不同的函数里来实现,那一个软件可能要包括上百个函数的封装, 这个时候你想到一个日志记录的功能,你想记录每个函数调用的时间,或者你想测试函数的性能如何 —— 一个函数从运行到返回你要的结果花了多长时间, 不可能你对每个函数都这样去补充一个功能(补充功能不是不可以,只是这样的功能对于你开发过程中所有的函数测试,都能用得上,如果你有100个函数,100个函数的内部封装都不一样,要添加这么复杂的代码,简直一点也不pythonic了),所以,以代码简洁著称的python就提供了装饰器这个神器。
下面写一个记录函数运行时长的装饰器,再分析它的运行原理。
import time
def time_decorator(func):
def inner_f():
now = time.time()
func()
over = time.time()
interval = over-now
print('共耗时%.4f秒'%interval)
return inner_f
@time_decorator
def o():
for i in range(1,2000):
print(i)
return 'over!'
#...
1998
1999
共耗时0.0145秒
使用了@语法之后,python解释器首先发现了装饰器的存在,然后将它下面的函数,也就是被装饰的函数的函数名,作为参数
传入到装饰器内部(别忘了装饰器本身也是函数!),然后解释器会自动调用装饰器返回的函数,也就是内部的嵌套函数,在例子中是 inner_f(), 调用这个函数后,里面的功能就很容易读懂了! func()也就是被装饰的函数,在例子中是 o() 这个函数。
当然了,不管是装饰器,闭包,都有非常复杂的用法,python内部也提供了很多实用的装饰器,但不管多么复杂,只要懂得了它的原理,更深层的使用只是熟练程度上的问题。 继续进步吧~