2016-12-11 144 views
0

我有一个函数,它接受一个键并遍历嵌套的字典,无论其深度如何,都会返回该值。但是,我只能得到打印的价值,而不是返回。我已阅读关于此问题的其他问题,并已尝试1.实现yield 2.将值附加到列表中,然后返回列表。递归函数打印但不返回

def get_item(data,item_key): 
    # data=dict, item_key=str 
    if isinstance(data,dict): 
     if item_key in data.keys(): 
      print data[item_key] 
      return data[item_key] 
     else: 
      for key in data.keys(): 
       # recursion 
       get_item(data[key],item_key) 

item = get_item(data,'aws:RequestId') 
print item 

的样本数据:

data = OrderedDict([(u'aws:UrlInfoResponse', OrderedDict([(u'@xmlns:aws', u'http://alexa.amazonaws.com/doc/2005-10-05/'), (u'aws:Response', OrderedDict([(u'@xmlns:aws', u'http://awis.amazonaws.com/doc/2005-07-11'), (u'aws:OperationRequest', OrderedDict([(u'aws:RequestId', u'4dbbf7ef-ae87-483b-5ff1-852c777be012')])), (u'aws:UrlInfoResult', OrderedDict([(u'aws:Alexa', OrderedDict([(u'aws:TrafficData', OrderedDict([(u'aws:DataUrl', OrderedDict([(u'@type', u'canonical'), ('#text', u'infowars.com/')])), (u'aws:Rank', u'1252')]))]))])), (u'aws:ResponseStatus', OrderedDict([(u'@xmlns:aws', u'http://alexa.amazonaws.com/doc/2005-10-05/'), (u'aws:StatusCode', u'Success')]))]))]))]) 

当我执行,所需的值可以打印,但不会返回:

>>>52c7e94b-dc76-2dd6-1216-f147d991d6c7 
>>>None 

这是怎么回事?为什么函数没有找到它并返回值呢?

+0

你必须在'else'子句中返回''。 – AChampion

+0

@AChampion我试过 - 仍然返回'无',甚至没有打印出值 –

+0

阅读此:http://stackoverflow.com/questions/11356168/return-in-recursive-function – MYGz

回答

3

一个简单的修复,你必须找到一个嵌套的字典,返回一个值。您不需要明确使用else子句,因为if返回。你也不需要调用.keys()

def get_item(data, item_key): 
    if isinstance(data, dict): 
     if item_key in data: 
      return data[item_key] 

     for key in data: 
      found = get_item(data[key], item_key) 
      if found: 
       return found 
    return None # Explicit vs Implicit 

>>> get_item(data, 'aws:RequestId') 
'4dbbf7ef-ae87-483b-5ff1-852c777be012' 

一个蟒蛇的设计原则是EAFP(更容易请求原谅比许可),这意味着异常较为普遍比其他语言的使用。以上EAFP设计改写如下:

def get_item(data, item_key): 
    try: 
     return data[item_key] 
    except KeyError: 
     for key in data: 
      found = get_item(data[key], item_key) 
      if found: 
       return found 
    except (TypeError, IndexError): 
     pass 
    return None 
+0

不错。试图理解@Mohammad Yusuf Ghazi的链接,但这是一个更简单的解释。谢谢 –

0

正如其他人所评论的,在其他块中也需要return语句。你有两个if块,所以你需要两个return语句。这里是你可能想要的代码

from collections import OrderedDict 

def get_item(data,item_key): 
    result = [] 
    if isinstance(data, dict): 
     for key in data: 
      if key == item_key: 
       print data[item_key] 
       result.append(data[item_key]) 
      # recursion 
      result += get_item(data[key],item_key) 
     return result 
    return result 
0

你的else块如果发现它需要返回值。

我对你的代码做了一些其他的小改动。你不需要做

if item_key in data.keys(): 

相反,你可以简单地做

if item_key in data: 

同样,你不需要

for key in data.keys(): 

您可以在dict直接迭代(或从dict派生的任何类)遍历其密钥:

for key in data: 

这里是我的版本的代码,它应该在的Python 2.7和Python 3的

from __future__ import print_function 
from collections import OrderedDict 

def get_item(data, item_key): 
    if isinstance(data, dict): 
     if item_key in data: 
      return data[item_key] 

     for val in data.values(): 
      v = get_item(val, item_key) 
      if v is not None: 
       return v 

data = OrderedDict([(u'aws:UrlInfoResponse', 
    OrderedDict([(u'@xmlns:aws', u'http://alexa.amazonaws.com/doc/2005-10-05/'), (u'aws:Response', 
    OrderedDict([(u'@xmlns:aws', u'http://awis.amazonaws.com/doc/2005-07-11'), (u'aws:OperationRequest', 
    OrderedDict([(u'aws:RequestId', u'4dbbf7ef-ae87-483b-5ff1-852c777be012')])), (u'aws:UrlInfoResult', 
    OrderedDict([(u'aws:Alexa', 
    OrderedDict([(u'aws:TrafficData', 
    OrderedDict([(u'aws:DataUrl', 
    OrderedDict([(u'@type', u'canonical'), ('#text', u'infowars.com/')])), 
     (u'aws:Rank', u'1252')]))]))])), (u'aws:ResponseStatus', 
    OrderedDict([(u'@xmlns:aws', u'http://alexa.amazonaws.com/doc/2005-10-05/'), 
     (u'aws:StatusCode', u'Success')]))]))]))]) 

item = get_item(data, 'aws:RequestId') 
print(item) 

输出运行

4dbbf7ef-ae87-483b-5ff1-852c777be012 

注意,这个函数如果isinstance(data, dict)测试失败返回None,或者for循环无法返回。确保递归函数中每条可能的返回路径都有明确的return语句,因为这样可以更清楚地说明发生了什么,但恕我直言,将这些返回隐含在这个相当简单的函数中是可以的。