基于类的python装饰器

2019年10月14日 / 13次阅读 / Last Modified 2019年10月14日
语法

python装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重载了__call__()方法,那么这个对象就是callable的。

class call_class():
    def __call__(self):
        print('I am in call_class')

tt = call_class()
tt()

执行结果如下:

$ python3 cc.py
I am in call_class

我们判断一个对象(变量和函数都是对象)是否可调用,其实就是判断这个对象是否含有__call__函数。请参考:用hasattr或callable判断变量是否为函数

__call__这样前后都带下划线的方法在Python中被称为内置方法,有时候也被称为魔法方法。重载这些魔法方法一般会改变对象的内部行为。上面这个例子就让一个类对象拥有了被调用的行为。

回到装饰器上的概念上来,装饰器要求接受一个callable对象,并返回一个callable对象,那么用类来实现也是也可以的。我们可以让类的构造函数__init__()接受一个函数,然后重载__call__()并返回一个函数,也可以达到装饰器函数的效果。

基于前一篇python装饰器基础介绍中的示例代码,我将带参数的装饰器重新写成基于类的形式,代码如下:

class calling_trace():
    def __init__(self, run):
        self.run = run

    def __call__(self, func):
        def wrapper(*args, **kw):
            print('calling', func.__name__)
            if self.run == 1:
                a = func(*args, **kw)
                print('return value:', a)
            else:
                print('not allow to run')
        return wrapper

#def calling_trace(run):
#    def deco(func):
#        def wrapper(*args, **kw):
#            print('calling', func.__name__)
#            if run == 1:
#                a = func(*args, **kw)
#                print('reture value:',a)
#            else:
#                print('not allow to run')
#        return wrapper
#    return deco

# test5 = calling_trace(run=1)(test5)
@calling_trace(run=1)
def test5(a,b,c=3):
    print('test5 is runing...')
    return a+b+c

@calling_trace(run=0)
def test6(*args):
    print('test6 is runing...')
    return sum(args)

test5(1,2)
test5(1,2,c=8)
test6(23,34,45,56)

class calling_trace与注释掉的那个函数,效果是完全一样的。以上代码运行结果是:

$ python3 deco.py
calling test5
test5 is runing...
return value: 6
calling test5
test5 is runing...
return value: 11
calling test6
not allow to run

基于类的python装饰器,代码看起来可能只是稍微简单一点点。

-- EOF --

本文链接:https://www.pynote.net/archives/1318

留言区

《基于类的python装饰器》有1条留言

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

  • 麦新杰

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


前一篇:
后一篇:

More

麦新杰的Python笔记

Ctrl+D 收藏本页


©Copyright 麦新杰 Since 2019 Python笔记

go to top