如何在Python中声明常量?

在Java中,我们做:

public static final String CONST_NAME = "Name";

当前回答

属性是创建常量的一种方法。你可以通过声明一个getter属性来做到这一点,但忽略setter。例如:

class MyFinalProperty(object):

    @property
    def name(self):
        return "John"

您可以看看我写的一篇文章,以找到更多使用Python属性的方法。

其他回答

我正在尝试用不同的方法在Python中创建一个真正的常量,也许我找到了漂亮的解决方案。

例子:

为常量创建容器

>>> DAYS = Constants(
...     MON=0,
...     TUE=1,
...     WED=2,
...     THU=3,
...     FRI=4,
...     SAT=5,
...     SUN=6
... )   

从容器中获取价值

>>> DAYS.MON
0
>>> DAYS['MON']
0  

用纯python数据结构表示

>>> list(DAYS)
['WED', 'SUN', 'FRI', 'THU', 'MON', 'TUE', 'SAT']
>>> dict(DAYS)
{'WED': 2, 'SUN': 6, 'FRI': 4, 'THU': 3, 'MON': 0, 'TUE': 1, 'SAT': 5}

所有常数都是不可变的

>>> DAYS.MON = 7
...
AttributeError: Immutable attribute

>>> del DAYS.MON 
...
AttributeError: Immutable attribute

仅对常量自动补全

>>> dir(DAYS)
['FRI', 'MON', 'SAT', 'SUN', 'THU', 'TUE', 'WED']

像list.sort那样排序

>>> DAYS.sort(key=lambda (k, v): v, reverse=True)
>>> list(DAYS)
['SUN', 'SAT', 'FRI', 'THU', 'WED', 'TUE', 'MON']

与python2和python3的兼容性

常量的简单容器

from collections import OrderedDict
from copy import deepcopy

class Constants(object):
    """Container of constant"""

    __slots__ = ('__dict__')

    def __init__(self, **kwargs):

        if list(filter(lambda x: not x.isupper(), kwargs)):
            raise AttributeError('Constant name should be uppercase.')

        super(Constants, self).__setattr__(
            '__dict__',
            OrderedDict(map(lambda x: (x[0], deepcopy(x[1])), kwargs.items()))
        )

    def sort(self, key=None, reverse=False):
        super(Constants, self).__setattr__(
            '__dict__',
            OrderedDict(sorted(self.__dict__.items(), key=key, reverse=reverse))
        )

    def __getitem__(self, name):
        return self.__dict__[name]

    def __len__(self):
        return  len(self.__dict__)

    def __iter__(self):
        for name in self.__dict__:
            yield name

    def keys(self):
        return list(self)

    def __str__(self):
        return str(list(self))

    def __repr__(self):
        return '<%s: %s>' % (self.__class__.__name__, str(self.__dict__))

    def __dir__(self):
        return list(self)

    def __setattr__(self, name, value):
        raise AttributeError("Immutable attribute")

    def __delattr__(*_):
        raise AttributeError("Immutable attribute")

你可以使用StringVar或IntVar等,你的常量是const_val

val = 'Stackoverflow'
const_val = StringVar(val)
const.trace('w', reverse)

def reverse(*args):
    const_val.set(val)

我将创建一个重写基对象类的__setattr__方法的类,并用它包装我的常量,注意我使用的是python 2.7:

class const(object):
    def __init__(self, val):
        super(const, self).__setattr__("value", val)
    def __setattr__(self, name, val):
        raise ValueError("Trying to change a constant value", self)

换行字符串:

>>> constObj = const("Try to change me")
>>> constObj.value
'Try to change me'
>>> constObj.value = "Changed"
Traceback (most recent call last):
   ...
ValueError: Trying to change a constant value
>>> constObj2 = const(" or not")
>>> mutableObj = constObj.value + constObj2.value
>>> mutableObj #just a string
'Try to change me or not'

这很简单,但如果你想像使用非常量对象一样使用常量(不使用constObj.value),它会更密集一些。这可能会导致问题,所以最好保留.value来显示和知道您正在使用常量进行操作(尽管可能不是最“python”的方式)。

在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)

嗯. .尽管这是过时的,让我在这里补充我的2分:-)

class ConstDict(dict):
    def __init__(self, *args, **kwargs):
        super(ConstDict, self).__init__(*args, **kwargs)

    def __setitem__(self, key, value):
        if key in self:
            raise ValueError("Value %s already exists" % (key))
        super(ConstDict, self).__setitem__(key, value)

您可以防止在那里发生任何更新,而不是破坏ValueError。这样做的一个好处是,您可以在程序中动态地添加常数,但一旦设置了常数就不能更改。你也可以在设置常量之前添加任何规则(比如key必须是字符串或小写字符串或大写字符串等)

然而,我不认为在Python中设置常量有任何重要性。没有优化可以像在C中那样发生,因此它是不需要的,我猜。