我如何在Python中创build一个常量?

有没有办法在Python中声明一个常量? 在Java中,我们可以用这种方式创build常量值:

public static final String CONST_NAME = "Name"; 

Python中的上述Java常量声明等价于什么?

不,那里没有。 你不能在Python中声明一个variables或值为常量。 只是不要改变它。

如果你在一个class上,相当于:

 class Foo(object): CONST_NAME = "Name" 

如果没有的话,这是公正的

 CONST_NAME = "Name" 

但是你可能想看看由Alex Martelli编写的代码片段中的常量 。

在其他语言中没有const关键字,但是可以创build一个属性,该属性具有读取数据的“getter函数” ,但没有“setter函数”来重写数据。 这基本上保护了标识符不被改变。

这是一个使用类属性的替代实现:

请注意,对于读者来说,代码是很不容易的。 见下面的解释

 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 CONST.FOO ##3131964110 CONST.FOO = 0 ##Traceback (most recent call last): ## ... ## CONST.FOO = 0 ##TypeError: None 

代码说明:

  1. 定义一个函数constant ,它接受一个expression式,并用它来构造一个“getter” – 一个函数,它只返回expression式的值。
  2. setter函数引发TypeError,因此它是只读的
  3. 使用我们刚刚创build的constant函数作为装饰来快速定义只读属性。

而在其他一些更老式的方式:

(代码相当棘手,下面有更多的解释)

 class _Const(object): @apply def FOO(): def fset(self, value): raise TypeError def fget(self): return 0xBAADFACE return property(**locals()) CONST = _Const() print CONST.FOO ##3131964110 CONST.FOO = 0 ##Traceback (most recent call last): ## ... ## CONST.FOO = 0 ##TypeError: None 

请注意,@应用装饰似乎已被弃用。

  1. 为了定义标识符FOO,firs定义了两个函数(fset,fget – 这些名字是我select的)。
  2. 然后使用内置的property函数来构造一个可以“设置”或“获取”的对象。
  3. 注意, property函数的前两个参数被命名为fsetfget
  4. 使用我们为自己的getter&setterselect这些名字的事实,并使用应用于该作用域的所有本地定义的**(双星号)创build关键字字典,以便将parameter passing给property函数

在Python中,而不是强制执行的语言,人们使用命名约定,例如__method用于私有方法,而_method用于受保护的方法。

因此,以同样的方式,你可以简单地声明常量,例如全部大写

 MY_CONSTANT = "one" 

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

 def MY_CONSTANT(): return "one" 

唯一的问题是你将不得不做MY_CONSTANT(),但是MY_CONSTANT = "one"是python(通常)中的正确方法。

你也可以使用namedtuple来创build常量:

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

我可能在这里错过了一个技巧,但这似乎对我有用:

 class CONST(object): FOO = 1234 def __setattr__(self, *_): pass CONST = CONST() #---------- print CONST.FOO # 1234 CONST.FOO = 4321 CONST.BAR = 5678 print CONST.FOO # Still 1234! print CONST.BAR # Oops AttributeError 

创build实例允许魔法__setattr__方法启动并拦截尝试设置FOOvariables。 如果你想的话,你可以在这里抛出exception。 通过类名实例化实例可防止直接通过类访问。

对于一个值来说,这是一个总的痛苦,但是你可以把很多东西附加到你的CONST对象上。 有一个上层阶级,阶级名称也似乎有点困难,但我认为这是相当简洁的总体。

除了两个最重要的答案(只要使用带有大写字母名称的variables,或者使用属性来使值为只读),我想提到可以使用元类来实现命名常量。 我提供了一个在GitHub上使用元类的非常简单的解决scheme,如果你想让这些值更具有关于它们的types/名称的信息,这可能会有所帮助:

 >>> from named_constants import Constants >>> class Colors(Constants): ... black = 0 ... red = 1 ... white = 15 ... >>> c = Colors.black >>> c == 0 True >>> c Colors.black >>> c.name() 'black' >>> Colors(0) is c True 

这是稍微高级的Python,但仍然非常容易使用和方便。 (该模块有一些更多的function,包括常量是只读的,请参阅其自述文件。)

在各种知识库中都有相似的解决scheme,但据我所知,他们要么缺乏我期望从常量中获得的基本特征之一(比如常量或者任意types),要么join了深奥的特征使它们不太普遍适用。 但是YMMV,我会感激反馈。 🙂

编辑:添加Python 3的示例代码

注意: 这个答案看起来像它提供了一个更完整的实现类似于以下(具有更多的function)。

首先,制作一个元类 :

 class MetaConst(type): def __getattr__(cls, key): return cls[key] def __setattr__(cls, key, value): raise TypeError 

这可以防止修改静态属性。 然后创build另一个使用该元类的类:

 class Const(object): __metaclass__ = MetaConst def __getattr__(self, name): return self[name] def __setattr__(self, name, value): raise TypeError 

或者,如果你使用Python 3:

 class Const(object, metaclass=MetaConst): def __getattr__(self, name): return self[name] def __setattr__(self, name, value): raise TypeError 

这应该防止实例道具被改变。 要使用它,请inheritance:

 class MyConst(Const): A = 1 B = 2 

现在直接或通过实例访问的道具应该是不变的:

 MyConst.A # 1 my_const = MyConst() my_const.A # 1 MyConst.A = 'changed' # TypeError my_const.A = 'changed' # TypeError 

这是上面的一个例子。 这是 Python 3 的另一个例子。

我会做一个类重写基类对象类的__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) 

包装一个string:

 >>> 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),它会更encryption集。 这可能会导致问题,所以最好保持.value显示,并知道你正在用常量进行操作(尽pipe可能不是最“pythonic”的方式)。

Pythonic声明“常量”的方式基本上是一个模块级的variables:

 RED = 1 GREEN = 2 BLUE = 3 

然后编写你的类或函数。 由于常量几乎总是整数,而且在Python中也是不变的,所以改变它的机会很小。

当然,除非你明确设定RED = 2

这里是一个“常量”类的实现,它创build具有只读(常量)属性的实例。 例如,可以使用Nums.PI获取已初始化为3.14159的值,并且Nums.PI = 22引发exception。

 # ---------- Constants.py ---------- class Constants(object): """ Create objects with read-only (constant) attributes. Example: Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0) print 10 + Nums.PI print '----- Following line is deliberate ValueError -----' Nums.PI = 22 """ def __init__(self, *args, **kwargs): self._d = dict(*args, **kwargs) def __iter__(self): return iter(self._d) def __len__(self): return len(self._d) # NOTE: This is only called if self lacks the attribute. # So it does not interfere with get of 'self._d', etc. def __getattr__(self, name): return self._d[name] # ASSUMES '_..' attribute is OK to set. Need this to initialize 'self._d', etc. #If use as keys, they won't be constant. def __setattr__(self, name, value): if (name[0] == '_'): super(Constants, self).__setattr__(name, value) else: raise ValueError("setattr while locked", self) if (__name__ == "__main__"): # Usage example. Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0) print 10 + Nums.PI print '----- Following line is deliberate ValueError -----' Nums.PI = 22 

感谢@MikeGraham的FrozenDict ,我以此为出发点。 更改,所以而不是Nums['ONE']使用语法是Nums.ONE

感谢@ Raufio的回答,想法是重写__ setattr __。

或者对于具有更多function的实现,请参阅GitHub上的 @Hans_meine的named_constants

一个元组在技术上属于一个常量,因为如果你试图改变它的一个值,元组将会引发一个错误。 如果你想用一个值声明一个元组,那么在它的唯一值之后放一个逗号,如下所示:

 my_tuple = (0 """Or any other value""",) 

要检查这个variables的值,使用类似这样的东西:

 if my_tuple[0] == 0: #Code goes here 

如果您尝试更改此值,则会引发错误。

您可以使用namedtuple作为解决方法来有效地创build一个与Java中的静态最终variables(Java常量)相同的常量。 作为解决方法,它有点优雅。 (更优雅的方法是简单地改进Python语言 – 什么语言可以让你重新定义math.pi 。但是我离题了。)

(当我写这篇文章的时候,我意识到这个提到的这个问题的另外一个答案,但是我会继续在这里,因为我将展示一个与你期望在Java中更接近的语法,因为不需要创build一个named 键入为“命令”强制您执行此操作。)

遵循你的例子,你会记得在Java中我们必须在某个类中定义常量, 因为你没有提到类名,我们称之为Foo 。 这是Java类:

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

这是等效的Python。

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

我想在这里添加的关键点是,你不需要单独的Footypes(即使这听起来像一个矛盾),所以我们命名我们命名为_Foo所以希望它赢得了不会转移到导入模块。

第二点是我们立即创build一个 nametuple 的实例 ,称它为Foo ; 没有必要在一个单独的步骤(除非你想)做到这一点。 现在你可以做你可以在Java中做的事情:

 >>> Foo.CONST_NAME 'Name' 

但是你不能指定它:

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

致谢:我以为我发明了这个命名的方法,但是后来我发现有人给出了一个类似(虽然不那么紧凑)的答案。 然后我也注意到Python中的“命名元组”是什么? ,它指出sys.version_info现在是一个namedtuple,所以也许Python标准库早就提出了这个想法。

注意不幸的是(这仍然是Python),你可以完全擦除整个Foo分配:

 >>> Foo = 'bar' 

(捂脸)

但至less我们阻止了Foo.CONST_NAME值的改变,这总比没有好。 祝你好运。

属性是创build常量的一种方法。 你可以通过声明一个getter属性来完成,但忽略setter。 例如:

 class MyFinalProperty(object): @property def name(self): return "John" 

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

正如你可能已经知道的,Python没有常量:(

也许最简单的select是为它定义一个函数。 例如

 def MY_CONSTANT(): return 42 

MY_CONSTANT()现在具有常量的所有function(加上一些烦人的花括号)。

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

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

不幸的是,Python还没有常量,这是耻辱。 ES6已经将支持常量添加到JavaScript( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/const ),因为它在任何编程语言中都是非常有用的。 正如在Python社区中的其他答案中所回答的那样,使用惯例 – 用户大写variables作为常量,但是它不能防止代码中的任意错误。 如果你喜欢,你可能会发现下一个单文件解决scheme很有用(请参阅docstrings如何使用它)。

文件constants.py

 import collections __all__ = ('const', ) class Constant(object): """ Implementation strict constants in Python 3. A constant can be set up, but can not be changed or deleted. Value of constant may any immutable type, as well as list or set. Besides if value of a constant is list or set, it will be converted in an immutable type as next: list -> tuple set -> frozenset Dict as value of a constant has no support. >>> const = Constant() >>> del const.temp Traceback (most recent call last): NameError: name 'temp' is not defined >>> const.temp = 1 >>> const.temp = 88 Traceback (most recent call last): ... TypeError: Constanst can not be changed >>> del const.temp Traceback (most recent call last): ... TypeError: Constanst can not be deleted >>> const.I = ['a', 1, 1.2] >>> print(const.I) ('a', 1, 1.2) >>> const.F = {1.2} >>> print(const.F) frozenset([1.2]) >>> const.D = dict() Traceback (most recent call last): ... TypeError: dict can not be used as constant >>> del const.UNDEFINED Traceback (most recent call last): ... NameError: name 'UNDEFINED' is not defined >>> const() {'I': ('a', 1, 1.2), 'temp': 1, 'F': frozenset([1.2])} """ def __setattr__(self, name, value): """Declaration a constant with value. If mutable - it will be converted to immutable, if possible. If the constant already exists, then made prevent againt change it.""" if name in self.__dict__: raise TypeError('Constanst can not be changed') if not isinstance(value, collections.Hashable): if isinstance(value, list): value = tuple(value) elif isinstance(value, set): value = frozenset(value) elif isinstance(value, dict): raise TypeError('dict can not be used as constant') else: raise ValueError('Muttable or custom type is not supported') self.__dict__[name] = value def __delattr__(self, name): """Deny against deleting a declared constant.""" if name in self.__dict__: raise TypeError('Constanst can not be deleted') raise NameError("name '%s' is not defined" % name) def __call__(self): """Return all constans.""" return self.__dict__ const = Constant() if __name__ == '__main__': import doctest doctest.testmod() 

如果这还不够,请参阅完整的testing用例。

 import decimal import uuid import datetime import unittest from ..constants import Constant class TestConstant(unittest.TestCase): """ Test for implementation constants in the Python """ def setUp(self): self.const = Constant() def tearDown(self): del self.const def test_create_constant_with_different_variants_of_name(self): self.const.CONSTANT = 1 self.assertEqual(self.const.CONSTANT, 1) self.const.Constant = 2 self.assertEqual(self.const.Constant, 2) self.const.ConStAnT = 3 self.assertEqual(self.const.ConStAnT, 3) self.const.constant = 4 self.assertEqual(self.const.constant, 4) self.const.co_ns_ta_nt = 5 self.assertEqual(self.const.co_ns_ta_nt, 5) self.const.constant1111 = 6 self.assertEqual(self.const.constant1111, 6) def test_create_and_change_integer_constant(self): self.const.INT = 1234 self.assertEqual(self.const.INT, 1234) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.INT = .211 def test_create_and_change_float_constant(self): self.const.FLOAT = .1234 self.assertEqual(self.const.FLOAT, .1234) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.FLOAT = .211 def test_create_and_change_list_constant_but_saved_as_tuple(self): self.const.LIST = [1, .2, None, True, datetime.date.today(), [], {}] self.assertEqual(self.const.LIST, (1, .2, None, True, datetime.date.today(), [], {})) self.assertTrue(isinstance(self.const.LIST, tuple)) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.LIST = .211 def test_create_and_change_none_constant(self): self.const.NONE = None self.assertEqual(self.const.NONE, None) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.NONE = .211 def test_create_and_change_boolean_constant(self): self.const.BOOLEAN = True self.assertEqual(self.const.BOOLEAN, True) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.BOOLEAN = False def test_create_and_change_string_constant(self): self.const.STRING = "Text" self.assertEqual(self.const.STRING, "Text") with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.STRING += '...' with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.STRING = 'TEst1' def test_create_dict_constant(self): with self.assertRaisesRegexp(TypeError, 'dict can not be used as constant'): self.const.DICT = {} def test_create_and_change_tuple_constant(self): self.const.TUPLE = (1, .2, None, True, datetime.date.today(), [], {}) self.assertEqual(self.const.TUPLE, (1, .2, None, True, datetime.date.today(), [], {})) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.TUPLE = 'TEst1' def test_create_and_change_set_constant(self): self.const.SET = {1, .2, None, True, datetime.date.today()} self.assertEqual(self.const.SET, {1, .2, None, True, datetime.date.today()}) self.assertTrue(isinstance(self.const.SET, frozenset)) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.SET = 3212 def test_create_and_change_frozenset_constant(self): self.const.FROZENSET = frozenset({1, .2, None, True, datetime.date.today()}) self.assertEqual(self.const.FROZENSET, frozenset({1, .2, None, True, datetime.date.today()})) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.FROZENSET = True def test_create_and_change_date_constant(self): self.const.DATE = datetime.date(1111, 11, 11) self.assertEqual(self.const.DATE, datetime.date(1111, 11, 11)) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.DATE = True def test_create_and_change_datetime_constant(self): self.const.DATETIME = datetime.datetime(2000, 10, 10, 10, 10) self.assertEqual(self.const.DATETIME, datetime.datetime(2000, 10, 10, 10, 10)) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.DATETIME = None def test_create_and_change_decimal_constant(self): self.const.DECIMAL = decimal.Decimal(13123.12312312321) self.assertEqual(self.const.DECIMAL, decimal.Decimal(13123.12312312321)) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.DECIMAL = None def test_create_and_change_timedelta_constant(self): self.const.TIMEDELTA = datetime.timedelta(days=45) self.assertEqual(self.const.TIMEDELTA, datetime.timedelta(days=45)) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.TIMEDELTA = 1 def test_create_and_change_uuid_constant(self): value = uuid.uuid4() self.const.UUID = value self.assertEqual(self.const.UUID, value) with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'): self.const.UUID = [] def test_try_delete_defined_const(self): self.const.VERSION = '0.0.1' with self.assertRaisesRegexp(TypeError, 'Constanst can not be deleted'): del self.const.VERSION def test_try_delete_undefined_const(self): with self.assertRaisesRegexp(NameError, "name 'UNDEFINED' is not defined"): del self.const.UNDEFINED def test_get_all_defined_constants(self): self.assertDictEqual(self.const(), {}) self.const.A = 1 self.assertDictEqual(self.const(), {'A': 1}) self.const.B = "Text" self.assertDictEqual(self.const(), {'A': 1, 'B': "Text"}) 

优点:1.访问整个项目的所有常量2.严格控制常量值

缺乏:1.不支持自定义types和types“字典”

笔记:

  1. 使用Python3.4和Python3.5进行testing(我使用了“tox”)

  2. testing环境:

 $ uname -a Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux 

在我的情况下,我需要不变的字节数来实现一个encryption库,其中包含许多我想确保的常量字面数。

这个答案的作品,但试图重新分配bytearray元素不会引发错误。

 def const(func): '''implement const decorator''' def fset(self, val): '''attempting to set a const raises `ConstError`''' class ConstError(TypeError): '''special exception for const reassignment''' pass raise ConstError def fget(self): '''get a const''' return func() return property(fget, fset) class Consts(object): '''contain all constants''' @const def C1(): '''reassignment to C1 fails silently''' return bytearray.fromhex('deadbeef') @const def pi(): '''is immutable''' return 3.141592653589793 

常量是不可变的,但常量bytearray赋值失败:

 >>> c = Consts() >>> c.pi = 6.283185307179586 # (https://en.wikipedia.org/wiki/Tau_(2%CF%80)) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "consts.py", line 9, in fset raise ConstError __main__.ConstError >>> c.C1[0] = 0 >>> c.C1[0] 222 >>> c.C1 bytearray(b'\xde\xad\xbe\xef') 

一个更强大,更简单,也许更“pythonic”的方法涉及使用memoryview对象(<= python-2.6中的缓冲对象)。

 import sys PY_VER = sys.version.split()[0].split('.') if int(PY_VER[0]) == 2: if int(PY_VER[1]) < 6: raise NotImplementedError elif int(PY_VER[1]) == 6: memoryview = buffer class ConstArray(object): '''represent a constant bytearray''' def __init__(self, init): ''' create a hidden bytearray and expose a memoryview of that bytearray for read-only use ''' if int(PY_VER[1]) == 6: self.__array = bytearray(init.decode('hex')) else: self.__array = bytearray.fromhex(init) self.array = memoryview(self.__array) def __str__(self): return str(self.__array) def __getitem__(self, *args, **kwargs): return self.array.__getitem__(*args, **kwargs) 

ConstArray项目分配是TypeError

 >>> C1 = ConstArray('deadbeef') >>> C1[0] = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'ConstArray' object does not support item assignment >>> C1[0] 222 

我为python const编写一个util lib: kkconst – pypi支持str,int,float,datetime

const字段实例将保持其基本types的行为。

例如:

 from __future__ import print_function from kkconst import ( BaseConst, ConstFloatField, ) class MathConst(BaseConst): PI = ConstFloatField(3.1415926, verbose_name=u"Pi") E = ConstFloatField(2.7182818284, verbose_name=u"mathematical constant") # Euler's number" GOLDEN_RATIO = ConstFloatField(0.6180339887, verbose_name=u"Golden Ratio") magic_num = MathConst.GOLDEN_RATIO assert isinstance(magic_num, ConstFloatField) assert isinstance(magic_num, float) print(magic_num) # 0.6180339887 print(magic_num.verbose_name) # Golden Ratio 

more details usage you can read the pypi url: pypi or github

You can wrap a constant in a numpy array, flag it write only, and always call it by index zero.

 import numpy as np # declare a constant CONSTANT = 'hello' # put constant in numpy and make read only CONSTANT = np.array([CONSTANT]) CONSTANT.flags.writeable = False # alternatively: CONSTANT.setflags(write=0) # call our constant using 0 index print 'CONSTANT %s' % CONSTANT[0] # attempt to modify our constant with try/except new_value = 'goodbye' try: CONSTANT[0] = new_value except: print "cannot change CONSTANT to '%s' it's value '%s' is immutable" % ( new_value, CONSTANT[0]) # attempt to modify our constant producing ValueError CONSTANT[0] = new_value >>> CONSTANT hello cannot change CONSTANT to 'goodbye' it's value 'hello' is immutable Traceback (most recent call last): File "shuffle_test.py", line 15, in <module> CONSTANT[0] = new_value ValueError: assignment destination is read-only 

of course this only protects the contents of the numpy, not the variable "CONSTANT" itself; you can still do:

 CONSTANT = 'foo' 

and CONSTANT would change, however that would quickly throw an TypeError the first time CONSTANT[0] is later called in the script.

although… I suppose if you at some point changed it to

 CONSTANT = [1,2,3] 

now you wouldn't get the TypeError anymore. hmmmm….

https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.setflags.html

We can create a descriptor object:

 class Constant: def __init__(self,value=None): self.value = value def __get__(self,instance,owner): return self.value def __set__(self,instance,value): raise ValueError("You can't change a constant") class A: NULL = Constant() NUM = Constant(0xFF) class B: NAME = Constant('bar') LISTA = Constant([0,1,'INFINITY']) >>> obj=A() >>> print(obj.NUM) #=> 255 >>> obj.NUM =100 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: You can't change a constant 

Here's a trick if you want constants and don't care their values:

Just define empty classes.

例如:

 class RED: pass class BLUE: pass 

You can use StringVar or IntVar, etc, your constant is const_val

 val = 'Stackoverflow' const_val = StringVar(val) const.trace('w', reverse) def reverse(*args): const_val.set(val) 

Extending Raufio's answer, add a repr to return the value.

 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) def __repr__(self): return ('{0}'.format(self.value)) dt = const(float(0.01)) print dt 

then the object behaves a little more like you might expect, you can access it directly rather then '.value'

well.. even though this is outdated, let me add my 2 cents here 🙂

 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) 

Instead of ValueError to break, you can prevent any update happening there. One advantage of this is that you can add constants dynamically in the program but you cannot change once a constant is set. Also you can add any rule or whatsoever before setting a constant(something like key must be a string or a lower case string or upper case string and so on before setting the key)

However, I do not see any importance of setting constants in Python. No optimizations can happen like in C and hence it is something that is not required, I guess.

You can emulate constant variables with help of the next class. An example of usage:

 # Const const = Const().add(two=2, three=3) print 'const.two: ', const.two print 'const.three: ', const.three const.add(four=4) print 'const.four: ', const.four #const.four = 5 # a error here: four is a constant const.add(six=6) print 'const.six: ', const.six const2 = Const().add(five=5) # creating a new namespace with Const() print 'const2.five: ', const2.five #print 'const2.four: ', const2.four # a error here: four does not exist in const2 namespace const2.add(five=26) 

Call the constructor when you want to start a new constant namespace. Note that the class is under protection from unexpected modifying sequence type constants when Martelli's const class is not.

The source is below.

 from copy import copy class Const(object): "A class to create objects with constant fields." def __init__(self): object.__setattr__(self, '_names', []) def add(self, **nameVals): for name, val in nameVals.iteritems(): if hasattr(self, name): raise ConstError('A field with a name \'%s\' is already exist in Const class.' % name) setattr(self, name, copy(val)) # set up getter self._names.append(name) return self def __setattr__(self, name, val): if name in self._names: raise ConstError('You cannot change a value of a stored constant.') object.__setattr__(self, name, val) 

A python dictionary is unchangeable once declared and can serve as constants.

 my_consts={"TIMEOUT":300, "RETRIES":10, "STATE":"happy"} i=301 if i > my_consts["TIMEOUT"]: print "I've just timed out. Sorry folks." print "I tried, many times, " + str(my_consts["RETRIES"]) + " in fact." print "But I am still feeling quite " + my_consts["STATE"]