为了更清晰的条件语句的en passant分配
项目描述
简单的 en passant 分配,使Python的条件语句更清晰
用法
from __future__ import print_function # Python 2/3 compat from enpassant import * result = Passer() while result / expensive_request(): print(result.report()) # assuming report() is a method of the object # expensive_request() would naturally hand back
讨论
许多语言支持 en passant (传递中) 分配,如下所示
if result = expensive_request(): print(result.report())
在Python中,这是一个语法错误。这会导致代码行数增加,并且在某些情况下,视觉清晰度降低
result = expensive_request() if result: print(result.report())
更糟糕的是,在循环结构的情况下
result = expensive_request() while result: print(result.report()) result = expensive_request()
在高度提炼的示例中,这里看起来并不那么糟糕。但在实际程序中,被调用的函数通常有要管理的参数,并且周围的代码总是更长、更复杂。周围的计算和请求越复杂,比较本身就应该越简单。正如 Python之禅 所说:“简单比复杂好。”和“可读性很重要。”
我希望Python最终能提供一种简洁的方式来处理这个问题,如下所示
while expensive_request() as result: print(result.report())
但是在此期间,enpassant 提供了一种解决方案。
工作原理
from enpassant import * result = Passer() while result / expensive_request(): print(result.report())
这里 result / expensive_request() 被读作“expensive_request的结果”。result 只是一个代理对象,当它遇到除法运算符时,返回分母。也就是说,result / whatever == whatever。但同时也 记住 分母的值。然后,无论何时你想获取提供的结果值(可能是,在循环体或条件体的后面),只需通过 result 访问它。如果你想获取 expensive_request() 返回的完整对象,可以通过 result.value 获取。或者结果有项目或属性,可以通过索引或直接命名属性来访问。简单易行!
注意:如果你改变 result 的项目或属性,这些设置也会转发到底层对象。result 不是一个副本,而是一个真正的代理,并且在当前 Python 限制下尽可能地接近实际返回的对象。
一些细节
enpassant “赋值”对条件表达式是透明的,因为表达式的值总是分母的值。但如果 Passers 也保证具有与它们包含的值相同的布尔值,那么你可以将它们用于后续测试。
上面例子中的 result 不是以下函数调用(或表达式)的纯结果,而是一个代理。项目([])和属性(.)访问直接在 result 上工作,因为 Passer 对象将 getitem 和 get-attribute 请求传递给它们包含的值。通常,这是一个便利之处,避免了需要无谓地声明实际上是 result.value 被索引或取消引用。但如果你需要特定的对象(比如对象身份或 isinstance 测试),请直接使用 result.value。
替代值访问
你也可以通过调用 Passer 来获取它的值
if result / expensive_request(): print(result().report())
这种技术清楚地表明,值是通过某种过程渲染的,而不仅仅是作为正常的 Python 名称/变量呈现。从 result() 得到的对象是先前函数调用的真正和完整的结果,无需隐式/自动转发项目和属性。哪种风格更合适是判断和品味的问题。
或者,如果你更喜欢更简洁的,+(一元正)操作也会得到值
if result / expensive_request(): print(+result.report())
替代调用
如果你更喜欢使用小于(<)或小于等于(<=)运算符作为指示 result 取下一个值的指标,它们作为除法操作的别名得到支持。因此,以下都是相同的
if result / expensive_request(): print(result.report()) if result < expensive_request(): print(result.report()) if result <= expensive_request(): print(result.report())
哪种看起来最合理、恰当和富有表现力是个人品味的问题。然而,需要注意的是,通常称为除法(/)的操作具有比典型比较操作(< 和 <=)更高的优先级(即更紧密地绑定到其操作数)。如果与更复杂的表达式一起使用,你必须了解优先级或使用括号来消除歧义!
如果Python支持任意符号,那将是非常棒的。Unicode中存在一些合理的替代赋值标记,例如 ← (左箭头),但遗憾的是!在Python变得更熟悉Unicode之前,我们不得不选择一些现有的ASCII运算符来重新使用。
如果您愿意,也可以使用函数调用的习惯用法
if result(expensive_request()): print(result.report())
这种方法的优点是看起来像“包装”了昂贵的请求值,而不是重新使用/重载现有操作。
抓取器及相关
我已经试验过其他收集和呈现值的形式。这个版本的 enpassant 包含了这些实验中的一个的结果。Grabber 类的实例可以在首次访问时设置其属性。该属性后续的使用将产生设置值。
info = Grabber() info.name('Joe') assert info.name == 'Joe'
这种方法的挑战在于一旦设置了属性值,就不能再重置。
注意
请参阅 CHANGES.yml 以获取变更日志。
En passant 是一个国际象棋术语。
En passant 赋值/命名在 Issue1714448 和 PEP 379 中讨论过,分别已被拒绝和撤回。但那是多年前的事情了。我希望能在未来重新考虑这个想法。
使用pytest、pytest-cov、coverage和tox管理自动化多版本测试。使用pyroma进行打包代码风格检查。
成功打包并针对所有2017年早期的Python版本进行测试:2.6、2.7、3.2、3.3、3.4、3.5和3.6,以及最新的PyPy和PyPy3。
在Python 2.6中,使用Raymond Hettinger的ordereddict模块(它包含在源树中以方便安装)提供 OrderedDict。谢谢,Raymond!
simplere 包同样为正则表达式搜索的常用情况提供 en passant 处理(及其他辅助功能)。
另一个可选模块:dataholder。
作者 Jonathan Eunice 或 @jeunice on Twitter 欢迎您的评论和建议。
安装
要安装或升级到最新版本
pip install -U enpassant
您可能需要使用 sudo 前缀以授权安装。在不具有超级用户权限的环境中,您可能希望使用pip的 --user 选项,只为单个用户安装,而不是系统范围内。您可能还需要根据您的系统配置使用特定版本的pip,例如 pip2 和 pip3。
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。
源代码发行版
构建版本
enpassant-0.6.7.zip的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 5547d9be6a6d865247c202c3e26e22e14f28b244a2679b129e8878f5a5333f20 |
|
MD5 | f73f5a5e8458fd56b3a982746482e135 |
|
BLAKE2b-256 | 4052a626069871d4df6d107b335a31c408ed83b678a7aefe33c04a2100b91866 |
enpassant-0.6.7-py2.py3-none-any.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e83f5ed66aeb1e7226e83041f806ef32746f4a400aa358d4dc8aa17e4dc5721d |
|
MD5 | bbadaa31e27977aa4e4e8bcf47520809 |
|
BLAKE2b-256 | 702ba5f1d9db1bf001799c9bc18d0c28869426a54c93eed8d55dd6cdd15e04bf |