Python学习之装饰器
装饰器就是修改其他函数功能的函数。
学习装饰器,需要一步一步来解析(涉及前面的函数知识)
函数对象
由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。
函数对象有一个__name__属性,可以拿到函数的名字
# 函数 def hello(name="python"): return "hello " + name # 直接调用函数 print(hello()) # hello python # 将函数赋值给一个变量 greet = hello print(greet) #<function hello at 0x0000011141F361F0> print(greet()) # hello python print(greet.__name__) # hello
返回函数
在函数中定义另外的函数
# 在函数中返回函数 def subject(name="python"): print("you are inside in the subject() function") def pyth(): return "you are inside in pyth() function" def java(): return "you are inside in java() function" print(pyth()) print(java()) subject()

pyth()函数和java()函数只能在subject()函数里面被调用。
上述例子我们不需要在一个函数里去执行另一个函数,可以将其作为输出返回出来。
def subject(name="python"): def pyth(): return "you are inside in pyth() function" def java(): return "you are inside in java() function" if name == "python": return pyth elif name == "java": return java else: print("没有调用函数里面的函数") f = subject() # 返回的是一个函数 print(f) # <function subject.<locals>.pyth at 0x000001F080F56280> print(f()) # you are inside in pyth() function
函数作为参数传递
将函数作为另外函数的参数传递
def hello(name="python"): return "hello " + name def param(func): print("before hello() function") print(func()) param(hello)

装饰器
如果我们要增加其他功能,在函数前打印日志,又不改变函数的定义,就需要用到装饰器。
所以我们定义一个打印日志的decorator
def log(func): def wrapper(*args, **kwargs): print("call %s()" % func.__name__) # func() return func(*args, **kwargs) return wrapper
使用该decorator
@log def hi(name="python"): print("hi", name) hi()

我们在调用hi()函数时,不仅会运行hi()函数,也会在前面打印日志。
把@log放到了函数hi()的定义处,相当于执行了 hi = log(hi),把hi()函数作为参数传入log()函数中。
如果装饰器本身需要传入参数,又应该怎么做呢?
def log(text): def deco(func): def wrapper(*args, **kwargs): print("call %s %s()" % (text, func.__name__)) # func() return func(*args, **kwargs) return wrapper return deco @log("ex") def hi(name="python"): print("hi", name) hi() print(hi.__name__)

经过decorator装饰之后的函数,__name__属性已经发生改变,已经不是hi,而是wrapper,返回的是wrapper()函数的名字。
所以,需要把原始的__name__属性复制到wrapper()函数中。使用Python内置的functools.wraps。
import functools def log(text): def deco(func): @functools.wraps(func) def wrapper(*args, **kwargs): print("call %s %s()" % (text, func.__name__)) # func() return func(*args, **kwargs) return wrapper return deco @log("ex") def hi(name="python"): print("hi", name) hi() print(hi.__name__)

@functools.wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
记录学习笔记,有其他参考,如有侵权,联系删除
本文来自博客园,作者:rissa,转载请注明原文链接:https://www.cnblogs.com/rissa/p/15101680.html

浙公网安备 33010602011771号