如何在Python中声明常量?
在Java中,我们做:
public static final String CONST_NAME = "Name";
如何在Python中声明常量?
在Java中,我们做:
public static final String CONST_NAME = "Name";
当前回答
您可以将一个常量包装在numpy数组中,将其标记为仅写,并始终通过下标0调用它。
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
当然,这只保护numpy的内容,而不是变量“CONSTANT”本身;你仍然可以:
CONSTANT = 'foo'
和CONSTANT会改变,然而,这将很快抛出TypeError第一次在脚本中调用CONSTANT[0]。
尽管……我想如果你在某个时候把它改成
CONSTANT = [1,2,3]
现在你不会再得到TypeError了。嗯……
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.setflags.html
其他回答
你可以使用StringVar或IntVar等,你的常量是const_val
val = 'Stackoverflow'
const_val = StringVar(val)
const.trace('w', reverse)
def reverse(*args):
const_val.set(val)
您可以在下一个类的帮助下模拟常量变量。用法示例:
# 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)
当您希望启动一个新的常量名称空间时,请调用构造函数。注意,当Martelli的const类没有被修改时,这个类受到了保护,不受意外修改序列类型常量的影响。
来源如下。
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)
您可以将一个常量包装在numpy数组中,将其标记为仅写,并始终通过下标0调用它。
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
当然,这只保护numpy的内容,而不是变量“CONSTANT”本身;你仍然可以:
CONSTANT = 'foo'
和CONSTANT会改变,然而,这将很快抛出TypeError第一次在脚本中调用CONSTANT[0]。
尽管……我想如果你在某个时候把它改成
CONSTANT = [1,2,3]
现在你不会再得到TypeError了。嗯……
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.setflags.html
这里有一个技巧,如果你想要常量,而不关心它们的值:
只定义空类。
e.g:
class RED:
pass
class BLUE:
pass
我忍不住要提供我自己的极简元类实现(这可能是前面元类答案的变体)。
常量存储在容器类中(不需要实例化)。值只能设置一次,但设置后不能更改(或删除)。
就我个人而言,我目前还没有这个用例,但这是一个有趣的练习。
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
请随意提出改进建议。