Python没有常量是不是不够安全的设计?

WBOY
풀어 주다: 2016-06-06 16:23:11
원래의
1710명이 탐색했습니다.

我是一个Python轻度用户+爱好者,这两天我尝试用Python替代bash完成一些简单的工作(最主要的目的其实是学习),有一些困惑。

Python不能很方便的定义常量,这就带来了一些问题,如果一个程序或引用的第三方库,不小心修改了某一个模块下的一个全局变量,比如re模块的re.I,re.M等,这样就会给程序带来很大的不确定性?

re这个例子只不过是一个历史遗留问题,是特例,还是类似的例子在Python中是普遍存在的?

回复内容:

“修改某一模块下的全局变量”,这就是打猴子补丁啊(Monkey patch)。Python的设计思想就是要足够动态,让你方便运行时各种魔改,你看他连private关键字都没,还可以运行着运行着把自己底层标准库给换了(比如gevent里面的monkey patch),区区常量算个毛。 你说的事是普遍存在的。python中任何一个名字都只是个简单绑定,它的实体是什么这一点你随时可以改。像_和__这种用来表示私有的前缀效果也不过是自动改个名而已。这提供了足够高的自由度,让程序员在不直接修改模块的前提下可以改动其内的行为,同时要求程序员自己不要无故作死。像re.M这样的量,关键不在于可不可改,而是应不应该去改。

当然这是不安全的。拿JAVA来做对比就会明白Python在安全性上维持的重点在程序员自身。这也是为啥招个『初级』Python程序员会坑死。

当然了,一些特殊的手法可以使得像你举例的那种改动不可执行(例如re.M不再是一个数而是一个随机密钥,在载入模块时生成,具体辨认通过模块内隐藏的函数来执行,而不直接暴露参数本身)。只不过真的没什么必要。 熟悉Python开发哲学的人会质问你不清楚后果为什么要修改别的模块的全局变量?

要是想弄个不能被修改的常量对象也是没问题的,简单地利用元组的 immutable 特性即可:
<code class="language-python"><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>


<span class="k">def</span> <span class="nf">const</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="n">ConstType</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">"Constant"</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
    <span class="k">return</span> <span class="n">ConstType</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
    
<span class="n">const1</span> <span class="o">=</span> <span class="n">const</span><span class="p">(</span>
    <span class="n">name</span><span class="o">=</span><span class="s">"test"</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="mi">123</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">print</span> <span class="n">const1</span><span class="o">.</span><span class="n">name</span>  <span class="c"># test</span>
<span class="n">const1</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"xxxx"</span>  <span class="c"># raise AttributeError</span>
</code>
로그인 후 복사
别作死…………
比如
<code class="language-python"><span class="bp">True</span><span class="p">,</span> <span class="bp">False</span> <span class="o">=</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">True</span>
</code>
로그인 후 복사
全局变量可以有,但是如果滥用就不好了。考虑你问题的规模,小脚本还好说,如果依赖复杂,大量依赖全局变量,我觉得设计本身可能就有问题。

建议将全局变量作为一个类的属性,内部用单下划线来限制外部调用,然后用@property将变量包装成只读属性。 坑还是很多。。 抖个机灵。
在c++里这么定义一下的话……
#DEFINE true false 是。

也许是故意的。 感觉python是提供了足够的便捷,加入常量就如同加入数据类型一样,更多的检查本质上是为了规避编程者本身的问题,让你少犯错,在程序运行之前。为了足够灵活,很多编译型语言的特性拿掉,这些约束就落在了程序员身上,这未尝不是件好事。总之,我清楚我在干嘛,so,我才不会改第三方模块全局变量,也不会True=0,如果我真有这样的需求…很感谢python提供了我这个权限。 这个问题,完美的回答还是等什么时候guido也用知乎了,邀请他回答下,哈哈,知乎愿景。
관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿