探讨了异常处理和其他未充分使用但仍然有用的Python功能。这是Python3.x新特性系列的第四篇文章。Python3.3于2012年首次发布,尽管它已经发布了很长时间,但它引入的许多功能都没有得到充分利用,而且非常酷。以下是其中的三个。yieldfromyield关键字使Python更加强大。不出所料,人们开始使用它来创建整个迭代器生态系统。itertools模块和more-itertoolsPyPI包是两个示例。有时新的生成器会想要使用现有的生成器。作为一个简单的(尽管有些人为的)示例,假设您想要枚举所有自然数对。一种方法是按照“自然数对之和,自然数对第一项”的顺序生成所有自然数对。用yieldfrom来实现这个方法是很自然的。yieldfrom关键字的缩写如下:foriteminx:yielditemimportitertoolsdefpairs():forninitertools.count():yieldfrom((i,n-i)foriinrange(n+1))list(itertools.islice(pairs(),6))[(0,0),(0,1),(1,0),(0,2),(1,1),(2,0)]隐式命名空间包假设有一家名为Parasol的虚构公司制造了很多东西。它的大部分内部软件都是用Python编写的。虽然Parasol已经开源了它的一些代码,但其中一些代码过于专有或专业化,无法开源。公司使用内部DevPI服务器来管理内部包。Parasol中的每个Python程序员在PyPI上找到一个未使用的名称是没有意义的,因此所有内部包都称为parasol.<业务部门>.<项目>。按照最佳实践,开发人员希望包名称能够反映此命名系统。这一点很重要!如果parasol.accounting.numeric_tricks包安装了一个名为numeric_tricks的顶级模块,这意味着依赖此包的人将无法使用名为numeric_tricks的PyPI包,无论它写得多么好。然而,这让开发人员陷入两难境地:哪个包拥有parasol/__init__.py文件?从Python3.3开始,最好的解决方案是将parasol和可能的parasol.accounting转换为没有__init__.py文件的命名空间包。抑制异常的上下文有时在从异常恢复期间引发的异常是一个问题,并且有上下文来跟踪它是很有用的。然而,有时情况并非如此:异常已经被处理,新的条件是不同的错误条件。例如,假设在查找字典中的键失败后,如果无法解析它,您希望以ValueError()失败。importtimedefexpensive_analysis(data):time.sleep(10)ifdata[0:1]==">":returndata[1:]returnNone这个函数耗时比较长,所以在使用的时候,想着要缓存结果:缓存={}deflast_letter_analyzed(数据):尝试:分析=缓存[数据]除了KeyError:分析=expensive_analysis(数据)如果分析为无:提高ValueError(“无效数据”,数据)缓存[数据]=分析returnanalyzed[-1]不幸的是,当缓存未命中时,回溯看起来很难看:last_letter_analyzed("stuff")-------------------------------------------------------------------------KeyErrorTraceback(最近调用last)inlast_letter_analyzed(data)4try:---->5analyzed=cache[data]6exceptKeyError:KeyError:'stuff'在处理过程中上述异常的另一个异常发生:ValueErrorTraceback(mostrecentcalllast)---->1last_letter_analyzed("stuff")inlast_letter_analyzed(data)7analyzed=expensive_analysis(data)8如果分析为无:---->9提高ValueError("invaliddata",data)10cached[data]=analyzed11returnanalyzed[-1]ValueError:('invaliddata','stuff')如果你使用raise...fromNone,你可以获得更多可读的返回:deflast_letter_analyzed(data):try:analyzed=cache[data]exceptKeyError:analyzed=expensive_analysis(data)ifanalyzedisNone:raiseValueError("invaliddata",data)fromNonecached[data]=分析返回analyzed[-1]last_letter_analyzed("stuff")---------------------------------------------------------------------------ValueErrorTraceback(最近调用最后)in---->1last_letter_analyzed("stuff")inlast_letter_analyzed(data)5analyzed=expensive_analysis(data)6如果分析是None:---->7raiseValueError("invaliddata",data)fromNone8cached[data]=analyzed9returnanalyzed[-1]ValueError:('invaliddata','stuff')欢迎来到2012Even尽管Python3.3是十年前发布的,但它的许多功能仍然很酷且未得到充分利用。如果您还没有,请将它们添加到您的工具箱中。