私が見つけた洗練された 2 レベル区切りの解析コマンドを使用できますか。
requestDict = dict(line.split('=') for line in clientRequest.split('&'))
2 番目のレベルの辞書を処理および保存するために、3 番目のレベルを追加しますか?
もちろんできますが、(a) 2 レベルを超えるネストされた内包表記は判読不能になる傾向があるため、おそらくそうしたくないでしょう。(b) この非常に単純な構文は、あなたのようなケースでは機能しません。データはdictに変換できます。
たとえば、どうすればよい'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
これは、コンマで区切られた各コンポーネントの中にコロンがある場合はlikedict
を返しますが、そうでない場合はlikeを返します。{'ip': '192.168.10.10', 'deviceid': '1234', 'optdata': '75BCD15'}
{'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('&'))
最後に 1 つ: 古いバージョンの Python で実行する必要がない限りdict
、ジェネレータ式を頻繁に呼び出すべきではありません。辞書内包表記で書き直せればほぼ間違いなくその方がわかりやすいし、辞書内包表記で書き換えられないならそもそも一行表記じゃないはず。
もちろん、式を個別の式に分割し、それらの一部をステートメントまたは関数に変換し、それらに名前を付けると、コードが長くなりますが、それは必ずしも悪いことを意味するわけではありません。Zen of Python ( import this
) の約半分は、その理由の説明に費やされています。または、Guido からの引用の 1 つ:「Python は、意図的に、コード ゴルフには適していない言語です。」
実際にどのようになるかを知りたい場合は、2 つのステップに分けてみましょう。
>>> {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
. どのシーケンス?わかりません。何が機能しないかを確認するには、段階的に分解する必要があります。それは面白くない。
したがって、うまくいけば、これを行いたくない理由が示されます。