How to seek all values without recursion: use a stack. It's harder to write the script, but it's probably faster or at least costs less memory, as you don't know how much resources Python allocates when invoking recursive functions.
Now, using recursive functions:
import sys
def write (*args, **kwargs):
sys.stdout.write(*args, **kwargs)
def seek (data, level=0, cache=[]):
dtype = type(data)
tabs = ' '
if (dtype is dict):
if (data in cache):
write ('__CircularReference__')
else:
cache.append(data)
write ('{\n')
level += 1
for k in data:
write (level * tabs + '"'+k+'": ')
seek(data[k], level, cache)
write (',\n')
level -= 1
write (level * tabs + '}')
elif (dtype is list):
if (data in cache):
write ('__CircularReference__')
else:
cache.append(data)
write ('[\n')
level += 1
c = 0
for i in data:
write (level * tabs + '['+ str(c) +']: ')
seek(data[c], level, cache)
write (',\n')
c += 1
level -= 1
write (level * tabs + ']')
else:
write (str(data))
def main ():
data = {
"a": 1,
"b": "Yep",
"list": [0, 1, 2, [{"data": "123", "another_list": [4, 5, 6]}, 7, 8, 9, 10] ],
}
data['circular'] = data
seek(data)
if __name__ == '__main__':
main()
The expected output should be:
{
"a": 1,
"b": Yep,
"list": [
[0]: 0,
[1]: 1,
[2]: 2,
[3]: [
[0]: {
"data": 123,
"another_list": [
[0]: 4,
[1]: 5,
[2]: 6,
],
},
[1]: 7,
[2]: 8,
[3]: 9,
[4]: 10,
],
],
"circular": __CircularReference__,
}
Now, I added a cache to detect Circular References, stated from @Tony Gweesip which was a few seconds faster than me when posting this answer. It was fun :)