[英]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.