开发者学堂课程【Python 入门 2020年版:装饰器详解】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/639/detail/10349
装饰器详解
内容介绍
一、 复习上一节内容
二、 装饰器详解
一、复习上一节内容
1、上节讲的装饰器比较简单,当写了装饰器语法后,首先它会自动立刻调用函数,同时把demo函数传给fn参数,fn就指向
demo了,最后cal_time返回来一个inner函数,返回inner函数以后,当你再写demo的时候, demo不再是上面的demo了,而是装饰器函数返回的inner的值,现在写demo的时候其实调的是inner函数。
def cal_time(fn):
def inner():
start= time.time()
fn()
end = time.time()
print('代码耗时',end - start)
return inner
@cal_time
def demo():
x=0
for i in range(1,100000000):
x+=i
print(x)
二、装饰器详解
1、如果有多个函数,比方说有一个foo函数,要计算一下这个代码的执行时间
def foo():
print('hello')
time.sleep(3)
print('world')
如果直接写foo()它只会打印hello world,不会执行时间,因为现在调的是foo函数,要给它加装饰器,装饰完再来调foo。
@cal_time
def foo():
print('hello')
time.sleep(3)
print('world')
foo()
再来执行,就会显示运行时间了。
2、如果要计算代码的执行时长,加一个装饰器就行了,如果不想计算了,再把这个装饰器去掉就行了,去掉之后它就是一个普通函数。
加装饰器这个foo也是inner,可以打印foo:print(‘foo=’,foo)。装饰器是比较高级的用法,而且有一点不太好理解,只要记住这个语法格式就行了,首先第一个要一个外部函数,它需要接收一个参数,这个参数待会会把函数传进来,然后这个外部函数要有一个返回值,返回的是内部函数,以后再调用这个函数的时候它会调inner函数, inner函数里又把fn也就是原来的被装饰的那个函数给调用了。
3、还有一个情况,如果写的不是print x而是return x,
@cal_time
def demo():
x=0
for i in range(1,100000000):
x+=i
return x
demo()
要调一下demo,现在demo里面是有一个返回值的,运行看一下值多少,值算了但是结果拿不到令m=demo(),打印一下m:print(‘m的值是’,m),运行得到结果m是空的,原因是现在的demo已经不再是原来的demo,而是inner,这个inner里没有返回值,所以这个结果就拿不到,加一个s=fn,return s就行了。
def inner():
start= time.time()
s=fn()
end = time.time()
print('代码耗时',end - start)
return s
fn其实指的是原来的demo函数,拿到这个demo函数的执行结果,最后再把它返回回去,这样就拿到了,这个地方不是很难只要记住语法规范就行了。
4、计算1~n的值
@cal_time
def demo(n):
x= 0
for i in range(1, n)
x +=j
return x
m=demo(100000000)
print('m的值是',m)
如果现在运行,结果会报inner多个参数, inner需要0个参数,但是给了一个,要记得demo已经不再是以前的demo,而是inner, inner不需要参数。
所以def inner()里写个参数x就可以了。现在运行fn又会报错了,因为s=fn(),fn才是原来的demo,现在demo需要参数,但是没有给到。
这个参数是1亿传给x,然后再传给fn来进行计算,这个结果就能够算出来了。
5、inner返回的就是1到1亿的所有数字之和,耗时的时间是把它打印出来了,如果想返回两个值的话可以这样写
def inner(x):
start= time.time()
s=fn(x)
end = time.time()
return s, end-start
这样就是返回两个东西,再调demo的时候,m是两个数据,是元组,元组里的第0个数据会是算的和,第一个数据才是耗的时长。
m=demo(100000000)
print('m的值是',m)
只要记住一点,demo在运行时已经不再是原来的demo,而是这个inner函数,拿到的所有结果都看inner函数,它返回什么就是什么。
6、def inner(x) x=100000000,要把1亿传给这个n:
def demo(n),x不是形参,是实参是调用,fn是demo函数,这么写就相当于demo把1亿传进去了。
7、在demo里有一个功能更强大,
m=demo(100000000,'good',y='hello')
print('m的值是',m)
这样写会报错,报错是因为demo现在调的是inner函数,inner只要一个参数,一个参数的话会报错,一般情况下, inner函数装饰完了之后,会这样写一个x,这个x是待会fn调的是要用的。
def inner(x, *args, **kwargs):
这样写就能够传多个参数了,运行一下,现在它就可以传可变参数了,这是装饰器强大的一点,它对原有的函数进行了一个扩充,原有的函数只能传一个参数,现在可以传很多个。