自学内容网 自学内容网

python装饰器

说到python中的装饰器,面试基本都会问到,而我也是每次面试前看一下,工作后长时间不用又会忘记,学习-忘记-学习-忘记。。。干脆整理为文档,以供后续翻阅、回忆起来方便。
这篇文章不太适合初学者,没有太多解释,就直接上代码,初学者建议找寻别的帖子学习~

基于函数的装饰器

# 无参
def decorator(func):
    def wrapper(*arg, **kwargs):
        print('装饰器方法')
        return func(*arg, **kwargs)
    return wrapper

@decorator
def foo():
    print('foo 方法执行')

# 带参
def decor_param(level):    
    def decorator(func):
        def wrapper(*arg, **kwargs):
            if level == 'D':
                print('装饰器方法')
            else:
                print('=======')
            return func(*arg, **kwargs)
        return wrapper
    return decorator

@decor_param(level='Dw')
def foo():
    print('foo 方法执行')

基于类实现的装饰器

# 无参
class Request:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print('num of calls is: {}'.format(self.num_calls))
        return self.func(*args, **kwargs)

# 定义函数时就会调用init方法,但不会执行call方法
@Request
def example():
    print("hello world")
    return 10

# 调用函数时才执行call方法,调用多次执行多次,但init只有1次
example()
example()

# 如果需要通过类形式实现带参数的装饰器,那么会比前面的例子稍微复杂一点。
# 那么在构造函数里接受的就不是一个函数,而是传入的参数。通过类把这些参数保存起来。然后在重载__call__方法是就需要接受一个函数并返回一个函数。
class logging(object):
    def __init__(self, level='INFO'):
        self.level = level
        
    def __call__(self, func): # 接受函数
        def wrapper(*args, **kwargs):
            print("[{level}]: enter function {func}()".format(
                level=self.level,
                func=func.__name__))
            func(*args, **kwargs)
        return wrapper  #返回函数
 
@logging(level='INFO')
def say(something):
    print("say {}!".format(something))

say('SB')

装饰器应用-实现单例模式

def Singleton(cls):
    cls.instance = None

    def _singleton_wrapper(*args, **kargs):
        if cls.instance is None:
            cls.instance = cls(*args, **kargs)
        return cls.instance

    return _singleton_wrapper

@Singleton
class Test():
    pass

a = Test()
b = Test()
print(a is b)  #True

小结

装饰器必须接受一个callable对象,其实它并不关心你返回什么,可以是另外一个callable对象(大部分情况),也可以是其他类对象,比如property。

参考资料

详解python装饰器


原文地址:https://blog.csdn.net/weixin_50652063/article/details/144013388

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!