代码之家  ›  专栏  ›  技术社区  ›  Kenny Winker

在没有NoneType错误的情况下访问嵌套dicts的Python方法是什么

  •  6
  • Kenny Winker  · 技术社区  · 12 年前

    我有一个深度嵌套的dict(从json解码,从instagramapi解码)。 我最初的代码是这样的:

    caption = post['caption']['text']
    

    但如果“caption”键或“text”键不存在,则会引发NoneType或KeyError错误。

    所以我想到了这个:

    caption = post.get('caption', {}).get("text")
    

    这很有效,但我不确定它的风格。例如,如果我将此技术应用于我试图检索的一个嵌套更深的属性,它看起来很难看:

    image_url = post.get('images',{}).get('standard_resolution',{}).get('url')
    

    有没有更好、更像蟒蛇的方式来写这篇文章?我的目标是检索数据,如果数据在那里,但如果数据不在那里,就不要阻碍执行。

    谢谢

    4 回复  |  直到 12 年前
        1
  •  13
  •   nneonneo    12 年前

    最像Python的方式就是简单地抓住 KeyError :

    try:
        caption = post['caption']['text']
    except KeyError:
        caption = None
    

    对于Python程序员来说,这是简单、显而易见的,并且可以立即理解。

        2
  •  10
  •   Techdragon    8 年前

    Python 3.4及更新版本包含contextlib上下文管理器 suppress ,正是为了这种事情。当您事先知道可能会发生特定错误并且您的代码能够处理这些错误时,就可以抑制这些错误。

    from contextlib import suppress
    
    sample = {'foo': 'bar'}
    
    with suppress(KeyError):
        print(sample['baz'])
    

    将阻止 KeyError 防止被抚养。

    因此,为了访问获取深度嵌套的字典值,可以使用 镇压 这样地。

    value = None
    with suppress(KeyError):
        value = data['deeply']['nested']['dictionary']['key']
    
        3
  •  2
  •   Ric    12 年前

    你对这样的事情感觉如何

    if 'caption' in post:
        caption = post['caption']['text']
    

    但它也开始崩溃

    if 'images' in post and 'standard_resolution' in post['images']:
        image_url = post['images']['standard_resolution']['url']
    

    所以我认为最Python的方式就是 ask for forgiveness and not permission

    try:
        image_url = post['images']['standard_resolution']['url']
    except KeyError:
        image_url = None
    
        4
  •  -1
  •   Jonathan Vanasco    12 年前

    我会创建一个自定义dict子类,然后解决这个问题:

    class SafeDict(dict):
        def __getitem__(self,k):
            if k in self:
                return dict.__getitem__(self,k)
            return None
    
    
    a = SafeDict({'a':'a'})
    print a['a']
    >> a
    print a['b']
    >> None
    

    你可以做一个自定义 初始化 将嵌套dict作为SafeDict的另一个实例处理(这将允许您传递它们),或者您可以使用测试(或try/except块)来防止KeyErrors

    此外,您可以将其作为一个对象类,重载 __getattr__ ,然后用点符号处理。我倾向于使用这种方法(我第一次在Pylons框架中看到这种方法)

    class AttributeSafeObject(object):
    
        def __init__(self,**kwargs):
            for key in kwargs:
                setattr(self,key,kwargs[key])
    
        def __getattr__(self, name):
            try:
                return object.__getattribute__(self,name)
            except AttributeError:
                return None
    
    post = AttributeSafeObject({'a':'a'})
    print post.a
    >> a
    print post.title
    >> None
    
    推荐文章