迭代 Python 字典并构建新字典的正确方法

Proper way to iterate Python dictionary and build new one

我正在尝试找到一种有说服力的方法来检查字典中是否存在某些键并使用它们来构建新键。

这是我的例子json:

 "dmarc": {
    "record": "v=DMARC1; p=none; rua=mailto:dmarc.spc@test.domain; adkim=s; aspf=s",
    "valid": true,
    "location": "test.domain",
    "warnings": [
                "DMARC record at root of test.domain has no effect"
                ],
     "tags": {
            "v": {
                   "value": "DMARC1",
                   "explicit": true
                 },
            "p": {
                   "value": "none",
                   "explicit": true
                 },
            "rua": {
                   "value": [
                          {
                           "scheme": "mailto",
                           "address": "ssc.dmarc.spc@canada.ca",
                           "size_limit": null
                          }
                         ],
                   "explicit": true
                   },
            "adkim": {
                   "value": "s",
                   "explicit": true
                     },
            "aspf": {
                   "value": "s",
                   "explicit": true
                   },
            "fo": {
                   "value": [
                             "0"
                            ],
                   "explicit": false
                  },
           "pct": {
                   "value": 100,
                   "explicit": false
                  },
           "rf": {
                  "value": [
                            "afrf"
                           ],
                  "explicit": false
                 },
           "ri": {
                  "value": 86400,
                  "explicit": false
                 },
           "sp": {
                  "value": "none",
                  "explicit": false
                 }
             }
       }
 }

我特别想做的是拉 recordvalidlocationtags-ptags-sptags-pct 以编程方式,而不是做一堆 try/excepts。例如,要获得 valid,我这样做:

try:
    res_dict['valid'] = jsonData['valid']
except KeyError:
    res_dict['valid'] = None

现在,对于顶级 key/values,这很容易 loop/repeat,但是对于嵌套 key/values,我将如何完成此操作?

简单:使用

代替dict['key']
  • dict.get('key', {}) 对于所有不是叶子的节点,并且
  • dict.get('key', DEFAULT) 用于叶子,其中 DEFAULT 是您需要的任何内容。

如果您省略 DEFAULT 并且 'key' 不存在,您将得到 None。参见 the docs

例如:

jsonData.get('record', "")    # empty string if no 'record' key
jsonData.get('valid', False)  # False if no 'valid' key
jsonData.get('location')      # None if no 'location'
jsonData.get('tags', {}).get('p')  # None if no 'tags' and/or no 'p'
jsonData.get('tags', {}).get('p', {})  # {} if no 'tags' and/or no 'p'
jsonData.get('tags', {}).get('p', {}).get('explicit', False)  # and so on

以上假定您不遍历列表(JSON 数组)。如果这样做,您仍然可以使用

  • dict.get('key', [])

但如果您必须从那里深入研究,您可能需要循环遍历列表项。

不,您不需要 try-except 块。您可以使用以下方法检查密钥是否存在:

if jsonData.get("valid"):
    res_dict["valid"] = jsonData.get("valid")

.get("key") 方法 return 是给定 key 的值,如果字典中存在的话。如果没有,那么它将 return None (如果 get() 仅与一个参数一起使用)。

如果你想让它 return 如果它找不到 key 其他东西,那么假设:

jsonData.get("valid", "invalid_something_else")

处理这个问题的一种方法是利用 dict.keys 的结果可以被视为 set 这一事实。见以下代码。

my_keys = {'record', 'valid', 'location'} # you can add more here
new_dict = {}
available_keys = my_keys & jsonData.keys()
for key in available_keys:
    new_dict[key] = jsonData[key]

上面,我们在 my_keys 集合中定义了我们感兴趣的键。然后,我们通过获取字典中的键和我们感兴趣的键的交集来获取可用键。实际上,这只会获得我们感兴趣的键,这些键也在字典中定义。最后,我们只是遍历 available_keys 并构建新字典。

但是,如果输入字典中不存在键,这不会将键设置为 None。为此,最好使用其他答案中提到的 get 方法,例如:

my_keys = ['record', 'valid', 'location'] # you can add more here
new_dict = {}
for key in my_keys:
    new_dict[key] = jsonData.get(key)

get 方法允许我们尝试获取字典中键的值。如果未定义该键,则它 returns None。您还可以通过向 get 方法添加额外参数来更改返回的默认值,例如 new_dict[key] = jsonData.get(key, "some other default value")