返回26/1002301_77888392Python 语法首先被转换成抽象语法树Abstract Syntax TreeAST然后才被编译成字节码。这是对源代码抽象语法结构的一种树状表示。利用内置的 ast 模块可以得到对Python 语法的处理过程。利用带有 ast.PyCF_ONLY_AST 标记的 compile()函数或者利用 ast.parse()帮助函数可以创建 Python 代码的原始 AST。逆向直接转换却没有那么简单没有用于完成这项功能的内置函数。不过有些项目例如 PyPy可以完成这项任务。ast 模块提供了一些帮助函数可以用于处理 AST如下所示tree ast.parse(def hello_world(): print(“hello world!”))treeast.Module object at 0x00000000038E9588ast.dump(tree)Module(body[FunctionDef(namehelloworld’,argsarguments(args[],varargNone,kwonlyargs[],kwdefaults[],kwargNone,defaults[]),body[Expr(valueCall(funcName(id‘print’, ctxLoad()),args[Str(s‘hello world!’)],keywords[]))],decorator_list[],returnsNone)])在上一个例子中对 ast.dump()的输出做了重新格式化以提高其可读性并且更好地展示 AST 的树状结构。在传递给 compile()调用之前可以对 AST 进行修改知道这一点很重要。例如新的语法节点可用于额外的测量例如计算测试覆盖率。也可以修改现有代码树以便向现有语法中添加新的语义。MacroPy 项目https://github.com/lihaoyi/macropy就用到了这样的技术利用已经存在的语法向 Python 中添加语法宏也可以用纯人工的方式创建 AST不需要解析任何源代码。这样 Python 程序员就能够为自定义的领域特定语言创建 Python 字节码甚至在 Python VM 之上完全实现另一种现有的编程语言。导入钩子利用 MacroPy 的能力修改原始 AST并不像使用 import macropy.activate 语句那样简单如果它不能以某种方式覆写 Python 的导入行为的话。幸运的是Python 提供了利用两种导入钩子import hook来拦截导入的方法。• 元钩子meta hook它在任何其他 import 处理之前被调用。利用元钩子你可以覆写 sys.path 的处理方式甚至是冻结模块frozen module和内置模块。为了添加新的元钩子必须向 sys.meta_path 列表中添加新的元路径查找器meta path finder对象。• 导入路径钩子import path hook它是作为 sys.path 处理的一部分被调用的。如果遇到了与给定钩子相关联的路径项则使用这种钩子。通过使用新的路径查找器path finder对象扩展 sys.path_hooks 列表来添加导入路径钩子。路径查找器和元路径查找器的实现细节在 Python 官方文档中都有详细说明https://docs.python.org/3/reference/import.html。如果你想要在这个层面上处理导入问题那么官方文档应该是你的首选资料。这是因为 Python 的导入机制相当复杂任何尝试用几个段落进行总结的方法最终不可避免会失败。你可以将本节当作这些可能做法的笔记也可以当作更详细资料的参考。使用代码生成模式的项目很难找到一个真正可用的库的实现它依赖代码生成模式而又不仅是一项实验或简单的概念证明。造成这种情况的原因是显而易见的如下所示。• 对 exec()和 eval()函数必要的担心因为不负责任的使用可能会造成真正的灾难。• 成功的代码生成非常困难因为它需要对语言特性的深入理解和优异的通用编程技能。尽管有这些困难但仍有一些项目成功地应用了这种方法或者提高了性能或者实现了其他方法无法实现的事情。1falcon 的编译路由器falcon 是一个极简的 Python WSGI Web 框架用于构建快速又轻量级的 API。它极力推崇目前在Web上非常流行的REST架构风格。它是对其他大型框架如Django或Pyramid的很好的替代。对于其他致力于精简的微框架如 Flask、Bottle 和 Web2py而言它也是一个强大的竞争对手。其特性之一就是非常简单的路由机制。它不像 Django 的 urlconf 提供的路由那样复杂也没有提供那么多的功能但在大多数情况下对于遵照 REST 架构设计的 API 都是够用的。关于 falcon 的路由最有趣的是实际的路由器是利用路由列表生成的代码来实现的这些路由列表被提供给定义 API 配置的对象。这种方法使路由的速度很快。思考下面这个非常简短的 API 示例来自于 falcon 的网上文档sample.pyimport falconimport jsonclass QuoteResource:def on_get(self, req, resp):“”“Handles GET requests”“”quote {‘quote’: ‘I’ve always been more interested in ’‘the future than in the past.’,‘author’: ‘Grace Hopper’}resp.body json.dumps(quote)api falcon.API()api.add_ _route(’/quote’, QuoteResource())加粗的代码是对 api.add_route()方法的调用简而言之就是更新整个动态生成的路由器代码树利用 compile()进行编译并利用 eval()生成新的路由查找函数。观察 api._router._find()函数的__code__属性可以发现它是从字符串中生成的每次调用 api.add_route()都会发生如下改变api._router._find. _code __code object find at 0x00000000033C29C0, file “”, line 1api.addroute(‘/none’, None)api.router._find. __code __code object find at 0x00000000033C2810, file “”, line 1Python 语法首先被转换成抽象语法树Abstract Syntax TreeAST然后才被编译成字节码。这是对源代码抽象语法结构的一种树状表示。利用内置的 ast 模块可以得到对Python 语法的处理过程。利用带有 ast.PyCF_ONLY_AST 标记的 compile()函数或者利用 ast.parse()帮助函数可以创建 Python 代码的原始 AST。逆向直接转换却没有那么简单没有用于完成这项功能的内置函数。不过有些项目例如 PyPy可以完成这项任务。ast 模块提供了一些帮助函数可以用于处理 AST如下所示tree ast.parse(def hello_ world(): print(“hello world!”)) tree ast.Module object at 0x00000000038E9588 ast.dump(tree) Module( body[ FunctionDef( namehello world’, argsarguments( args[], varargNone, kwonlyargs[], kw defaults[], kwargNone, defaults[] ), body[ Expr( valueCall( funcName(id‘print’, ctxLoad()), args[Str(s‘hello world!’)], keywords[] ) ) ], decorator _list[], returnsNone ) ] ) 在上一个例子中对 ast.dump()的输出做了重新格式化以提高其可读性并且更 好地展示 AST 的树状结构。在传递给 compile()调用之前可以对 AST 进行修改知道 这一点很重要。例如新的语法节点可用于额外的测量例如计算测试覆盖率。也可以修 改现有代码树以便向现有语法中添加新的语义。MacroPy 项目https://github.com/lihaoyi/ macropy就用到了这样的技术利用已经存在的语法向 Python 中添加语法宏也可以用纯人工的方式创建 AST不需要解析任何源代码。这样 Python 程序员就能够 为自定义的领域特定语言创建 Python 字节码甚至在 Python VM 之上完全实现另一种现有 的编程语言。 导入钩子 利用 MacroPy 的能力修改原始 AST并不像使用 import macropy.activate 语句 那样简单如果它不能以某种方式覆写 Python 的导入行为的话。幸运的是Python 提供了 利用两种导入钩子import hook来拦截导入的方法。 • 元钩子meta hook它在任何其他 import 处理之前被调用。利用元钩子你可以覆写 sys.path 的处理方式甚至是冻结模块frozen module和内置模块。 为了添加新的元钩子必须向 sys.meta_path 列表中添加新的元路径查找器 meta path finder对象。 • 导入路径钩子import path hook它是作为 sys.path 处理的一部分被调用的。 如果遇到了与给定钩子相关联的路径项则使用这种钩子。通过使用新的路径查找 器path finder对象扩展 sys.path_hooks 列表来添加导入路径钩子。 路径查找器和元路径查找器的实现细节在 Python 官方文档中都有详细说明https://docs. python.org/3/reference/import.html。如果你想要在这个层面上处理导入问题那么官方文档 应该是你的首选资料。这是因为 Python 的导入机制相当复杂任何尝试用几个段落进行总 结的方法最终不可避免会失败。你可以将本节当作这些可能做法的笔记也可以当作更详 细资料的参考。 使用代码生成模式的项目 很难找到一个真正可用的库的实现它依赖代码生成模式而又不仅是一项实验或简 单的概念证明。造成这种情况的原因是显而易见的如下所示。 • 对 exec()和 eval()函数必要的担心因为不负责任的使用可能会造成真正的灾难。 • 成功的代码生成非常困难因为它需要对语言特性的深入理解和优异的通用编程技能。 尽管有这些困难但仍有一些项目成功地应用了这种方法或者提高了性能或者实 现了其他方法无法实现的事情。 1falcon 的编译路由器 falcon 是一个极简的 Python WSGI Web 框架用于构建快速又轻量级的 API。它极力 推崇目前在Web上非常流行的REST架构风格。它是对其他大型框架如Django或Pyramid 的很好的替代。对于其他致力于精简的微框架如 Flask、Bottle 和 Web2py而言它也 是一个强大的竞争对手。 其特性之一就是非常简单的路由机制。它不像 Django 的 urlconf 提供的路由那样复 杂也没有提供那么多的功能但在大多数情况下对于遵照 REST 架构设计的 API 都是 够用的。关于 falcon 的路由最有趣的是实际的路由器是利用路由列表生成的代码来实现 的这些路由列表被提供给定义 API 配置的对象。这种方法使路由的速度很快。 思考下面这个非常简短的 API 示例来自于 falcon 的网上文档sample.pyimport falconimport jsonclass QuoteResource:def on_get(self, req, resp):“”“Handles GET requests”“”quote {‘quote’: ‘I’ve always been more interested in ’‘the future than in the past.’,‘author’: ‘Grace Hopper’}resp.body json.dumps(quote)api falcon.API()api.add_ _route(’/qu利用 eval()生成新的路由查找函数。观察 api._router._find()函数的__code__属性可以发现它是从字符串中生成的每次调用 api.add_route()都会发生如下改变api._ router. _find. _code __ code object find at 0x00000000033C29C0, file “”, line 1 api.add route(‘/none’, None) api. router. _find. __code __ code object find at 0x00000000033C2810, file “”, line 1Markdown 已选中 2787 字数 100 行数 当前行 100, 当前列 0HTML 2735 字数 98 段落
Python 高手编程系列四百三十四:抽象语法树
返回26/1002301_77888392Python 语法首先被转换成抽象语法树Abstract Syntax TreeAST然后才被编译成字节码。这是对源代码抽象语法结构的一种树状表示。利用内置的 ast 模块可以得到对Python 语法的处理过程。利用带有 ast.PyCF_ONLY_AST 标记的 compile()函数或者利用 ast.parse()帮助函数可以创建 Python 代码的原始 AST。逆向直接转换却没有那么简单没有用于完成这项功能的内置函数。不过有些项目例如 PyPy可以完成这项任务。ast 模块提供了一些帮助函数可以用于处理 AST如下所示tree ast.parse(def hello_world(): print(“hello world!”))treeast.Module object at 0x00000000038E9588ast.dump(tree)Module(body[FunctionDef(namehelloworld’,argsarguments(args[],varargNone,kwonlyargs[],kwdefaults[],kwargNone,defaults[]),body[Expr(valueCall(funcName(id‘print’, ctxLoad()),args[Str(s‘hello world!’)],keywords[]))],decorator_list[],returnsNone)])在上一个例子中对 ast.dump()的输出做了重新格式化以提高其可读性并且更好地展示 AST 的树状结构。在传递给 compile()调用之前可以对 AST 进行修改知道这一点很重要。例如新的语法节点可用于额外的测量例如计算测试覆盖率。也可以修改现有代码树以便向现有语法中添加新的语义。MacroPy 项目https://github.com/lihaoyi/macropy就用到了这样的技术利用已经存在的语法向 Python 中添加语法宏也可以用纯人工的方式创建 AST不需要解析任何源代码。这样 Python 程序员就能够为自定义的领域特定语言创建 Python 字节码甚至在 Python VM 之上完全实现另一种现有的编程语言。导入钩子利用 MacroPy 的能力修改原始 AST并不像使用 import macropy.activate 语句那样简单如果它不能以某种方式覆写 Python 的导入行为的话。幸运的是Python 提供了利用两种导入钩子import hook来拦截导入的方法。• 元钩子meta hook它在任何其他 import 处理之前被调用。利用元钩子你可以覆写 sys.path 的处理方式甚至是冻结模块frozen module和内置模块。为了添加新的元钩子必须向 sys.meta_path 列表中添加新的元路径查找器meta path finder对象。• 导入路径钩子import path hook它是作为 sys.path 处理的一部分被调用的。如果遇到了与给定钩子相关联的路径项则使用这种钩子。通过使用新的路径查找器path finder对象扩展 sys.path_hooks 列表来添加导入路径钩子。路径查找器和元路径查找器的实现细节在 Python 官方文档中都有详细说明https://docs.python.org/3/reference/import.html。如果你想要在这个层面上处理导入问题那么官方文档应该是你的首选资料。这是因为 Python 的导入机制相当复杂任何尝试用几个段落进行总结的方法最终不可避免会失败。你可以将本节当作这些可能做法的笔记也可以当作更详细资料的参考。使用代码生成模式的项目很难找到一个真正可用的库的实现它依赖代码生成模式而又不仅是一项实验或简单的概念证明。造成这种情况的原因是显而易见的如下所示。• 对 exec()和 eval()函数必要的担心因为不负责任的使用可能会造成真正的灾难。• 成功的代码生成非常困难因为它需要对语言特性的深入理解和优异的通用编程技能。尽管有这些困难但仍有一些项目成功地应用了这种方法或者提高了性能或者实现了其他方法无法实现的事情。1falcon 的编译路由器falcon 是一个极简的 Python WSGI Web 框架用于构建快速又轻量级的 API。它极力推崇目前在Web上非常流行的REST架构风格。它是对其他大型框架如Django或Pyramid的很好的替代。对于其他致力于精简的微框架如 Flask、Bottle 和 Web2py而言它也是一个强大的竞争对手。其特性之一就是非常简单的路由机制。它不像 Django 的 urlconf 提供的路由那样复杂也没有提供那么多的功能但在大多数情况下对于遵照 REST 架构设计的 API 都是够用的。关于 falcon 的路由最有趣的是实际的路由器是利用路由列表生成的代码来实现的这些路由列表被提供给定义 API 配置的对象。这种方法使路由的速度很快。思考下面这个非常简短的 API 示例来自于 falcon 的网上文档sample.pyimport falconimport jsonclass QuoteResource:def on_get(self, req, resp):“”“Handles GET requests”“”quote {‘quote’: ‘I’ve always been more interested in ’‘the future than in the past.’,‘author’: ‘Grace Hopper’}resp.body json.dumps(quote)api falcon.API()api.add_ _route(’/quote’, QuoteResource())加粗的代码是对 api.add_route()方法的调用简而言之就是更新整个动态生成的路由器代码树利用 compile()进行编译并利用 eval()生成新的路由查找函数。观察 api._router._find()函数的__code__属性可以发现它是从字符串中生成的每次调用 api.add_route()都会发生如下改变api._router._find. _code __code object find at 0x00000000033C29C0, file “”, line 1api.addroute(‘/none’, None)api.router._find. __code __code object find at 0x00000000033C2810, file “”, line 1Python 语法首先被转换成抽象语法树Abstract Syntax TreeAST然后才被编译成字节码。这是对源代码抽象语法结构的一种树状表示。利用内置的 ast 模块可以得到对Python 语法的处理过程。利用带有 ast.PyCF_ONLY_AST 标记的 compile()函数或者利用 ast.parse()帮助函数可以创建 Python 代码的原始 AST。逆向直接转换却没有那么简单没有用于完成这项功能的内置函数。不过有些项目例如 PyPy可以完成这项任务。ast 模块提供了一些帮助函数可以用于处理 AST如下所示tree ast.parse(def hello_ world(): print(“hello world!”)) tree ast.Module object at 0x00000000038E9588 ast.dump(tree) Module( body[ FunctionDef( namehello world’, argsarguments( args[], varargNone, kwonlyargs[], kw defaults[], kwargNone, defaults[] ), body[ Expr( valueCall( funcName(id‘print’, ctxLoad()), args[Str(s‘hello world!’)], keywords[] ) ) ], decorator _list[], returnsNone ) ] ) 在上一个例子中对 ast.dump()的输出做了重新格式化以提高其可读性并且更 好地展示 AST 的树状结构。在传递给 compile()调用之前可以对 AST 进行修改知道 这一点很重要。例如新的语法节点可用于额外的测量例如计算测试覆盖率。也可以修 改现有代码树以便向现有语法中添加新的语义。MacroPy 项目https://github.com/lihaoyi/ macropy就用到了这样的技术利用已经存在的语法向 Python 中添加语法宏也可以用纯人工的方式创建 AST不需要解析任何源代码。这样 Python 程序员就能够 为自定义的领域特定语言创建 Python 字节码甚至在 Python VM 之上完全实现另一种现有 的编程语言。 导入钩子 利用 MacroPy 的能力修改原始 AST并不像使用 import macropy.activate 语句 那样简单如果它不能以某种方式覆写 Python 的导入行为的话。幸运的是Python 提供了 利用两种导入钩子import hook来拦截导入的方法。 • 元钩子meta hook它在任何其他 import 处理之前被调用。利用元钩子你可以覆写 sys.path 的处理方式甚至是冻结模块frozen module和内置模块。 为了添加新的元钩子必须向 sys.meta_path 列表中添加新的元路径查找器 meta path finder对象。 • 导入路径钩子import path hook它是作为 sys.path 处理的一部分被调用的。 如果遇到了与给定钩子相关联的路径项则使用这种钩子。通过使用新的路径查找 器path finder对象扩展 sys.path_hooks 列表来添加导入路径钩子。 路径查找器和元路径查找器的实现细节在 Python 官方文档中都有详细说明https://docs. python.org/3/reference/import.html。如果你想要在这个层面上处理导入问题那么官方文档 应该是你的首选资料。这是因为 Python 的导入机制相当复杂任何尝试用几个段落进行总 结的方法最终不可避免会失败。你可以将本节当作这些可能做法的笔记也可以当作更详 细资料的参考。 使用代码生成模式的项目 很难找到一个真正可用的库的实现它依赖代码生成模式而又不仅是一项实验或简 单的概念证明。造成这种情况的原因是显而易见的如下所示。 • 对 exec()和 eval()函数必要的担心因为不负责任的使用可能会造成真正的灾难。 • 成功的代码生成非常困难因为它需要对语言特性的深入理解和优异的通用编程技能。 尽管有这些困难但仍有一些项目成功地应用了这种方法或者提高了性能或者实 现了其他方法无法实现的事情。 1falcon 的编译路由器 falcon 是一个极简的 Python WSGI Web 框架用于构建快速又轻量级的 API。它极力 推崇目前在Web上非常流行的REST架构风格。它是对其他大型框架如Django或Pyramid 的很好的替代。对于其他致力于精简的微框架如 Flask、Bottle 和 Web2py而言它也 是一个强大的竞争对手。 其特性之一就是非常简单的路由机制。它不像 Django 的 urlconf 提供的路由那样复 杂也没有提供那么多的功能但在大多数情况下对于遵照 REST 架构设计的 API 都是 够用的。关于 falcon 的路由最有趣的是实际的路由器是利用路由列表生成的代码来实现 的这些路由列表被提供给定义 API 配置的对象。这种方法使路由的速度很快。 思考下面这个非常简短的 API 示例来自于 falcon 的网上文档sample.pyimport falconimport jsonclass QuoteResource:def on_get(self, req, resp):“”“Handles GET requests”“”quote {‘quote’: ‘I’ve always been more interested in ’‘the future than in the past.’,‘author’: ‘Grace Hopper’}resp.body json.dumps(quote)api falcon.API()api.add_ _route(’/qu利用 eval()生成新的路由查找函数。观察 api._router._find()函数的__code__属性可以发现它是从字符串中生成的每次调用 api.add_route()都会发生如下改变api._ router. _find. _code __ code object find at 0x00000000033C29C0, file “”, line 1 api.add route(‘/none’, None) api. router. _find. __code __ code object find at 0x00000000033C2810, file “”, line 1Markdown 已选中 2787 字数 100 行数 当前行 100, 当前列 0HTML 2735 字数 98 段落