我是否应该对常数全部使用大写?


34

我是一名Python程序员,主要使用pylint整理源代码。我可以消除除以下警告以外的所有警告:常量名称无效。将名称更改为全部大写可以解决此问题,但是我真的应该这样做吗?如果这样做,我发现我的代码看起来很丑陋,因为大多数变量都是常量(根据pylint)。


1
如果您的大多数变量都是模块级常量,则可能是在做一些不寻常的事情。他们中的大多数应该住在函数内部。
RemcoGerlich

1
您能给我们看一下pylint认为是常量的代码示例吗?
温斯顿·埃韦特

@WinstonEwertNOTES_DIRECTORY = argv[1] chdir(NOTES_DIRECTORY) FILES = glob('*.txt') RAND_FILE = choice(FILES) with open(RAND_FILE) as notes_file: POINTS = notes_file.readlines() RAND_POINT = choice(POINTS)
Abhishek Kumar

@AbhishekKumar,您的代码在函数中还是在顶层?
Winston Ewert

@WinstonEwert在顶层,并遵循PyLint的说明。
Abhishek Kumar

Answers:


33

您可能正在编写如下代码:

notes_director = argv[1]
chdir(notes_director)
files = glob('*.txt')
rand_file = choice(files)
with open(rand_file) as notes_file: 
    points = notes_file.readlines() 
    rand_point = choice(points)

您应该将此代码移到一个函数中:

def main():
    notes_director = argv[1]
    chdir(notes_director)
    files = glob('*.txt')
    rand_file = choice(files)
    with open(rand_file) as notes_file: 
        points = notes_file.readlines() 
        rand_point = choice(points)

# actually call the main function    
main()

Pylint假定实际完成工作的代码将在函数内部。因为您将这段代码放在代码的顶层,而不是放在函数内部,所以会感到困惑。

一般而言,最好在函数内部而不是在顶层进行工作。这使您可以更好地组织您正在做的事情,并有利于重用它。实际上,您应该只让代码在快速而肮脏的脚本中执行功能之外的算法。


1
强烈不同意,我认为使用模块级别变量有很多Python的理由。我认为此建议仅仅是pylint误读PEP8的产物,并且假设“常量应为模块级别”的相反含义也应成立。
MetricSystem

21

是。根据PEP8关于常量的规则:

常量通常在模块级别定义,并以所有大写字母书写,并用下划线分隔单词。示例包括MAX_OVERFLOWTOTAL

长版:

在Python社区中(与许多其他社区一样),存在着有关如何编写代码的约定。这与工作代码不同:即使您将常量全部小写,您的代码仍然可以工作。

但它“强迫”有一样的工具社会共识(如记录在PEP8)pylint的。如果您为自己的幸福而编程,则可能会忽略pylint给您的提示。如果您想与社区进行公开交流,也就是“除了我自己以外的人都应该使用我的代码”,您应该根据PEP8准备代码。


7
另一方面,完全有可能pylint弄错它。Python不提供将常量与变量区分开的方法,除了期望常量始终具有相同的值。pylint假定仅设置一次且永远不会更改的任何内容都是常量,但是除非打算将其设为常量,否则可能只是实现的一种人工产物。特别是,问题注释中给出的代码在每次运行时都将具有不同的值,因此即使pylint认为它们是常量,也不应将其视为常量。
Jules

@Jules我将变量设置为一次并在运行时更改不再是常量,因此在许多语言(例如JS中)中都存在一个const关键字。尽管初始值不同,但可能不同PI
Thomas Junk '18

1
我将不可变变量(即在运行时设置且未更改的变量)和常量(即在每次程序运行中都相同的变量)区分开来,并且如果语言提供了这样做的选项,则可以在编译时进行计算)...重点是因为没有任何方法可以指定与python的区别,pylint因此即使在前一种情况下也假定使用后者。
朱尔斯

Pylint绝对是错误的,因为它读为“常量应该是模块级别”,并假定相反的“模块级别应该是常量”。但是因为它否则是一个很好的有用的工具,所以我们似乎陷入了困境。
MetricSystem

@MetricSystem-在您看来-模块级变量除了是常量还具有什么功能?它应该可变吗?
Thomas Junk

13

PEP8和Python社区规范是要使用的ALL_CAPS_CONSTANTS。这是一个常见的视觉线索,已在C,Java,Perl,PHP,Python,bash和其他编程语言以及Shell环境中使用了数十年。但是用现代的在线说法,所有大写字母都表示喊叫。大喊是无礼的。

但是,Python与不一致ALL_CAPS_CONSTANTS。JavaScript可能有Math.PI,但是Python有math.pi。没有比π更可识别或持久的常数。或者考虑sys.version_info,您正在运行的Python版本。在你的程序的寿命100%不变-远远超过PORTMAX_ITERATIONS或其他常量你定义。还是sys.maxsize呢?平台的最大本机整数值不仅在一个或两个程序运行时恒定,而且在硬件寿命中恒定不变。

如果这些常数-包括π和e这样的常数是宇宙的基本常数,并且不会在整个永恒中变化-如果它们可以是小写字母,那么...其他常数也可以。你可以选择。

请记住,PEP8是样式指南。准则,而不是法律。甚至Python的标准库也经常违反该准则。并引用了另一个Python核心指南PEP20(又名“ Python的禅宗”):

  • 美丽胜于丑陋
  • 可读性计数
  • 实用性胜过纯洁。

从实际音符,当一个程序YELLY_CONSTANT,并SHOUTY_PARAMETER开始篦,它有助于记住,全部大写的常量通常不是真正持久的柏拉图式的理想,但在程序运行的参数。,或并没有真正的常数PORT,也不必将它们作为独立的程序全局变量进行管理。例如,可以将它们作为程序参数的全局可访问包放入字典中:SITENAMENUMRUNS

config = {
    'port': 80,
    'sitename': "Bubba's Blog",
    'numruns': 100,
}

Python还有一个很好的关键字参数传递工具,可以减少使用的需要APPARENTLY_ANGRY_GLOBAL_VARIABLES

def process_data(sitename, port=80, numruns=100):
    ...

process_data("Bubba's Blog")

实际上,将从配置文件,OS环境变量,命令行参数或其他来源中读取(或应读取)许多这些值,以满足控制原理/模式的颠倒。但这又是一个更大的故事。


1

是的,在大多数编程语言中(至少我使用的那些语言)这很普遍。

您可以参考此Google链接,以在同一团队的开发人员之间共享共同的风格。

建议使用

Type                  |Public          |Internal
Global/Class Constants|CAPS_WITH_UNDER |_CAPS_WITH_UNDER
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.