我有一个深层嵌套的dict(从json解码,来自instagram api)。 我的初始代码是这样的:
caption = post['caption']['text']
但如果“标题”键或“文本”键不存在,则会抛出NoneType或KeyError错误。
所以我想出了这个:
caption = post.get('caption', {}).get("text")
哪个有效,但我不确定它的风格。例如,如果我将这种技术应用于我试图检索的更深层次的嵌套属性之一,它看起来很丑陋:
image_url = post.get('images',{}).get('standard_resolution',{}).get('url')
有没有更好,更pythonic的方式来写这个?我的目标是检索数据(如果有的话),但如果数据不存在则不会阻止执行。
谢谢!
答案 0 :(得分:10)
最恐怖的方式就是捕捉KeyError
:
try:
caption = post['caption']['text']
except KeyError:
caption = None
这对Python程序员来说简单明了,并且可以立即理解。
答案 1 :(得分:2)
你觉得这样的事情
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']
所以我认为最恐怖的方式就是ask for forgiveness and not permission
try:
image_url = post['images']['standard_resolution']['url']
except KeyError:
image_url = None
答案 2 :(得分:1)
Python 3.4和更新版本包含一个contextlib上下文管理器suppress
,它正是为了这种事情。当您提前知道它们可能发生并且您的代码可以处理它时,可以抑制特定错误。
from contextlib import suppress
sample = {'foo': 'bar'}
with suppress(KeyError):
print(sample['baz'])
会阻止KeyError
被提升。
因此,要访问获取深层嵌套的字典值,您可以使用suppress
这样的内容。
value = None
with suppress(KeyError):
value = data['deeply']['nested']['dictionary']['key']
答案 3 :(得分:-1)
我创建了一个自定义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
你可以做一个自定义的 init 来处理嵌套的dicts作为另一个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