使用WITH简化多级对象引用,重新混合PASCAL的WITH语句
withref的Python项目详细描述
withref使python的with语句能够简化复杂的 取消引用。这就是我最初天真地认为的 for,类似于半记忆pascal的with语句。
典型的Python使用是对入口和出口的更复杂的保护 使用对象的点。参见例如this effbot article,但是withref使 更简单的“请给我未被引用的对象”用例工作如下 好。
用法
from __future__ import print_function # Python 2/3 compatibility from withref import ref from stuf import stuf # stuf used for demonstration purposes only. Convenient way to # make dict entries accessible as dot-deferenceable properties. a = stuf({ 'b': { 'c': { 'c1': 1 }, 'd': 44.1 } }) with ref(a.b.c) as c: c.c1 = 99 print(a) a_ideal = stuf({'b': {'c': {'c1': 99}, 'd': 44.1}}) assert a == a_ideal
当然,它也适用于数组样式引用:
with ref(a['b']['c']) as cc: c['c1'] = 99 assert a == a_ideal
但要小心不要乱引用!当它正常工作时:
with ref(a.b.c.c1) as c1: print(c1) assert c1 == 99
这不是:
with ref(a.b.c.c1) as c1: c1 = 12345 assert c1 == 12345 assert a.b.c.c1 == 99 # with heavy heart # because we just ostensibly set it to 12345
与pascal不同,ref不是内置到语言中的。与Perl不同的是, python并不急于为每个 提及变量或值。因此,ref可以提供值 完全延迟的c1,但不是可分配的l值。
像pascal的with一样,ref删除封闭结构的n-1层 对于值,但对于赋值只有n-2。不过,在复杂的多层结构中 结构,这是一个很好的简化:
with ref(app.config.server.wsgi) as wsgi: wsgi.logger = some_logger wsgi.debug_level = 4 wsgi.port = 8080
有争议的节拍:
app.config.server.wsgi.logger = some_logger app.config.server.wsgi.debug_level = 4 app.config.server.wsgi.port = 8080
为了简单明了。
我看到很多配置代码总是重复相同的长度 多级解引用。这种风格是重复性的(抗干的),并且倾向于 左对齐代码块,这两个代码块都会妨碍程序理解。使用 with语句是一种简单的方法,同时还可以添加一些额外的 视觉结构。
虽然赋值(“左值生产”)并不总是可能的,但仍然有 简单的价值创造可能会有一些有趣的技巧:
with ref("this is a string"[0:4]) as t: print(t)
备选方案
虽然yadda.yadda.yadda引用太常见,但也可以 使用更接近的变量赋值:
wsgi = app.config.server.wsgi wsgi.logger = some_logger wsgi.debug_level = 4 wsgi.port = 8080
这缺少withref方法的缩进结构,但是 仍然比你在野外经常发现的要好得多。
另请参见
withhacks模块,包括 许多其他有趣的技巧(多行lambdas、新的循环结构等)——但是 还需要byteplay模块 积极反省并咀嚼python字节码(“危险,威尔·罗宾逊! 危险!,并且没有更新到Python2.6之后的版本。所以它不在 货币除了现代Python的尾部之外。
未来可能的扩展
如withhacks所示,通过内省,我们可以确定 调用对象,即使在它是其叶节点的边缘情况下也是如此 封闭结构。这不需要任何字节码更改,而且应该 与现代版本的python(如2.7]和3.x)兼容。
这个技巧是否可以简单、轻便、可靠地实现,以及 透明到足以满足那些编写模块的人 需要这种解引用的简化-即复杂的模块经常 在生产环境中使用,可以理解他们不喜欢 引入任何可能的误差源或任何性能阻抗 是关键的开放性问题。
注释
使用pytest,pytest-cov,管理自动多版本测试, coverage 以及tox。 用pyroma包装绒布。
已成功打包,并且 测试了python的所有最新模型版本:2.6、2.7、3.3, 3.4、3.5、3.6以及最近的pypy和pypy3构建。
作者,Jonathan Eunice或 @jeunice on Twitter 欢迎您的意见和建议。
安装
要安装或升级到最新版本:
pip install -U withref
您可能需要在它们前面加上sudo来授权 安装。在没有超级用户权限的环境中,您可能希望 使用pip的--user选项,仅为而是单一用户 而不是整个系统。根据您的本地系统配置,您可以 可能还需要特定于版本的安装程序,如pip2和pip3。