On 01Jan2021 16:34, Steven D'Aprano <[email protected]> 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 <[email protected]>
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/CFZNLRQJENSDQLJ5F456F7G6ZHINSGMV/
Code of Conduct: http://python.org/psf/codeofconduct/