Python沒有常量是不是不夠安全的設計?
我是一個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 特性即可:from collections import namedtuple
def const(**kwargs):
ConstType = namedtuple("Constant", kwargs.keys())
return ConstType(**kwargs)
const1 = const(
name="test", value=123,
)
print const1.name # test
const1.name = "xxxx" # raise AttributeError
全局變數可以有,但是如果濫用就不好了。考慮你問題的規模,小腳本還好說,如果依賴複雜,大量依賴全局變數,我覺得設計本身可能就有問題。
建議將全局變數作為一個類的屬性,內部用單下劃線來限制外部調用,然後用@property將變數包裝成只讀屬性。別作死…………比如
True, False = False, True
你說這都能幹,只能說盡量管住自己不犯二……
個人認為是自由度和程序員自我約束的一種PSF認為是tradeoff的解決方案吧
不過始終是個問題
這就要求自己別亂改之外,用別人代碼的之前還要看看他有沒有亂改
抖個機靈。在c++里這麼定義一下的話……#DEFINE true false
坑還是很多。。
是。
也許是故意的。感覺python是提供了足夠的便捷,加入常量就如同加入數據類型一樣,更多的檢查本質上是為了規避編程者本身的問題,讓你少犯錯,在程序運行之前。為了足夠靈活,很多編譯型語言的特性拿掉,這些約束就落在了程序員身上,這未嘗不是件好事。總之,我清楚我在幹嘛,so,我才不會改第三方模塊全局變數,也不會True=0,如果我真有這樣的需求…很感謝python提供了我這個許可權。 這個問題,完美的回答還是等什麼時候guido也用知乎了,邀請他回答下,哈哈,知乎願景。
推薦閱讀:
※Python的Dictionary的花括弧,應該換行嗎?
※一行 Python 能實現什麼喪心病狂的功能?
※Python換行符問題:
還是
?
※如何用Yacc實現一個Python的編譯器?
※為什麼大多數編程語言被設計成函數只有一個返回值,而不是多個?