python locals()用法_Python:使用“..%(var)s…”%locals()是一个很好的做法吗?

对于小型应用程序和所谓的“一次性”脚本来说,这是可以的,特别是对于@kaizer.se提到的vars增强和@RedGlyph提到的.format版本。

然而,对于维护周期长的大型应用程序和许多维护人员来说,这种做法可能会导致维护方面的麻烦,我认为@s.Lott的答案就是从这里来的。让我解释一下其中涉及的一些问题,因为对于那些没有开发和维护大型应用程序(或可重用组件)的创伤的人来说,这些问题可能并不明显。

在一个“严肃”的应用程序中,您不会对格式字符串进行硬编码——或者,如果您进行了硬编码,它将以某种形式出现,例如_('Hello {name}.'),其中_来自gettext或类似的i18n/L10n框架。关键是这样一个应用程序(或者碰巧在这样的应用程序中使用的可重用模块)必须支持国际化(AKA i18n)和本地化(AKA L10n):您希望您的应用程序能够在某些国家和文化中发出“Hello Paul”,在某些国家和文化中发出“Hola Paul”,在其他国家和文化中发出“Ciao Paul”,等等。因此,根据当前的本地化设置,格式字符串在运行时或多或少会自动替换为另一个;它不是硬编码的,而是存在于某种数据库中。出于所有目的和意图,假设格式字符串始终是一个变量,而不是字符串文本。

所以,你所拥有的基本上是formatstring.format(**locals())

而且您不能简单地检查格式化将要使用的本地名称。您必须打开并仔细阅读L10N数据库,识别将在不同设置中使用的格式字符串,验证所有这些字符串。

因此在实践中,您不知道将要使用什么本地名称——这严重影响了函数的维护。您不敢重命名或删除任何局部变量,因为它可能会严重破坏用户体验,因为有些(对您而言)语言、区域设置和首选项的组合不清晰

如果您有出色的集成/回归测试,那么在beta版本发布之前就会发现破坏——但是QA会对您大喊大叫,并且发布会被延迟。。。而且,老实说,虽然用单元测试实现100%覆盖率是合理的,但一旦考虑设置的组合爆炸[对于L10N和更多原因]]和所有依赖项的支持版本,就不能用集成测试了。所以,你不能因为“他们会被质量保证(QA)困住”(如果你这样做了,你可能在开发大型应用程序或可重用组件的环境中撑不了多久)而轻率地冒着崩溃的风险。

因此,在实践中,您永远不会删除“name”局部变量,即使用户体验人员早已将该问候语改为更合适的“欢迎,可怕的霸主!”(以及适当的10个版本)。都是因为你为了locals()。。。

所以你在积累cruft是因为你已经限制了你维护和编辑代码的能力——也许“name”局部变量的存在只是因为它是从一个数据库或类似的地方获取的,所以保持它(或其他一些局部变量)不只是cruft,它也降低了你的性能。表面的便利性值得吗?-)

但是等等,还有更糟的!在许多有用的服务中,类似于lint的程序(例如,pylint)可以为您做的是警告您未使用的局部变量(希望它也可以为未使用的全局变量做,但是,对于可重用的组件,这太难了;-)。这样你就能很快、很便宜地捕捉到大多数偶然的拼写错误,比如if ...: nmae = ...,而不是通过查看单元测试中断并进行侦探工作来找出它中断的原因(你有强迫性的、普遍的单元测试,这些测试最终会捕捉到这些错误,正确的?-)--lint将告诉您一个未使用的局部变量nmae,您将立即修复它。

但是如果你的代码中有一个blah.format(**locals()),或者等价于一个blah % locals()。。。你是索尔,伙计!-)可怜的lint怎么知道nmae实际上是一个未使用的变量,还是它确实被传递给locals()的任何外部函数或方法所使用?它不能——不管怎样,它都会发出警告(导致“狼叫”效应,最终导致你忽略或禁用此类警告),或者它永远不会发出警告(具有相同的最终效果:没有警告;-)。

将此与“显式优于隐式”选项进行比较…:blah.format(name=name)

在那里——再也不用担心维护、性能和am-I-PILLING-lint了;幸福!你立即向所有相关的人(包括lint;-)清楚地说明了正在使用的局部变量是什么,以及具体用于什么目的。

我可以继续,但我认为这篇文章已经很长了;-)。

所以,总结一下:“γνῶθισεαότόν!”嗯,我是说,“了解你自己!”。我说的“你自己”实际上是指“你的代码的目的和范围”。如果它是一个一次性的东西,永远不会是i18n'd和L10n'd,不需要将来的维护,永远不会在更广泛的上下文中重用,等等,那么继续使用locals()来获得它的小而整洁的方便;如果你知道其他的,或者即使你不完全确定,也要小心出错,把事情说得更清楚些——在准确地说出你要做的事情时要忍受一些小小的不便,并享受由此带来的所有好处。

顺便说一句,这只是Python努力支持“小型的、一次性的、探索性的、可能是交互式的”编程的例子之一(通过允许和支持远远超出locals()的风险便利性——想想import *,eval,exec,为了方便起见,还有其他几种方法可以将名称空间和风险维护影响混为一谈),以及“大型、可重用、企业级”的应用程序和组件。这两个方面都能做得很好,但前提是你“了解自己”,避免使用“便利”部分,除非你绝对确定你能负担得起。通常,关键的考虑是,“这对我的名称空间有什么影响,以及编译器、lint&c、人工读者和维护人员对名称空间的形成和使用的意识,等等?”。

记住,“名称空间是一个非常棒的主意——让我们做更多的事情吧!”是Python禅的结论。。。但是,Python作为一种“成人同意的语言”,允许您根据开发环境、目标和实践定义这意味着什么的边界。负责任地使用这个电源!-)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值