Reputation: 63
def getValueForSpecificKey(self,capturedLog,key):
''' Get value from log for any specific key,caputredLog must be a string'''
global Found
global returnValue
if type(capturedLog)==type({}):
for eachKey in capturedLog:
if eachKey==key:
Found=True
print "Found Key Match :",eachKey
print capturedLog[key]
listAppendValue=capturedLog[key]
#returnValue=capturedLog[key]
returnValue.append(listAppendValue)
print "="*1000
print "The value for key in the captured Log is -> ",capturedLog[key]
print " Return value "*10,(returnValue)
return Found,returnValue
self.getValueForSpecificKey(capturedLog[eachKey],key)
elif type(capturedLog) is list:
for elements in capturedLog:
self.getValueForSpecificKey(elements,key)
print returnValue
return Found,returnValue
I have this function which recursively iterated over a valid json.The json might contain dict or list.The function here searched takes some input log which is json and a key to search in the json.I am able to iterate to get all the keys in the json .Things are fine.
But the problem comes when I try to return the value.Since the returnValue is a global variable .Appending to the list ,keeps on appending all the values to the same list.Even when I create an object of the class from some other module and call this function the list still grows and I am not able to clear/reset the returnValue before/after the function call.I need to change the returnValue which is a list each time the object is created from external module i.e when the first time this function is called.So it is a problem where I need to return value with recursion.
Since the api is already defined I can only change the code within.
Please help. Thanks.
Upvotes: 1
Views: 3336
Reputation: 63
Okay , Here is the solution
Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. This is generally not what was intended. A way around this is to use None as the default, and explicitly test for it in the body of the function, e.g.:
def getValueForSpecificKey(self,capturedLog,key,First=None):
''' Get value from requests log for any specific key,caputredLog must be a string'''
global Found
global returnValue
if First is None:
First='notnone'
Found=False
returnValue=[]
print "Return Value ->",returnValue
print "Found - >",Found
if type(capturedLog)==type({}):
for eachKey in capturedLog:
print eachKey
if eachKey==key:
Found=True
print "Found Key Match :",eachKey
print capturedLog[key]
listAppendValue=capturedLog[key]
returnValue.append(listAppendValue)
print "="*1000
print "The value for key in the captured Log is -> ",capturedLog[key]
print " Return value "*10,(returnValue)
return Found,returnValue
print "CapturedLog - >",capturedLog
print "Calling using recursion "
self.getValueForSpecificKey(capturedLog[eachKey],key,First)
elif type(capturedLog) is list:
for elements in capturedLog:
self.getValueForSpecificKey(elements,key,First)
return Found,returnValue
Upvotes: 1
Reputation: 104792
I think you should alter your recursive function to not need any global variables. If you only expect to find a single result, I think it's not too complicated.
def getValueForSpecificKey(self, capturedLog, key):
'''
Get value from log for any specific key.
capturedLog will be searched if it is a list or dictionary.
Returns None if the key is not found, or capturedLog is another type.
'''
if isinstance(capturedLog, dict):
if key in capturedLog: # base case #1 (found the key)
return capturedLog[key]
values = capturedLog.values()
elif isinstance(capturedLog, list):
values = capturedLog
else:
return None # base case #2 (not a list or dict)
for value in values:
result = self.getValueForSpecificKey(value, key) # recursive case
if result is not None:
return result
return None # nothing found in the recursive search
If you might have multiple values in different dictionaries with the desired key, you'll probably need to pass a list around:
def getValueForSpecificKey(self, capturedLog, key, results=None):
'''
Get value from log for any specific key.
capturedLog will be searched if it is a list or dictionary.
Returns an empty list if the key is not found, or capturedLog is another type.
'''
if results is None:
results = [] # start a new list if this is a non-recursive call
if isinstance(capturedLog, dict):
if key in capturedLog:
results.append(capturedLog[key]) # found a result, add it to the list
return results
values = capturedLog.values()
elif isinstance(capturedLog, list):
values = capturedLog
else:
return results
for value in values: # recursive calls will add to the results list as necessary
self.getValueForSpecificKey(value, key, results)
return results
Upvotes: 1
Reputation: 1152
def getValueForSpecificKey(self,capturedLog,key,first=[])
global returnaValue
if not first:
first.append(1)
returnaValue = []
This will create a global empty list the first time you call it. This will indicate you should clear the global list, returnValue. No api change and works with recursion
Upvotes: 0