首页 > Python 的装饰器如何既支持 @deco 也支持 @deco(p) 调用?

Python 的装饰器如何既支持 @deco 也支持 @deco(p) 调用?

def deco(*args):
    def _deco(func):
        def __deco():
            print("before %s called [%s]." % (func.__name__, args))
            func()
            print("  after %s called [%s]." % (func.__name__, args))
        return __deco
    return _deco

@deco("mymodule")  # 可用
def myfunc():
    print(" myfunc() called.")

@deco()   # 也可用
def myfunc2():
    print(" myfunc2() called.")

@deco   # 报错 TypeError: _deco() takes exactly 1 argument
def myfunc3():
    print(" myfunc2() called.")

myfunc()
myfunc2()
myfunc3()

没有参数的 @deco 其实就是 deco(myfunc3),所以需要对参数做个判断就行。

import types

def deco(*args):
    def _deco(func):
        def __deco():
            print("before %s called [%s]." % (func.__name__, args))
            func()
            print("  after %s called [%s]." % (func.__name__, args))
        return __deco

    # 当直接使用 @deco 定义的时候第一个参数为函数
    if len(args) == 1 and type(args[0]) is types.FunctionType:
        return _deco(args[0])

    return _deco

def decorator(func_text):

    def decorator1(func):

        def wapper(*args, **kw):

            print 'before func...%s' % func_text

            func(*args, **kw)

            print 'after func...%s' % func_text

        return wapper   



    def decorator2(*args, **kw):

        print "before...%s" % func_text.__name__

        func_text(*args, **kw)

        print "after...%s" % func_text.__name__



    if hasattr(func_text, '__call__'):

        return decorator2

    else:

        return decorator

@decorator
def foo2(a,b):

print a

print b

print "foo2"



@decorator('decorator')
def foo3(a,b):
print a

print b

print "foo3"



foo2('a', 'b')

foo3('a', 'b')

@deco 和 @deco()是不一样的

【热门文章】
【热门文章】