avoiding recursion in repr?

D

David C. Fox

The __repr__ methods of the built-in list and dict objects properly
avoid an infinite loop when you take the representation of a list or
dictionary which contains itself (or more complicated nestings: list l1
contains list l2 which contains l1, etc.).

Looking at the CPython source code, it seems that the Py_ReprEnter and
Py_ReprLeave functions are used to implement this protection.

Is there any equivalent function for defining new container classes
written in Python, or do potentially recursive containers have to be
implemented in C?

(I could of course try to translate these functions into Python, but I'm
not sure that would catch mixed nestings of my class and list/dict).

David
 
J

John J. Lee

David C. Fox said:
The __repr__ methods of the built-in list and dict objects properly
avoid an infinite loop when you take the representation of a list or
dictionary which contains itself (or more complicated nestings: list
l1 contains list l2 which contains l1, etc.).

Looking at the CPython source code, it seems that the Py_ReprEnter and
Py_ReprLeave functions are used to implement this protection.

Is there any equivalent function for defining new container classes
written in Python, or do potentially recursive containers have to be
implemented in C?

(I could of course try to translate these functions into Python, but
I'm not sure that would catch mixed nestings of my class and
list/dict).

What's a "mixed nesting"?

Couldn't you just use a dict to remember objects that have been seen,
like copy.deep_copy?


John
 
D

David C. Fox

John said:
What's a "mixed nesting"?

For example an instance m of MyList containing a list l containing the
same instance m of MyList...
Couldn't you just use a dict to remember objects that have been seen,
like copy.deep_copy?

No. deep_copy uses a memo argument (with a default value of None) to
pass that dictionary around, but __repr__ for standard containers.
Therefore, in the MyList example above, m.__repr__ can't pass such a
dictionary when it calls the l.__repr__(), so when l.__repr__ calls
m.__repr__ it doesn't get the extra argument. If I'm understanding the
code for lists and dictionaries correctly, I think you need something
global and thread safe (which is what Py_ReprEnter/Leave seem to be for).

David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top