如何在Python中声明常量?

在Java中,我们做:

public static final String CONST_NAME = "Name";

当前回答

Python字典是可变的,所以它们似乎不是声明常量的好方法:

>>> constants = {"foo":1, "bar":2}
>>> print constants
{'foo': 1, 'bar': 2}
>>> constants["bar"] = 3
>>> print constants
{'foo': 1, 'bar': 3}

其他回答

也许pconst库会帮助你(github)。

$ PIP安装pconst

from pconst import const
const.APPLE_PRICE = 100
const.APPLE_PRICE = 200

“APPLE_PRICE”的常量值不可编辑。

您可以使用namedtuple作为一种变通方法来有效地创建一个常量,其工作方式与Java中的静态final变量(Java“常量”)相同。作为一种变通方法,它是优雅的。(更优雅的方法是简单地改进Python语言——什么样的语言可以让您重新定义math.pi?——但我跑题了。)

(当我写这篇文章时,我意识到这个问题的另一个答案提到了namedtuple,但我将在这里继续,因为我将展示一种更接近于您在Java中所期望的语法,因为不需要像namedtuple那样创建命名类型。)

跟着你的例子,你会记得在Java中,我们必须在某个类中定义常量;因为你没有提到类名,我们称它为Foo。下面是Java类:

public class Foo {
  public static final String CONST_NAME = "Name";
}

这里是等效的Python。

from collections import namedtuple
Foo = namedtuple('_Foo', 'CONST_NAME')('Name')

我想在这里补充的关键点是,您不需要单独的Foo类型(“匿名命名元组”会很好,尽管这听起来有点矛盾),所以我们将命名元组命名为_Foo,这样它就不会转义到导入模块中。

这里的第二点是,我们立即创建了nametuple的一个实例,称其为Foo;没有必要在单独的步骤中执行此操作(除非您想这样做)。现在你可以做你在Java中可以做的事情:

>>> Foo.CONST_NAME
'Name'

但你不能给它赋值:

>>> Foo.CONST_NAME = 'bar'
…
AttributeError: can't set attribute

确认:我认为我发明了命名元组方法,但后来我看到其他人给出了类似的答案(尽管不那么紧凑)。然后我还注意到Python中的“命名元组”是什么?,这就指出了sys。version_info现在是一个命名元组,所以可能Python标准库早就提出了这个想法。

注意,不幸的是(这仍然是Python),你可以完全删除整个Foo赋值:

>>> Foo = 'bar'

(facepalm)

但至少我们阻止了福星。CONST_NAME值,这比什么都没有好。祝你好运。

在Python中创建常量的更好方法是从 优秀的attrs库,这很有帮助 Python程序员创建类时不使用样板文件。的 Short-con package也有同样的功能 常量,提供一个方便的包装器 attr.make_class。[声明:我是short-con的作者。]

值可以通过dict或kwargs显式声明 例子也有同样的作用。常量()函数支持的所有特性 库和cons()是简单使用kwarg的辅助程序。

from short_con import constants, cons

Pieces = constants('Pieces', dict(king = 0, queen = 9, rook = 5, bishop = 3, knight = 3, pawn = 1))
Pieces = cons('Pieces', king = 0, queen = 9, rook = 5, bishop = 3, knight = 3, pawn = 1)

的值相同(或可以从其导出)的情况 属性名,使用更加紧凑。只提供名称作为 空格分隔的字符串、列表或元组。

NAMES = 'KING QUEEN ROOK BISHOP KNIGHT PAWN'
xs = NAMES.split()

Pieces = constants('Pieces', NAMES)      # All of these do the same thing.
Pieces = constants('Pieces', xs)
Pieces = constants('Pieces', tuple(xs))

基于名称的用法支持一些风格约定:大写或 小写的属性名,以及枚举样式的值。

方法创建的常量不同,底层值可以直接访问 内置枚举库:

Pieces.QUEEN        # short-con usage
Pieces.QUEEN.value  # enum library usage

对象直接可迭代,可转换为其他集合:

for name, value in Pieces:
    print(name, value)

d = dict(Pieces)
tups = list(Pieces)

这并不完全是常数,但从python 3.7开始,你可以使用如下所示的数据类模块:

from dataclasses import dataclass
from typing import Final

@dataclass(frozen=True)
class A():
    a1:Final = 3

a = A()

a.a1 = 4

---------------------------------------------------------------------------
FrozenInstanceError                       Traceback (most recent call last)
<ipython-input-14-5f7f4efc5bf0> in <module>
----> 1 a.a1 = 4

<string> in __setattr__(self, name, value)

FrozenInstanceError: cannot assign to field 'a1'

Python字典是可变的,所以它们似乎不是声明常量的好方法:

>>> constants = {"foo":1, "bar":2}
>>> print constants
{'foo': 1, 'bar': 2}
>>> constants["bar"] = 3
>>> print constants
{'foo': 1, 'bar': 3}