标识符@
主要用于函数类的基础上添加一些可重用的额外功能,以提高代码的可重用性和可维护性,就是在不改变函数源代码的情况下为函数添加新功能。
一,在函数中的使用
eg:现在定义一个测定程序运行时间的函数
import time
def calcu_time(func):
start=time.time()
func()
time.sleep(2)
end=time.time()
print(f"spend{end-start-2}")
当我们想要运行一个函数时,并想知道这个函数运行了多长时间时,下面我先写出不用装饰器的情况。
假如我们现在需要知道遍历一到九花了多长时间
import time
def calcu_time(func):
start=time.time()
func()
time.sleep(2)
end=time.time()
print(f"spend{end-start-2}")
def text():
for i in range(1,10):
print(i)
calcu_time(text)
以上就是我们在不加装饰器时所写的代码,现在我写出装载装饰器后的代码,
@calcu_time
def text():
for i in range(1,10)
print(i)
text()
我们可以明显的发现在装载装饰器后代码明显变少,这种方法有利于减小内存,增加代码可读性。
1
2
3
4
5
6
7
8
9
0.00869
以上是运行结果,相当于给text()加上了calcu_time的功能。并且在text被调用时装饰器就会被出发运行。
参考 http://t.csdn.cn/QXRD8http://t.csdn.cn/QXRD8
这位博主的最后的例子很好的说明了装饰器的触发时间,下面我做略微的解释
def dec1(func):
print("1111")
def one():
print("2222")
func()
print("3333")
return one
def dec2(func):
print("aaaa")
def two():
print("bbbb")
func()
print("cccc")
return two
@dec1
@dec2
def test():
print("test test")
test()
下面是运行结果
aaaa
1111
2222
bbbb
test test
cccc
3333
首先代码是由上至下运行的
相当于text=dec1(dec2(text))
代码由内向外运行,所以先运行dec2(text)
首先dec(func‘)中的func’为text,所以打印了aaaa,接着运行结束返回了two,所以此时的func“为two,dec2(text)运行完了后,成为了dec1(two)打印出了1111,运行完了后return one 回到函数调用处,运行one函数打印出了2222,two的上一级函数是two,所以在one函数中的func()运行了two函数打印出了bbbb,紧接着到了two函数的func()处,two的上一次函数为text,所以运行了text text,执行完后返回调用处,继续执行打印出来了cccc,two()函数运行完成返回调用处,执行了3333,自此整个程序执行完毕。
他的实质其实就是一个套娃 dec1(dec2(text))->dec1(text(two))->text(two(one)),执行完成。
如果还有人看不懂可以在评论区提问,或者复制代码去pycharm打断点然后打开debugger模式,可以看看函数执行的演变过程。
二,在类中的使用
在类中可以将装饰器应用于类方法与静态方法的构建。
1,类方法的构建
calss demo:
@classmethod
def cls_md(cls):
print(cls)
d=demo()
d.cls_md()
输出:
<class'_ _main_ _.demo'>
自建参数不再是self,而是cls,代指类,即为类的本身。
2,静态方法
当无关类和对象时使用,通过在方法上添加@staticmethod来实现,并被保存在该函数所在的类中。
我下面举一个静态方法的例子
import time
class time text:
@staticmethod
def show_time():
print(time.strftime("%y:%m:%d"),time.localtime)
t=time text()
t.show_time()
输出
2022:10:19
我们可以发现定义的show_time函数没有任何参数,与类和对象没有关系,故被称为静态方法,这种方法可以在一定条件上节约内存,增强代码可读性。