- 译者序
- 前言
- 第1章 问答环节
- 第2章 Python 如何运行程序
- 第3章 如何运行程序
- 第4章 介绍 Python 对象类型
- 第5章 数字
- 第6章 动态类型简介
- 第7章 字符串
- 第8章 列表与字典
- 第9章 元组、文件及其他
- 第10章 Python 语句简介
- 第11章 赋值、表达式和打印
- 第12章 if 测试和语法规则
- 第13章 while 和 for 循环
- 第14章 迭代器和解析,第一部分
- 第15章 文档
- 第16章 函数基础
- 第17章 作用域
- 第18章 参数
- 第19章 函数的高级话题
- 第20章 迭代和解析,第二部分
- 第21章 模块:宏伟蓝图
- 第22章 模块代码编写基础
- 第23章 模块包
- 第24章 高级模块话题
- 第25章 OOP:宏伟蓝图
- 第27章 更多实例
- 第28章 类代码编写细节
- 第29章 运算符重载
- 第30章 类的设计
- 第31章 类的高级主题
- 第32章 异常基础
- 第34章 异常对象
- 第35章 异常的设计
- 第36章 Unicode 和字节字符串
- 字符串基础知识
- Python 的字符串类型
- 文本和二进制文件
- Python 3.0 中的字符串应用
- 转换
- 编码 Unicode 字符串
- 编码非ASCII文本
- 编码和解码非ASCII文本
- 其他 Unicode 编码技术
- 转换编码
- 在 Python 2.6 中编码 Unicode 字符串
- 源文件字符集编码声明
- 使用 Python 3.0 Bytes 对象
- 序列操作
- 创建 bytes 对象的其他方式
- 混合字符串类型
- 使用 Python 3.0(和 Python 2.6)bytearray 对象
- 使用文本文件和二进制文件
- Python 3.0 中的文本和二进制模式
- 类型和内容错误匹配
- 使用 Unicode 文件
- 在 Python 3.0 中处理 BOM
- Python 2.6 中的 Unicode 文件
- Python 3.0 中其他字符串工具的变化
- Struct二进制数据模块
- pickle对象序列化模块
- XML解析工具
- 本章小结
- 本章习题
- 习题解答
- 第37章 管理属性
- 第38章 装饰器
- 第39章 元类
- 附录A 安装和配置
- 附录B 各部分练习题的解答
- 作者介绍
- 封面介绍
实现细节
函数内省
已经证实了内省API可以在函数对象以及其拥有我们所需的工具的相关代码对象上实现。第19章简单介绍过这个API,我们在这里实际地使用它。期待的参数名集合只是附加给一个函数的代码对象的前N个变量名:
同样的API在较早的Python中也可以使用,但是,在Python 2.5及更早的版本中,func.__code__attribute拼写为func.func_code in 2.5(为了可移植性,新的__code__属性在Python 2.6中也冗余地可用)。在函数上和代码对象上运行一个dir调用,以了解更多细节。
参数假设
给定期待的参数名的这个集合,该解决方案依赖于Python对于参数传递顺序所施加的两条限制(在Python 2.6和Python 3.0中都仍然成立):
·在调用时,所有的位置参数出现在所有关键字参数之前。
·在def中,所有的非默认参数出现在所有的默认参数之前。
也就是说,在一个调用中,一个非关键字参数通常不会跟在一个关键字参数后面,并且在定义中,一个非默认参数不会跟在一个默认参数后面。在两种位置中,所有的"name=value"语法必须出现在任何简单的"name"之后。
为了简化,我们也可以假设一个调用一般是有效的——例如,所有的参数要么接收值(按照名称或位置),要么将有意忽略而选取默认值。不一定要进行这种假设,因为当包装逻辑测试有效性的时候,函数还没有真正调用——随后包装逻辑调用的时候,调用仍然可能失效,由于不正确的参数传递。只要这不会引发包装器在糟糕地失效,我们可以改进调用的验证。这是有帮助的,因为在调用发生之前验证它,将会要求我们完全模仿Python的参数匹配算法——再一次说明,这对我们的工具来说是一个过于复杂的过程。
匹配算法
现在,给定了这些限制和假设,我们可以用这一算法来考虑调用中的关键字以及忽略的默认参数。当拦截了一个调用,我们可以作如下假设:
·*pargs中的所有N个传递的位置参数,必须与从函数的代码对象获取的前N个期待的参数匹配。对于前面列出的每个Python的调用顺序规则都是如此,因为所有的位置参数在所有关键字参数之前。
·要获取按照位置实际传递的参数的名称,我们可以把所有其他参数的列表分片为长度为N的*pargs位置参数元组。
·前N个期待的参数之后的任何参数,要么是按照关键字传递,要么是调用时候忽略的默认参数。
·对于要验证的每个参数名,如果它在**kargs中,它是按照名称传递的;如果它在前N个期待的参数中,它是按照位置传递的(在这种情况下,它在期待的列表中的相对位置给出了它在*pargs中的相对位置);否则,我们可以假设它是在调用时候忽略的并且默认的参数,不需要检查。
换句话说,对于假设*pargs中前N个实际传递的位置参数,必须与期待的参数列表中的前N个参数匹配,并且任何其他的参数要么必须是按照关键字传送并位于**kargs中,要么必须是默认的参数,我们就可以略过对调用时忽略的参数的测试。在这种方法下,对于最右边的位置参数和最左边的关键字参数之间的、或者在关键字参数之间的、或者在所有的最右边的位置之后的那些忽略掉的参数,装饰器将省略对其检查。可以跟踪装饰器及其测试脚本,看看这是如何在代码中实现的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论