在實際的程序開發中,我們通常會將一個不可變的變量聲明為一個常量。在很多高級語言中都會提供常量的關鍵字來定義常量,如 C++
中的 const
, Java
中的 final
等,但是 Python
語言因為變量無類型,所以也就不存在這樣的修飾符,其本身並未提供任何機制來進行常量的定義。因此我們只能通過自己定義類的方法來定義一個符合常量規則的類,使得該類定義的成員屬性滿足常量的屬性。常量一般符合以下兩條規則:
- 常量的各個字母使用大寫字母表示,中間以下划線連接:如
MAX_VALUE
;- 常量的值一旦綁定則不可以再修改。
由於常量的值一旦綁定則不可再修改,所以也就是說對常量二次賦值時需要拋出異常。因此我們顯然需要改寫自定義的常量類的賦值方法。在 Python
中,當我們對類的屬性進行賦值時,會自動調用 object
類的 __setattr__()
函數,該函數的定義如下:
object.__setattr__(self, name, value)
其中的 name
表示屬性的名稱,value
是試圖賦值給 name
的值,其中 object
類的 object.__dict__
以字典的形式保存了所有已賦值的屬性。
因此我們可以通過定義一個常量類 constant
類(默認繼承自object
),並對 object.__setattr__()
方法進行重寫。由於常量有兩條規則,所以我們需要根據這兩條規則自定義兩個異常處理,分別是二次賦值的異常處理和名稱非大寫的異常處理。
異常處理的定義方式請參看:Python 錯誤和異常
定義常量類:
constant.py
import sys
class _const:
# 自定義異常處理
class ConstError(PermissionError):
pass
class ConstCaseError(ConstError):
pass
# 重寫 __setattr__() 方法
def __setattr__(self, name, value):
if name in self.__dict__: # 已包含該常量,不能二次賦值
raise self.ConstError("Can't change const {0}".format(name))
if not name.isupper(): # 所有的字母需要大寫
raise self.ConstCaseError("const name {0} is not all uppercase".format(name))
self.__dict__[name] = value
# 將系統加載的模塊列表中的 constant 替換為 _const() 實例
sys.modules[__name__] = _const()
在其它文件中定義常量,test.py
import constant
constant.VALUE = 5
constant.VALUE = 4 # ConstError
constant.vaLue = 1 # ConstCaseError
當我們識圖修改常量 VALUE
的值或者定義一個名稱不是全部大寫的常量時,都會拋出異常,這樣就達到了不可更改常量的值的目的。