lambda,闭包,装饰器的理解和参悟

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内部也提供了很多实用的装饰器,但不管多么复杂,只要懂得了它的原理,更深层的使用只是熟练程度上的问题。  继续进步吧~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值