簡體   English   中英

遞歸函數打印但不返回

[英]Recursive function prints but does not return

我有一個函數,該函數需要一個鍵並遍歷嵌套的字典以返回該值,而不管其深度如何。 但是,我只能獲取要打印的值,而不能返回。 我已經閱讀了有關此問題的其他問題,並嘗試過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

怎么了? 為什么函數在找到它時就不會中斷並返回值?

一個簡單的解決方法是,您必須找到一個返回值的嵌套字典。 您不需要顯式使用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'

python的設計原則之一是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

正如其他人所評論的那樣,您也需要在else塊中使用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

如果找到,則else塊需要返回該值。

我對您的代碼做了其他一些小的更改。 你不需要做

if item_key in data.keys():

相反,您只需

if item_key in data:

同樣,您不需要

for key in data.keys():

您可以直接在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)測試失敗,或者for循環失敗,則此函數返回None 通常,最好確保遞歸函數中的每個可能的返回路徑都具有顯式的return語句,這樣可以更清楚地了解正在發生的事情,但是恕我直言,可以將這些返回值隱式保留在此相當簡單的函數中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM