python中自带的三个装饰器_python中的装饰器

0、闭包

想要理解python中的装饰器,先需要理解何为闭包,解释如下:

定义:在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。

例子:

# print_msg是外围函数

defprint_msg():

msg = "I'm closure"

# printer是嵌套函数

defprinter():

print(msg)

returnprinter

# 这里获得的closure就是一个闭包

closure =print_msg()

# 输出 I'm closure

closure()

1、函数装饰器

定义:用于扩展原函数功能的一种函数。(它的本质是嵌套函数)

用途:Python的装饰器广泛应用于缓存、权限校验(如django中的@login_required和@permission_required装饰器)、性能测试(比如统计一段程序的运行时间)和插入日志等应用场景。有了装饰器,我们就可以抽离出大量与函数功能本身无关的代码,增加一个函数的重用性。

比如有这样一个应用场景:试想你写了很多程序,一直运行也没啥问题。有一天老板突然让你统计每个程序都运行了多长时间并比较下运行效率。此时如果你去手动修改每个程序的代码一定会让你抓狂,而且还破坏了那些程序的重用性。聪明的程序员是绝不能干这种蠢事的。此时你可以编写一个@time_it的装饰器(代码如下所示)。如果你想打印出某个函数或程序运行时间,只需在函数前面@一下,是不是很帅?

例子,见下面这个计时的函数:

importtime

defdeco(func):

start_time =time.time()

f()

end_time =time.time()

execution_time = (end_time - start_time)*1000

print("time is %d ms" %execution_time)

deff():

print("hello")

time.sleep(1)

print("world")

if __name__ == '__main__':

deco(f)

print("f.__name__ is",f.__name__)

print()

这里我们定义了一个函数deco,它的参数是一个函数,然后给这个函数嵌入了计时功能。但是想要拓展这一千万个函数功能,

就是要执行一千万次deco()函数,所以这样并不理想!接下来,我们可以试着用装饰器来实现,先看看装饰器最原始的面貌。

importtime

defdeco(f):

defwrapper():

start_time =time.time()

f()

end_time =time.time()

execution_time = (end_time - start_time)*1000

print("time is %d ms" %execution_time )

returnwrapper

@deco

deff():

print("hello")

time.sleep(1)

print("world")

if __name__ == '__main__':

f()

这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。

其中作为参数的这个函数f()就在返回函数wrapper()的内部执行。然后在函数f()前面加上@deco,

f()函数就相当于被注入了计时功能,现在只要调用f(),它就已经变身为“新的功能更多”的函数了,

(不需要重复执行原函数)。

扩展1:带有固定参数的装饰器

importtime

defdeco(f):

defwrapper(a,b):

start_time =time.time()

f(a,b)

end_time =time.time()

execution_time = (end_time - start_time)*1000

print("time is %d ms" %execution_time)

returnwrapper

@deco

deff(a,b):

print("be on")

time.sleep(1)

print("result is %d" %(a+b))

if __name__ == '__main__':

f(3,4)

扩展2:无固定参数的装饰器

importtime

defdeco(f):

def wrapper(*args, **kwargs):

start_time =time.time()

f(*args, **kwargs)

end_time =time.time()

execution_time_ = (end_time - start_time)*1000

print("time is %d ms" %execution_time)

returnwrapper

@deco

deff(a,b):

print("be on")

time.sleep(1)

print("result is %d" %(a+b))

@deco

deff2(a,b,c):

print("be on")

time.sleep(1)

print("result is %d" %(a+b+c))

if __name__ == '__main__':

f2(3,4,5)

f(3,4)

扩展3:使用多个装饰器,装饰一个函数

importtime

defdeco01(f):

def wrapper(*args, **kwargs):

print("this is deco01")

start_time =time.time()

f(*args, **kwargs)

end_time =time.time()

execution_time = (end_time - start_time)*1000

print("time is %d ms" %execution_time)

print("deco01 end here")

returnwrapper

defdeco02(f):

def wrapper(*args, **kwargs):

print("this is deco02")

f(*args, **kwargs)

print("deco02 end here")

returnwrapper

@deco01

@deco02

deff(a,b):

print("be on")

time.sleep(1)

print("result is %d" %(a+b))

if __name__ == '__main__':

f(3,4)

输出为:

'''

this is deco01

this is deco02

hello,here is a func for add :

result is 7

deco02 end here

time is 1003 ms

deco01 end here

'''

2、内置装饰器

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用

classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)

property 是属性的意思,表示可以通过通过类实例直接访问的信息

这里介绍一下property装饰器:

注意,对于Python新式类(new-style class),如果将上面的 “@var.setter” 装饰器所装饰的成员函数去掉,则Foo.var 属性为只读属性,使用 “foo.var = ‘var 2′” 进行赋值时会抛出异常。但是,对于Python classic class,所声明的属性不是 read-only的,所以即使去掉”@var.setter”装饰器也不会报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值