On 01Jan2021 16:34, Steven D'Aprano <st...@pearwood.info> wrote: >This isn't so much an idea for Python, as a request for ideas to solve a >problem in Python. > >Back in the early days of Python, printing recursive lists could crash >the interpreter: > > a = [1, 2, 3] > a.append(a) > print(a) > >If you try that today, you get a nice display: > > [1, 2, 3, [...]] [...] >Is there something we can do to make it easier for people to deal with >recursive data structures, like the list repr and deepcopy code does? Is >there a pattern we can abstract out and provide as a tool or recipe for >people to use in their own code?
I don't know about a tool - that might be tricky to generalise - but my standard pattern for this is: def recurse(o, seen=None): if seen is None: seen = set() if id(o) in seen: return seen.add(id(o)) walk o and call recurse(sub_object, seen) ... The key to store in seen isn't always id(o), and for some tasks I discard the key on my way back out of the recursion. I can imagine writing a decorator for this. I'd probably like it to look like this: @no_recurse(keyfunc=None,popkey=False): def recurse(o, *, seen): ... recurse(sub_object, seen) maybe (untested): @decorator def no_recurse(func, keyfunc=None, popkey=False): if keyfunc is None: keyfunc = id def no_recurse_wrapper(o, *a, seen=None, **kw): if seen is None: seen = set() k = keyfunc(o) if k in seen: return None seen.add(k) try: return func(o, *a, seen=seen, **kw) finally: if popkey: seen.discard(k) The "@decorator" decorator is one of my own which decorates a decorator which may accept parameter of not, allowing both: @no_recurse def recurse(o, blah..., *, seen, other_kwargs...): and also: @no_recurse(keyfunc=lambda o: o.idkey()) def recurse(o, blah..., *, seen, other_kwargs...): for some nondefault decoration. There are some missing features there: what to return when recusion is encoutered (rather than None above), some mode to make the occurrence of recursion trivially noticeable by the primary function to do something better than "return None", etc etc. Cheers, Cameron Simpson <c...@cskk.id.au> _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/CFZNLRQJENSDQLJ5F456F7G6ZHINSGMV/ Code of Conduct: http://python.org/psf/codeofconduct/