Python 中使用 @函数名字
,放在某些函数上面,起到增强它们功能的作用。
def hi(name="piayie"): def greet(): return "now you are in the greet() function" def welcome(): return "now you are in the welcome() function" if name == "pieyie": return greet else: return welcome a = hi() print(a) output: <function hi.<locals>.greet at 0x6fff96c98c8>
注意返回的是 greet 和 welcome,而不是 greet() 和 welcome()。这是因为当你把一对小括号放在后面,这个函数就会执行;然而如果你不放括号在它后面,那它可以被到处传递,并且可以赋值给别的变量而不去执行它。
def hi(): return "hi piayie!" def doSomethingBeforeHi(func): print("I am doing some boring work before executing hi()") print(func()) doSomethingBeforeHi(hi) output: I am doing some boring work before executing hi() hi piayie!
增强函数功能,方便重复调用,但是函数本身的功能的执行也是需要的,并不是说把函数直接变成了另一个函数
装饰器有助于让我们的代码更简短,也更Pythonic。
会使得代码更加简洁,代码的复用性大大提升。
因此,装饰器被广泛使用。Python 中到处都能看到装饰器的身影。
不光在 Python,其他语言如 Java 中,装饰器被称作注解,也被应用广泛。
Python 前端最流行的框架之一 Flask,URL 地址和 controller 层的映射处理函数,就是使用装饰器。
# import Flask,同时创建一个 app: from flask import Flask app = Flask(__name__) #URL 路径 / 与处理函数建立映射关系,正是通过装饰器 app.route 控制层处理响应前端,并返回字符串 hello world 到前端界面。 @app.route('/') def index(): return "hello world" # Python 支持异步编程,从中也能看到装饰器的身影 # 使用装饰器 @asyncio.coroutine,将一个生成器asyncio_open_conn 标记为 coroutine 类型 import asyncio @asyncio.coroutine def asyncio_open_conn(host:str): print("using asyncio builds web connection") connect = yield from asyncio.open_connection(host, 80) print("get connect of %s"%(host,)) loop = asyncio.get_event_loop() connections = [asyncio_open_conn(host) for host in [ 'www.sina.com', 'www.baidu.com']] loop.run_until_complete(asyncio.wait(connections)) loop.close() output: using asyncio builds web connection using asyncio builds web connection get connect of www.sina.com get connect of www.baidu.com
下面介绍几个装饰器例子来理解什么是装饰器
# 定义函数 call_print,它的入参 f 为一个函数,它里面内嵌一个函数 g,并返回函数 g def call_print(f): def g(): print('you\'re calling %s function' % (f.__name__,)) return g