2016-12-11 142 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語句,因爲這樣可以更清楚地說明發生了什麼,但恕我直言,將這些返回隱含在這個相當簡單的函數中是可以的。