簡體   English   中英

Python從字典中獲取值的最佳方法?

[英]Python best way to assume a value from dictionary?

我正在從外部來源閱讀字典,例如

data = {'name': 'James', 'gender': 'male'}

有時

data = {'name': 'James', 'gender': 'male', 'article': {'title':'abc'}}

有時

data = {'name': 'James', 'gender': 'male', 'article': None}

我不確定不確定數據中是否存在articles時可以使用.get(key, default)

articles = data.get('article', {}).get('title')

但是有時,它們為元素提供了None值,因此上述內容不起作用並導致錯誤,需要變為:

articles = data.get('article') or {}

但這需要我將其分成2條語句,而不是像前面提到的那樣從文章中獲取值。

有沒有更優雅的方法可以做到這一點,例如:

data.get('article', {}, ignore=[None])

要么

data.get_ignore_none('article', {})

默認情況下,如果鍵不存在, .get()將返回None 您的情況是要返回一個空字典。

現在,我不知道發生了什么錯誤,但是我可以確定它是來自get_stuff(article)而不是您的列表理解。

您可以通過以下幾種方法解決此問題:

  1. 修改get_stuff ,使其直接獲取值,而不是每個元素。 這樣,您只是將它傳遞給[get_stuff(value) for value in data.get('articles')] 現在,在get_stuff ,您只需執行以下操作:

     def get_stuff(foo): if not foo: return None for item in foo: do stuff return normal_results 
  2. 在列表理解中添加一個過濾器:

     [get_stuff(foo) for foo in data.get('articles') if data.get('articles')] 

在這種情況下,使用異常盡早爆發沒有什么錯。 我假設無論數據是什么,都想要標題值或“無”。 以下功能將起作用(對於Python 3)。

def get_title(d):
    try:
        return data.get("article").get("title")
    except AttributeError:
        return None

如果外部字典獲得None作為值,或者默認情況下,它將在您剛剛捕獲的None對象上引發AttributeError。

首先,您似乎認為使用or表達式來丟棄data.get('article') false-y結果只能在以下兩條語句中完成:

temp = data.get('article') or {}
articles = temp.get("title")

但是,您可以將括號放在第一個表達式周圍,然后直接在其返回值上調用.get("title")

articles = (data.get('article') or {}).get("title")

但是我覺得這不是特別可讀或有效,當缺少'article'或“ None您正在創建一個新的映射並不必要地檢查它的"title"

一種可能的解決方案是使用如下函數:

def nested_get(mapping, *keys):
    """gets a value from a nested dictionary,
if any key along the way is missing or None then None is returned
will raise an AttributeError if a value in the chain is not a dictionary (support the .get method)"""
    current = mapping
    for item in keys:
        current = current.get(item)
        if current is None:
            return None
    return current

然后,您將執行nested_get(data, "article", "title")來嘗試獲取data["article"]["title"] ,如果data["article"]為None或丟失則不會引發錯誤。

我使用以下代碼對此進行了測試:

test_cases = [{'name': 'James', 'gender': 'male'},
              {'name': 'James', 'gender': 'male', 'article': {'title':'abc'}},
              {'name': 'James', 'gender': 'male', 'article': None}]

for case in test_cases:
    print(case)
    print(nested_get(case,"article","title"))
    print()

#the follwing will raise an error since mapping["a"] would need to be a dict
nested_get({"a":5}, "a","b")

這個怎么樣

>>> data = {1:(42,23)}
>>> [x for x in data.get(1) or []]
[42, 23]
>>> [x for x in data.get(32) or []]
[]

使用or更改為默認值,以防萬一您得到None或等同於false的信息

編輯

以相同的方式,您可以將or和括起來,以在一行中獲得所需的輸出

articles = (data.get('article') or {}).get('title')

只需處理所有3種情況即可。

您還可以例如定義get_ignore_none

def get_ignore_none(data_dict, key, default=None):
    if key in data_dict:
        value = data_dict[key]
        return value if value is not None else default
    return default

由於您是從外部來源加載此數據,因此一種方法是在您加載后立即進行預處理:

from collections import Mapping

def remove_none(d):
    for k, v in d.items():
        if v is None:
            del d[k]
        if isinstance(v, Mapping):
            remove_none(v)

data = load_data_from_somewhere()
remove_none(data)

現在,您可以隨處使用get來進行以下操作:

articles = data.get('article', {}).get('title')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM