我可以采用我发现的光滑的两级定界解析命令吗:
requestDict = dict(line.split('=') for line in clientRequest.split('&'))
并添加第三级来处理和保存第二级字典?
当然可以,但是(a)您可能不想这样做,因为超过两个级别的嵌套理解往往会变得不可读,并且(b)这种超级简单的语法不适用于像您这样的情况,其中只有一些数据可以变成字典。
例如,应该发生'PC'
什么?你想把它变成{'PC': None}
? 或者也许是set
{'PC'}
?还是list
['PC']
?或者干脆别管它?您必须做出决定并为此编写逻辑,并且尝试将其编写为表达式将使您的决定很难阅读。
所以,让我们把这个逻辑放在一个单独的函数中:
def parseCommasAndColons(s):
bits = [bit.split(':') for bit in s.split(',')]
try:
return dict(bits)
except ValueError:
return bits
对于每个以逗号分隔的组件内部都有冒号的情况,这将返回一个dict
like{'ip': '192.168.10.10', 'deviceid': '1234', 'optdata': '75BCD15'}
或,但对于其中任何一个都没有的情况,则返回一个like 。{'AMT-Cam': 'avatar'}
list
['1342177342']
即使这样也可能有点太聪明了;我可能会更明确地检查“这是字典格式吗”,而不是仅仅尝试转换列表列表并查看会发生什么。
无论哪种方式,您如何将其放回您最初的理解中?
好吧,你想在line.split('=')
. 所以让我们为此添加一个函数:
def parseCommasAndColonsForValue(keyvalue):
if len(keyvalue) == 2:
return keyvalue[0], parseCommasAndColons(keyvalue[1])
else:
return keyvalue
requestDict = dict(parseCommasAndColonsForValue(line.split('='))
for line in clientRequest.split('&'))
最后一件事:除非您需要在旧版本的 Python 上运行,否则您不应该经常调用dict
生成器表达式。如果它可以重写为字典推导式,那几乎肯定会更清晰,如果它不能改写为字典推导式,那么它可能一开始就不应该是一个单行表达式。
当然,将表达式分解为单独的表达式,将其中的一些变成语句甚至函数,并命名它们确实会使您的代码更长——但这并不一定意味着更糟。大约一半的 Python 之禅 ( import this
) 致力于解释原因。或者来自 Guido 的一句话:“Python 是一种糟糕的编程语言,这是故意的。”
如果你真的想知道它会是什么样子,让我们把它分成两个步骤:
>>> {k: [bit2.split(':') for bit2 in v.split(',')] for k, v in (bit.split('=') for bit in s.split('&'))}
{'clientid': [['b59694bf-c7c1-4a3a-8cd5-6dad69f4abb0']],
'junketid': [['1342177342']],
'keyid': [['987654321']],
'md': [['AMT-Cam', 'avatar']],
'mk': [['PC']],
'playbackmode': [['st']],
'sessionid': [['']],
'userdata': [['ip', '192.168.10.10'],
['deviceid', '1234'],
['optdata', '75BCD15']],
'ver': [['6']],
'version': [['6.7.8.9012']]}
这说明了为什么您不能只添加dict
对内部级别的调用——因为大多数这些东西实际上并不是字典,因为它们没有冒号。如果你改变了它,那么它就是这样的:
{k: dict(bit2.split(':') for bit2 in v.split(',')) for k, v in (bit.split('=') for bit in s.split('&'))}
我认为这不是很可读,而且我怀疑大多数 Python 程序员会这样做。从现在开始 6 个月后阅读它并试图弄清楚我的意思比写它需要更多的努力。
并且尝试调试它不会很有趣。如果您在输入上运行它,但缺少冒号,会发生什么?ValueError: dictionary update sequence element #0 has length 1; 2 is required
. 哪个序列?不知道。你必须一步一步地分解它,看看什么不起作用。这不好玩。
所以,希望这能说明你为什么不想这样做。