我遇到了一种情况,模块需要进行一些简单但稍微耗时的初始化。结束条件之一是将由初始化填写的一对列表;困扰我的是,列表的角色(基本上是常量)和实际初始化它们的需要之间存在冲突。
我觉得写这样的代码很不舒服:
CONSTANT_LIST = []
DIFFERENT_LIST = []
for item in get_some_data_slowly():
if meets_criteria_one(item):
CONSTANT_LIST.append(item)
continue
if meets_criteria_two(item):
DIFFERENT_LIST.append(item)
由于普通读者会在通常由常量占据的位置看到这些列表,并可能认为它们是空的。
OTOH,如果我能把这写为一个列表理解,我对同样的幕后事实也没意见:
CONSTANT_LIST = [i for i in some_data() if criterion(i)]
等等…除了我需要从同一个(稍微耗时)源中提取两个列表之外,所以两个列表的理解会使代码明显变慢。
更糟糕的是,应用程序将常量隐藏在方法后面:
__private_const_list = None
__other_private_list = None
def public_constant_list():
if __private_const_list: return __private_const_list
# or do the slow thing now and fill out both lists...
# etc
def public_other_const_list():
# same thing
有点傻,因为可能的使用频率基本上是每个会话1次。
正如你所看到的,这不是一个火箭科学问题,但我对Python的感觉一点也不刺痛。这里合适的蟒蛇图案是什么?
循环非常清晰。不要因为太聪明而混淆它。只需使用注释来帮助解释
CONSTANT_LIST = [] # Put a comment here to tell the reader that these
DIFFERENT_LIST = [] # are constants that are filled in elsewhere
"""
Here is an example of what CONSTANT_LIST looks like
...
Here is an example of what DIFFERENT_LIST looks like
...
"""
for item in get_some_data_slowly():
if meets_criteria_one(item):
CONSTANT_LIST.append(item)
elif meets_criteria_two(item):
DIFFERENT_LIST.append(item)
可能使用elif
而不是continue/if