在Python中使用字典(dict)键时,似乎有一些通用的方法:
some_dict['key_name'] # string constants everywhere
some_dict[KeyConstants.key_name] # where class KeyConstants: key_name: 'key_name'
some_dict[KEY_NAME] # with from some_module import KEY_NAME # a module level constant
'key_name'的缺点是您在整个代码中重复常量。这不是干的。更糟糕的是,如果您要发布您的API(从最广泛的意义上说),您将让API的消费者在任何地方重复这些常量,如果您想要将'key_name'更改为'better_key_name',那将是一个重大变化
这是键入的语言DRY方法,常量合并在一个地方。它唯一的缺点是它丑陋,可读性稍差,而且更冗长。 Pythonic原则主要禁止这样做。它允许您轻松更改表示键的常量,因为每个人都在对变量KeyConstants.key_name进行编码。它也适用于IDE进行重构。
PEP 8样式指南中建议使用模块级常量。 ALL_CAPS_ARE_LOUD并且难以输入。这具有选项1和2的一些优点。
dict密钥常量的其他一些最佳做法是什么?以上哪种方法是首选的?何时?
答案 0 :(得分:4)
我并不认为#3需要模块级导入;它们只能在模块名称中,例如你可以做How to programmatically set a global (module) variable?
之类的事情#2优于#1的优点是拼写错误和过时的值会抛出属性错误“此键不存在!”而不是索引错误“无法找到!” - 总是更好。 #2 - #1。它也不是更冗长,因为如果你输入很多东西,你只需设置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)
关于#3,ALL_CAPS_ARE_LOUD是有原因的;区分d[someVariable]
(可以持有任何关键字)和d[magicKeyword]
变得令人困惑 - 而d[MAGIC_KEYWORD]
明确表示它是一个常量,而不是一些可能持有的变量常数,例如for someVariable in magicKeywords
。 #3基本上等同于到#2,例如re.DOTALL
re
等同于KeyConstants
,无需记住KeyConstants
容器的名称,因为 模块。因此#3优于#2,除非你处于一个奇怪的情况,你有不同类型的键空间。
DRY / OAOO非常重要,但最终与其中任何一个都无关,因为你总是需要重复一个变量名来引用它;你能做的最好就是创建一个别名。
你也可以考虑#4,这是为你的字典赋予属性,例如d.key_name
- 只有当它是可订阅的对象时才适用。
但引用Jochen Ritzel的评论:“使用常量键应该是一个非常罕见的场合”(使用对象的属性,或者他建议可能是一个命名元组,尽管我已经总觉得它们很笨重)
答案 1 :(得分:2)
这是一个老问题,但你有没看过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)