如何在Python中声明常量?
在Java中,我们做:
public static final String CONST_NAME = "Name";
如何在Python中声明常量?
在Java中,我们做:
public static final String CONST_NAME = "Name";
当前回答
元组在技术上属于常量,因为如果您试图更改其中一个值,元组将引发错误。如果你想声明一个只有一个值的元组,那么在它唯一的值后面加一个逗号,就像这样:
my_tuple = (0 """Or any other value""",)
要检查这个变量的值,使用类似这样的方法:
if my_tuple[0] == 0:
#Code goes here
如果您试图更改此值,将引发一个错误。
其他回答
在Python中,不能将变量或值声明为常量。
为了让程序员知道变量是常量,通常用大写:
CONST_NAME = "Name"
要在常量发生变化时引发异常,请参阅Alex Martelli的《Python中的常量》。注意,这在实践中并不常用。
从Python 3.8开始,有一个类型。最后一个变量注释,它将告诉静态类型检查器(如myypy)您的变量不应该被重新分配。这是最接近于Java的final。然而,它实际上并不能阻止重新分配:
from typing import Final
a: Final[int] = 1
# Executes fine, but mypy will report an error if you run mypy on this:
a = 2
也许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中,常量只是一个变量,名称全大写,单词之间用下划线分隔,
e.g
Days_in_week = 7
该值是可变的,即您可以更改它。但既然名字的规则告诉你是常数,你为什么要这么做呢?我是说,这毕竟是你的项目!
这是python中采用的方法。出于同样的原因,没有private关键字。用下划线作为名称的前缀,您就知道它是私有的。代码可以打破规则....就像程序员可以删除private关键字一样。
Python可以添加一个const关键字…但是程序员可以删除关键字,然后如果他们想要更改常量,但为什么要这样做呢?如果你想打破规则,你可以改变规则。但如果名字的意思已经很清楚了,为什么还要费心打破规则呢?
也许在某些单元测试中,对值应用更改是有意义的?看看一周8天会发生什么,尽管在现实世界中,一周的天数是不能改变的。如果语言阻止你做一个例外,如果只有这一个情况,你需要打破规则……然后您将不得不停止将它声明为常量,即使它在应用程序中仍然是常量,并且只有这个测试用例来查看如果它被更改会发生什么。
全大写的名称告诉您它是一个常量。这才是重要的。没有一种语言强制约束代码,无论如何你都可以修改。
这就是python的哲学。
在其他语言中没有const关键字,但是可以创建一个具有“getter函数”来读取数据,但没有“setter函数”来重写数据的Property。这从本质上保护标识符不被更改。
下面是一个使用class属性的替代实现:
请注意,对于想了解常量的读者来说,代码远非简单。见下面的解释。
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(hex(CONST.FOO)) # -> '0xbaadfaceL'
CONST.FOO = 0
##Traceback (most recent call last):
## File "example1.py", line 22, in <module>
## CONST.FOO = 0
## File "example1.py", line 5, in fset
## raise TypeError
##TypeError
代码的解释:
定义一个接受表达式的函数常量,并使用它来构造一个“getter”——一个仅返回表达式值的函数。 setter函数引发TypeError,因此它是只读的 使用我们刚刚创建的常量函数作为装饰来快速定义只读属性。
用另一种更传统的方式:
(代码相当棘手,下面有更多解释)
class _Const(object):
def FOO():
def fset(self, value):
raise TypeError
def fget(self):
return 0xBAADFACE
return property(**locals())
FOO = FOO() # Define property.
CONST = _Const()
print(hex(CONST.FOO)) # -> '0xbaadfaceL'
CONST.FOO = 0
##Traceback (most recent call last):
## File "example2.py", line 16, in <module>
## CONST.FOO = 0
## File "example2.py", line 6, in fset
## raise TypeError
##TypeError
要定义标识符FOO,首先定义两个函数(fset, fget -名称由我选择)。 然后使用内置的属性函数构造一个可以“set”或“get”的对象。 注意属性函数的前两个参数名为fset和fget。 利用我们为自己的getter和setter选择这些名称的事实,并使用应用于该作用域的所有本地定义的**(双星号)创建一个关键字字典,将参数传递给属性函数