什么是Pythonic方式来访问没有NoneType错误的嵌套字典
我有一个深嵌套字典(解码从JSON,从Instagram的API)。 我最初的代码是这样的:什么是Pythonic方式来访问没有NoneType错误的嵌套字典
caption = post['caption']['text']
但是,这将抛出一个NoneType或KeyError异常错误,如果“字幕”键或“文本”项不存在。
于是我想出了这一点:
caption = post.get('caption', {}).get("text")
其中一期工程,但我不知道它的风格。举例来说,如果我将此技术向更深嵌套的属性,我试图找回之一,它看起来很丑陋:
image_url = post.get('images',{}).get('standard_resolution',{}).get('url')
是否还有更好的,更Python,这样写?我的目标是检索数据,如果存在的话,但不保留执行,如果它不存在。
谢谢!
最Pythonic的方式将只是为了赶上KeyError
:
try:
caption = post['caption']['text']
except KeyError:
caption = None
这对于Python程序员来说很简单,显而易见并且可以立即理解。
请不要将'try:'和'except:'的主体放在与其各自介绍相同的行上。这是[PEP 8](http://www.python.org/dev/peps/pep-0008/)的Definitely Nots中的一个,它本身就是纯音乐。 – Cairnarvon 2013-02-23 03:55:05
已修复,对PEP 8表示歉意。 – nneonneo 2013-02-23 03:56:21
有没有办法将这个推广到多个键?例如如果我想检索'caption.text',但也''images.standard_resolution.url'和'user.username'和其他一些,我必须做尝试/除了块? – 2013-02-23 04:05:40
你怎么看待这样的事情
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
我想创建一个自定义字典的子类,然后只是解决:
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
你既可以做一个自定义初始化处理嵌套类型的字典作为SafeDict的另一个实例(这将让你通过它们)或者你可以使用测试(或者一个try/except块)来防止KeyErrors,也可以使它成为一个对象类,重载__getattr__
,然后用点符号来处理事情。我倾向于选择这种做法(我第一次在塔框架看到这个)
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
'post'字典来自simplejson,我不知道如何让simplejson返回SafeDict,或将标准字典转换为SafeDict。 – 2013-02-23 04:03:08
您的'__getitem __()'代码会比'return self.get(k)'更简单(您大多正在重写'get()'方法)。无论如何,这确实回答了这个问题,因为即使'a = SafeDict({'a':SafeDict({'b':'b'})})''''a''c'] ['d']'这是问题要求解决的问题。 – EOL 2013-02-23 04:04:53
如果你退后一秒......你会注意到调用AnyClass(yourdict)真正调用了'AnyClass .__ init__',并将字典作为kwargs。如果你从'dict'继承了一个类,这些kwargs就成为了字典。如果您从对象继承,则可以使用__init__获得乐趣。个人而言,我可能会用对象符号去。它使得api编程更容易。 – 2013-02-23 04:06:38
的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']
为什么你不能只是发现异常? – Cairnarvon 2013-02-23 03:42:18
我可以。我想是因为我拉〜7键,我不想尝试/除了7次。 – 2013-02-23 03:48:31
相关:[Python:使用列表中的项目更改嵌套字典的字典值](http://stackoverflow.com/questions/11918852/python-change-values-in-dict-of-nested-dicts-using-项目在列表中) – jfs 2013-02-23 03:55:37