今天谈一谈Python的装饰器

在Python中装饰器的作用就是在不改变原来函数代码的情况下,扩展函数功能的一种函数,因此,装饰器本身也是一种函数,因为它本身返回的就是一个函数。

最朴素的装饰器

首先,我们定义一个函数,并在这函数里头嵌入计时的功能
这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数func()前面加上@deco,func()函数就相当于被注入了计时功能,现在只要调用func(),它就已经变身为“新的功能更多”的函数了。
所以这里装饰器就像一个注入符号@:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。

import time

def deco(func):
    def wrapper():
        startTime = time.time()
        func()
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper

@deco
def func():
    print("hello")
    time.sleep(1)
    print("world")

test = func
test()

在使用装饰器中,我们可以通过在函数上方写入@deco的方法调用,也可以通过func = deco(func)的方式使用。

嵌套装饰器

如果我们想使用多个装饰器来装饰同一个函数(也就是一个函数被赋予多个功能)这也是可以实现:


import time

def deco01(func):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
        print("deco01 end here")
    return wrapper

def deco02(func):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        func(*args, **kwargs)

        print("deco02 end here")
    return wrapper

@deco01
@deco02
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

f = func
f(3,4)

注意的是:当多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身。

带参数的装饰器

当我们需要在装饰器中加入参数,注意这不是在被装饰的函数中加入参数。我们可以采用多一个闭包,也就是多一层的嵌套:

def outermost(*args):
	def out(func):
		print ("装饰器参数{}".format(args))
		def inner(*args):
			print("innet start")
			func(*args)
			print ("inner end")
		return inner
	return out

@outermost("我是装饰器参数")
def myfun(*args):
	print ("试试装饰器和函数都带参数的情况,被装饰的函数参数{}".format(args))

myfun("我是被装饰的参数")

内置的装饰器

在Python中,普通的一个类也是一个对象,所以当我们直接使用这一个类的时候可以不去实例化一个对象而直接通过类本身去调用它其中的方法。

class test(object):
    def fun1(self, n):
        print("self:", self)

    @classmethod
    def fun2(cls, n):
        print("cls:", cls)

    @staticmethod
    def fun3(n):
        pass

a = test()
a.fun1(1) # self: <__main__.A object at 0x000001E596E41A90>
A.fun2(1) # cls: <class '__main__.A'>
A.fun3(1)

可看出来,当我们直接用staticmethod这个装饰器修饰类中方法的时候,可以不传入self这个参数,也可以不实例化一个对象出来去调用其中的方法;这就好像C++中的static成员、函数,它属于类,而不属于任何一个对象。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护,节省了实例化对象的开销成。
classmethod类似,也可以节省实例化对象的开销成本,它也不需要传入self这个参数,但是它需要传入cls的这个参数进去。当使用了@classmethod的时候,这个方法就默认为类方法,可以通过类直接去调用。
当需要使用到类中属性的时候,就使用classmethod,如果没有涉及到类中属性问题的时候,就使用staticmethod这个方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值