python函数修饰符的使用
python函数修饰符@ 修饰符 ‘@’符号用作函数修饰符是python2.4新增加的功能,修饰符必须出现在函数定义前一行,不允许和函数定义在同一行。也就是说@A def f(): 是非法的。 只可以在模块或类定义层内对函数进行修饰,不允许修修饰一个类。一个修饰符就是一个函数,它将被修饰的函数做为参数,并返回修饰后的同名函数或其它可调用的东西。 本质上讲,装饰符@类似于 回调函数,把其它的函数(暂且称为目的参数,后面紧接着的函数)作为自己的入参,在目的函数执行前,执行一些自己的操作, 比如:计数、打印一些提示信息等,然后返回目的函数。下面列举一个简单的例子。
创建函数修饰符的规则:
(1)修饰符是一个函数
(2)修饰符取被修饰函数为参数
(3)修饰符返回一个新函数
(4)修饰符维护被维护函数的签名
例子1: 被修饰函数不带参数 def log(func): def wrapper(): print("log开始 ...") func() print("log结束 ...") return wrapper @log def test(): print("test ..") test()
运行结果: log开始 ... test .. log结束 ...
例子2: 使用functools模块提供的修改函数属性的方法wraps def log(func): def wrapper(): print("log开始 ...") func() print("log结束 ...") return wrapper @log def test1(): print("test1 ..") def test2(): print("test2 ..") print(test1.__name__) print(test2.__name__)
运行结果: wrapper test2
可见test1的函数名称变了,如果某些代码用到就会出问题,可以使用functools模块提供的修改函数属性的方法wraps from functools import wraps def log(func): @wraps(func) def wrapper(): print("log开始 ...") func() print("log结束 ...") return wrapper @log def test1(): print("test1 ..") def test2(): print("test2 ..") print(test1.__name__) print(test2.__name__)
运行结果: test1 test2
例子3: 被修饰函数带参数 from functools import wraps def log(func): @wraps(func) def wrapper(*args,**kwargs): print("log开始 ...",func.__name__) ret = func(*args,**kwargs) print("log结束 ...") return ret return wrapper @log def test1(s): print("test1 ..", s) return s @log def test2(s1, s2): print("test2 ..", s1, s2) return s1 + s2 test1("a") test2("a","bc")
运行结果: log开始 ... test1 test1 .. a log结束 ... log开始 ... test2 test2 .. a bc log结束 ...
例子4: 修饰符带参数 ,需要比上面例子多一层包装 from functools import wraps def log(arg): def _log(func): @wraps(func) def wrapper(*args,**kwargs): print("log开始 ...",func.__name__, arg) ret = func(*args,**kwargs) print("log结束 ...") return ret return wrapper return _log @log("module1") def test1(s): print("test1 ..", s) return s @log("module1") def test2(s1, s2): print("test2 ..", s1, s2) return s1 + s2 test1("a") test2("a","bc")
运行结果: log开始 ... test1 module1 test1 .. a log结束 ... log开始 ... test2 module1 test2 .. a bc log结束 ...