1. 我是皮皮虾首页
  2. 编程开发
  3. 后端
  4. Python

python后端开发面试-装饰器

装饰器在python中是经常用到的,装饰器顾名思义是装饰的作用,其实就是一个函数把另外一个函数当作参数而已

函数装饰器

无参数装饰器

需要注意的是

  1. @cost_time # 装饰没有参数的时候不要写成@cost_time(),带括号表示有参数
  2. 下面装饰器使用等价于cost_time(main)()
import time

'''
    无参数
    func参数默认放在最外层
'''

def cost_time(func): # 不带参数
    def inner(*args,**kwargs):
        t1 = time.time()
        data = func(*args,**kwargs)
        print("cost time:", time.time() - t1)
        return data
    return inner

@cost_time # 装饰没有参数的时候不要写成@cost_time(),带括号表示有参数
def main():
    time.sleep(1)

main()

带参数装饰器

需要注意的是

  1. 带参数带装饰器函数外面需要多包裹一成,原因是参数需要占用一成
  2. 装饰器作用等价于:cost_time(arg=’1′)(test_arg)()
'''
 有参数装饰器
 需要多包裹一成,原因是参数需要占用一成
 装饰器作用等价于:cost_time(arg='1')(test_arg)()
'''
def cost_time(arg):
    def middle(func):
        def inner(*args,**kwargs):
            t1 = time.time()
            print("arg:",arg)
            data = func(*args, **kwargs)
            print("cost time:", time.time() - t1)
            return data
        return inner
    return middle

@cost_time(arg="1")
def main():
    pass


main()

wraps在装饰器中的作用

当函数使用了装饰器之后,函数的一些属性会发生变化,比如函数名,函数__doc__,为了避免函数使用装饰器之后发生属性的变更,wraps就派上用场了,它的作用就是消除装饰器带来的副作用。

下面的函数如果不加@wraps(fun),输出的结果可以自己试试。

def cost_time(arg):
    def middle(func):
        @wraps(func)
        def inner(*args,**kwargs):
            '''
              decorate func
             '''
            t1 = time.time()
            print("arg:",arg)
            data = func(*args, **kwargs)
            print("cost time:", time.time() - t1)
            return data
        return inner
    return middle

@cost_time(arg="1")
def main():
    '''
    main func
    '''
    pass

print(main.__name__,main.__doc__)

输出的结果

python后端开发面试-装饰器

使用类__call__的方式实现装饰器

不带参数的类装饰器

# -*- coding: utf-8 -*-
# @Time    : 2020/7/27 11:29 上午
# @Author  : wsppx
# @File    : c1.py
# @Software: PyCharm
import time
from functools import wraps


class CostTime:
    def __init__(self):
        pass
    def __call__(self, func):
        '''
        类实现了这个方法,相当于把这个类型的对象当作函数来使用。
        '''
        @wraps(func)
        def inner(*args, **kwargs):
            print("use call:")
            t1 = time.time()
            data = func(*args, **kwargs)
            print("cost time:", time.time() - t1)
            return data
        return inner


@CostTime()
def main():
    time.sleep(0.5)


main()

class A():
    @CostTime()
    def say(self):
        print("hello")

    def pick(self):
        print("pick you")

a = A()
a.say()
a.pick()


也可以用最简单的方式

import time

class CostTime:
    def __init__(self,func):
        print("init class")
        self.func = func
    def __call__(self, *args, **kwargs):
        '''
        类实现了这个方法,相当于把这个类型的对象当作函数来使用。
        '''
        print("use call:")
        t1 = time.time()
        data = self.func(*args, **kwargs)
        print("cost time:", time.time() - t1)
        return data


@CostTime
def main():
    time.sleep(0.5)


main()

print("-"*30)
@CostTime
class A():
    def say(self):
        print("hello")

    def pick(self):
        print("pick you")

a = A()
a.say()
a.pick()

使用类的方式实现装饰器

类装饰器什么时候会用到呢?当你装饰类的时候会用到,当然普通函数也可以,但是如果设计到

class CostTime:
    def decorate(self,func):
        @wraps(func)
        def inner(*args, **kwargs):
            t1 = time.time()
            data = func(*args, **kwargs)
            print("cost time:", time.time() - t1)
            return data
        return inner

    @staticmethod
    def static_decorate(func):
        def innert(*args,**kwargs):
            data = func(*args,**kwargs)
            return data
        return innert

ct = CostTime()
class A(object):
    @ct.decorate # 实例方法装饰
    def say(self):
        print("hello")

    @CostTime.static_decorate # 类静态方法装饰
    def pick(self):
        print("pick you")

a = A()
a.say()
a.pick()

@ct.decorate # 实例方法装饰普通函数
def main():
    time.sleep(0.5)
main()

原创文章,作者:站长,如若转载,请注明出处:https://wsppx.cn/631/%e7%bd%91%e7%bb%9c%e5%bc%80%e5%8f%91/%e5%90%8e%e7%ab%af/

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

<