如何在Python中创建常量?

1385 投票
44 回答
1442604 浏览
提问于 2025-04-15 21:52

在Python中,如何声明一个常量?

在Java中,我们是这样做的:

public static final String CONST_NAME = "Name";

44 个回答

161

在Python中,语言本身并不会强制某些规则,而是大家约定了一些命名方式。例如,用__method来表示私有方法,用_method来表示受保护的方法。

同样的道理,你可以把常量的名字写成全大写,比如:

MY_CONSTANT = "one"

如果你希望这个常量永远不变,可以通过访问属性来做一些技巧,但更简单的方法是声明一个函数:

def MY_CONSTANT():
    return "one"

唯一的问题是你在任何地方都需要使用MY_CONSTANT(),不过通常来说,MY_CONSTANT = "one"是Python中正确的写法。


你还可以使用namedtuple()来创建常量:

>>> from collections import namedtuple
>>> Constants = namedtuple('Constants', ['pi', 'e'])
>>> constants = Constants(3.14, 2.718)
>>> constants.pi
3.14
>>> constants.pi = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
439

在其他编程语言中有一个叫做 const 的关键词,但在这里没有。不过,我们可以创建一个属性,这个属性有一个“获取函数”来读取数据,但没有“设置函数”来修改数据。这样就能保护这个标识符不被改变。

下面是使用类属性的另一种实现方式:

注意,这段代码对于想了解常量的读者来说并不简单。具体解释见下文。

def constant(f):
    def fset(self, value):
        raise TypeError
    def fget(self):
        return f()
    return property(fget, fset)

class _Const(object):
    @constant
    def FOO():
        return 0xBAADFACE
    @constant
    def BAR():
        return 0xDEADBEEF

CONST = _Const()

print(hex(CONST.FOO))  # -> '0xbaadfaceL'

CONST.FOO = 0
##Traceback (most recent call last):
##  File "example1.py", line 22, in <module>
##    CONST.FOO = 0
##  File "example1.py", line 5, in fset
##    raise TypeError
##TypeError

代码解释:

  1. 定义一个函数 constant,它接收一个表达式,并用这个表达式构建一个“获取函数”——这个函数只返回表达式的值。
  2. 设置函数会引发一个类型错误,所以它是只读的。
  3. 使用我们刚创建的 constant 函数作为装饰器,快速定义只读属性。

还有一些比较传统的方法:

(这段代码有点复杂,下面会有更多解释)

class _Const(object):
    def FOO():
        def fset(self, value):
            raise TypeError
        def fget(self):
            return 0xBAADFACE
        return property(**locals())
    FOO = FOO()  # Define property.

CONST = _Const()

print(hex(CONST.FOO))  # -> '0xbaadfaceL'

CONST.FOO = 0
##Traceback (most recent call last):
##  File "example2.py", line 16, in <module>
##    CONST.FOO = 0
##  File "example2.py", line 6, in fset
##    raise TypeError
##TypeError
  1. 要定义标识符 FOO,首先定义两个函数(fset 和 fget - 名字可以自己选)。
  2. 然后使用内置的 property 函数来构建一个可以“设置”或“获取”的对象。
  3. 注意 property 函数的前两个参数分别是 fsetfget
  4. 利用我们为自己的获取和设置函数选择的名字,创建一个关键字字典,使用 **(双星号)将所有本地定义的参数传递给 property 函数。
1363

在Python中,你不能把一个变量或值声明为常量。


为了让程序员知道某个变量是常量,通常会把它写成大写字母:

CONST_NAME = "Name"

如果想在常量被改变时抛出异常,可以参考Alex Martelli的Python常量。不过要注意,这种做法在实际中并不常见。


从Python 3.8开始,有一个typing.Final的变量注解,可以告诉静态类型检查工具(比如mypy),你的变量不应该被重新赋值。这是最接近Java中final的用法。不过,它并不能真正阻止重新赋值

from typing import Final

a: Final[int] = 1

# Executes fine, but mypy will report an error if you run mypy on this:
a = 2

撰写回答