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