Inner workings of this Python feature: Can a Python data structure reference itself?

Terry Reedy tjreedy at udel.edu
Sat May 2 19:17:21 EDT 2015


On 5/2/2015 4:02 PM, vasudevram wrote:
> Hi group,
>
> Please refer to this blog post about code showing that a Python data
> structure can be self-referential:
>
> http://jugad2.blogspot.in/2015/05/can-python-data-structure-reference.html
>
>  Gotten a couple of comments on it already, but interested in hearing
> thoughts of Python core dev team members or others who can comment on
> the internals of how this feature operates, why, etc.

Please correct the following:
   "g (a list) contains itself as a list item (of g)."
g is a dict, as you yourself later said.

"Case 2) But if the evaluation works in a different order, i.e. the 
globals() function is first called (before the variable g is created), 
then at this point its return value (the dict) should not contain the 
item with key 'g' (and value g), and it is this dict that should get 
assigned to the variable g. Hence when we print g, we should not see g 
again within it."

This seems like you are presenting this as a statement of fact, but you 
then admit it is false.  The lead in sentence should more carefully 
state that what follows are possible hypotheses.  one is true and the 
other (mostly) not.

The key point is the meaning of "the globals() function returns a dict 
representing the current global symbol table,"  "Global symbol table" is 
an abstraction.  In CPython, the implementation is a dict and globals 
returns that dict, not a copy.  Python generally does not copy objects 
unless requested.

Similarly, locals() returns a dict representing the current local symbol 
table. In a CPython class statement, the local symbol table is 
implemented with a dict, and locals() is that dict.  In a CPython def 
statement, the local symbol table is implemented as a C array (of 
pointers to PyObjects). Locals() is a dict (created just once) updated 
from local names in the code object and the objects in the array *at the 
time of the call*

 >>> def f(a):
	g = locals()
	print(id(g), g)
	g = locals()
	print(id(g), g)
	
 >>> f(3)
56288136 {'a': 3}
56288136 {'a': 3, 'g': {...}}

'Case 2" applies for the first locals() call, but only for the first.

I believe that there was a time when printing a recursive structure hit 
the recursion limit like your flatten did. But I will not reload 1.5 to 
check.

-- 
Terry Jan Reedy




More information about the Python-list mailing list