目录
Python中的装饰器
高阶函数的举例
装饰器
带参数的装饰器
Python中的链接装饰器
Python中的装饰器
Python有一个有趣的功能,称为装饰器,可以向现有代码添加功能。
这也称为元编程,因为程序的一部分试图在编译时修改程序的另一部分。
Python中的所有内容(是!甚至是类)都是对象。我们定义的名称只是绑定到这些对象的标识符。函数也不例外,它们也是对象(带有属性)。
"""
first和second指代相同的功能对象。可以将函数作为参数传递给另一个函数。将其他函数作为参数的此类函数也称为高阶函数
"""
def first(msg):
print(msg)
first("Hello") # Hello
second = first # second 是高阶函数
second("Hello") # Hello
高阶函数的举例
def inc(x):
return x + 1
def dec(x):
return x - 1
def operate(func, x):
result = func(x)
return result
# is_returned()是一个嵌套函数,它在每次调用时都定义并返回is_called()
def is_called():
print('111')
def is_returned():
print("Hello")
return is_returned
if __name__ == '__main__':
# 可以将函数作为参数传递给另一个函数
o1 = operate(inc, 3)
o2 = operate(dec, 3)
print(o1) # 4
print(o2) # 2
# 一个函数可以返回另一个函数
new1 = is_called() # 111
print(new1) # <function is_called.<locals>.is_returned at 0x00000248F32738B8>
new2 = new1() # Hello
print(new2) # None
# 111
# <function is_called.<locals>.is_returned at 0x00000248F32738B8>
# Hello
# None
函数和方法是可以被调用。基本上,装饰器接受一个函数,添加一些功能并返回它。
装饰器
# 函数和方法被称为可调用的,因为它们可以被调用
# 基本上,装饰器接受一个函数,添加一些功能并返回它
def make_pretty(func):
def inner():
print("I got decorated")
func()
return inner
def ordinary():
print("I am ordinary")
if __name__ == '__main__':
ordinary() # I am ordinary
pretty = make_pretty(ordinary) # 将一个函数作为参数传给新的函数
pretty() # make_pretty返回一个函数,()实例化它
# I got decorated
# I am ordinary
# 这里make_pretty()是一个装饰器
# 函数ordinary()得到了装饰,并返回的新的函数pretty
# 我们可以看到装饰器函数在原始函数中添加了一些新功能。print("I got decorated")
# 这类似于包装礼物。装饰器充当包装器。装饰的对象(内部实际礼物)的性质不会改变。但是现在,它看起来很漂亮(因为它已经被装饰了)。
# 通常,我们装饰一个函数并将其重新分配为
# ordinary = make_pretty(ordinary)
# This is a common construct and for this reason, Python has a syntax to simplify this.
带参数的装饰器
def divide(a, b):
return a/b
def smart_divide(func):
def inner(a, b):
print("I am going to divide", a, "and", b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a, b)
return inner
@smart_divide
def divide(a, b):
print(a/b)
if __name__ == '__main__':
# 调用divide()函数时,实际是调用smart_divide(divide(2,5)),实质是调用inner()函数
divide(2, 5) # ==inner()
divide(2,0)
"""
I am going to divide 2 and 5
0.4
I am going to divide 2 and 0
Whoops! cannot divide
"""
inner()装饰器内部的嵌套函数的参数与其装饰的函数的参数相同。考虑到这一点,现在我们可以使通用装饰器可以使用任意数量的参数。
在Python中,这种魔术是通过完成的function(*args, **kwargs)。这样,args将成为位置参数的元组,kwargs并将成为关键字参数的字典。这样的装饰器的一个例子是:
def works_for_all(func):
def inner(*args, **kwargs):
print("I can decorate any function")
return func(*args, **kwargs)
return inner
Python中的链接装饰器
这就是说,一个功能可以用不同(或相同)的装饰器多次装饰。我们只需将装饰器放置在所需功能之上。
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
def percent(func):
def inner(*args, **kwargs):
print("%" * 30)
func(*args, **kwargs)
print("%" * 30)
return inner
@star
@percent
def printer(msg):
print(msg)
# ==
# printer = star(percent(printer))
if __name__ == '__main__':
printer("Hello")