Python 字典键常量最佳实践是什么?

26 投票
2 回答
15304 浏览
提问于 2025-04-16 18:08

在Python中使用字典(dict)键的时候,有几种常见的方法:

  1. some_dict['key_name'] # 到处都是字符串常量

  2. some_dict[KeyConstants.key_name] # 这里的类是 KeyConstants: key_name: 'key_name'

  3. some_dict[KEY_NAME] # 从某个模块导入 KEY_NAME # 这是模块级常量

    1. 使用'key_name'的缺点是你在代码中到处重复常量。这种做法不符合“不要重复自己”(DRY)的原则。更糟的是,如果你将来要发布你的API(广义上讲),使用你API的人会到处重复这些常量。如果你想把'key_name'改成'better_key_name',这就会造成很大的问题。

    2. 这种方法是类型化语言的DRY做法,把常量集中在一个地方。它的缺点是看起来不太美观,稍微难读,而且代码会更长。Python的原则主要是反对这种做法。不过,它让你可以轻松地更改表示键的常量,因为大家都是在用变量KeyConstants.key_name来编写代码。这种方法在重构时也很适合使用IDE。

    3. 模块级常量在PEP 8风格指南中是推荐的。使用全大写字母的常量看起来比较显眼,但也更难输入。这种方法结合了前两种方法的一些优点。

还有哪些关于字典键常量的最佳实践?以上哪种方法更受欢迎,适合在什么情况下使用?

2 个回答

1

这是个老问题,不过你有没有看看 Bunch 呢?它是一个字典,支持像JavaScript那样的属性访问方式。

>>> from bunch import bunchify
>>> from bunch import unbunchify
>>> import datetime as dt

>>> my_dict = {'a': 'a', 'b': [{'c': 'c', 'n': 1}, {'c': 'k', 'n': 2}], 'dt': dt.datetime.utcnow()}

>>> my_dict_obj = bunchify(my_dict) 
>>> my_dict_obj.b[0].c
'c'
>>>  'a' in my_dict_obj
True
>>>  'x' in my_dict_obj
False
>>> my_dict = unbunchify(my_dict_obj)
9
  1. d['key_name']
  2. d[Keys.key_name]
  3. d[KEY_NAME]

我觉得第三种写法不需要在模块开头导入东西;它们可以直接在模块的命名空间里,比如你可以做一些像如何以编程方式设置全局(模块)变量?的事情。

第二种写法比第一种的好处在于,如果你写错了或者用的值过时了,它会报一个属性错误,提示“这个键不存在!”而不是索引错误“找不到!”——这总是更好的。第二种写法比第一种更优。它也并没有更啰嗦,因为如果你打得比较多,可以先设置一个别名,比如K=Keys,这样你就可以用d[K.key_name],只多了两个字符。例如,根据我当时的心情,我可能会这样做:

import subprocess as proc
proc.Popen(..., stdout=proc.PIPE)

或者

import subprocess as proc
PIPE = proc.PIPE
proc.Popen(..., stdout=PIPE)

或者

from subprocess import *
Popen(..., stdout=PIPE)

关于第三种写法,全部大写的原因是因为它显得很“吵”;这会让人很难区分d[someVariable](这个可以是任何关键字)和d[magicKeyword]——而d[MAGIC_KEYWORD]就很明确,它是一个常量,而不是某个可能持有常量的变量,比如for someVariable in magicKeywords。所以第三种写法基本上等同于第二种,比如re.DOTALLre相当于KeyConstants,而且不需要记住KeyConstants的名字,因为它就是那个模块)。因此,除非你处于一种奇怪的情况,有不同类型的键空间,第三种写法优于第二种。

保持简洁(DRY)和避免重复(OAOO)是非常重要的,但最终和这些都没有关系,因为你总是需要重复变量名来引用它;你能做的最好的就是创建一个别名。

你也可以考虑第四种写法,就是给你的字典添加属性,比如d.key_name——这只有在它是某个可下标的对象时才合适。

但引用Jochen Ritzel的一句话:“使用常量键应该是非常少见的情况”(使用对象的属性,或者像他建议的那样,可能用命名元组,尽管我总觉得它们不太好用)。

撰写回答