如何在Python中声明常量?
在Java中,我们做:
public static final String CONST_NAME = "Name";
如何在Python中声明常量?
在Java中,我们做:
public static final String CONST_NAME = "Name";
当前回答
Python没有常量。
也许最简单的替代方法是为它定义一个函数:
def MY_CONSTANT():
return 42
MY_CONSTANT()现在拥有常量的所有功能(加上一些讨厌的大括号)。
其他回答
扩展Raufio的答案,添加__repr__来返回值。
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
那么对象的行为就更像你所期望的那样,你可以直接访问它而不是使用"。value "
我忍不住要提供我自己的极简元类实现(这可能是前面元类答案的变体)。
常量存储在容器类中(不需要实例化)。值只能设置一次,但设置后不能更改(或删除)。
就我个人而言,我目前还没有这个用例,但这是一个有趣的练习。
class MetaConstant(type):
''' Metaclass that allows underlying class to store constants at class-level (subclass instance not needed).
Non-existent attributes of underlying class (constants) can be set initially, but cannot be changed or deleted.
'''
def __setattr__(klass, attr, value):
'If attribute (constant) doesn\'t exist, set value. If attribute exists, raise AttributeError.'
if hasattr(klass, attr):
raise AttributeError(f'Can\'t change the value of the constant {klass.__name__}.{attr} to {value}'
f' (the value of {klass.__name__}.{attr} is already set to'
f' {getattr(klass, attr)}).')
super().__setattr__(attr, value)
def __delattr__(klass, attr):
if hasattr(klass, attr):
raise AttributeError(f'Can\'t delete constant {klass.__name__}.{attr}'
f' (set to {getattr(klass, attr)}).')
class Constants(metaclass=MetaConstant):
'Container class for constants. No instantiation required.'
#pass # uncomment if no constants set upon class creation
B = 'Six' # sets Constants.B to 'Six'
Constants.B = 6 # AttributeError
del Constants.B # AttributeError
Constants.A = 'Five' # sets Constants.A to 'Five'
Constants.A = 5 # AttributeError
del Constants.A # AttributeError
请随意提出改进建议。
我将创建一个重写基对象类的__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字典是可变的,所以它们似乎不是声明常量的好方法:
>>> constants = {"foo":1, "bar":2}
>>> print constants
{'foo': 1, 'bar': 2}
>>> constants["bar"] = 3
>>> print constants
{'foo': 1, 'bar': 3}
没有完美的方法可以做到这一点。据我所知,大多数程序员只是将标识符大写,所以PI = 3.142可以很容易地理解为一个常数。
另一方面,如果你想要一个像常数一样的东西,我不确定你能找到它。无论你做什么,总会有一些方法来编辑“常数”,所以它不是一个真正的常数。这里有一个非常简单的例子:
def define(name, value):
if (name + str(id(name))) not in globals():
globals()[name + str(id(name))] = value
def constant(name):
return globals()[name + str(id(name))]
define("PI",3.142)
print(constant("PI"))
这看起来像是一个php风格的常量。
在现实中,所有需要改变值的人是这样的:
globals()["PI"+str(id("PI"))] = 3.1415
这对于你在这里找到的所有其他解决方案都是一样的——即使是那些创建类并重新定义set属性方法的聪明的解决方案——总有一种方法可以绕过它们。Python就是这样的。
我的建议是避免所有的麻烦,将标识符大写。它不是一个合适的常数,但也没有什么合适的常数。