1. 18
  1. 4

    This is very neat, but I would like to approach it a bit differently.

    Python allows self referencing objects and is able to handle this gracefully when printing and computing

    >>> a = {}
    >>> a['self'] = a
    >>> a
    {'self': {...}}
    >>> a['self']
    {'self': {...}}
    >>> a['self']['self']
    {'self': {...}}
    

    Python also allows chained assignments

    >>> a = b = c = d = 23.4567
    >>> a
    23.4567
    >>> b
    23.4567
    >>> c
    23.4567
    >>> d
    23.4567
    

    Also, a dictionary has to be initialized before a key access

    >>> a['k'] = {}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'a' is not defined
    

    So what the neat

    >>> a = a['k'] = {}
    >>> a
    {'k': {...}}
    

    teaches us is how Python goes about allocating things in a chained assignment

    Let’s look at something else with recursion which is easier for me to illustrate

    >>> a = a[0] = [0, 1]
    >>> a
    [[...], 1]
    
    >>> a = a[1] = [0, 1]
    >>> a
    [0, [...]]
    

    It looks like

    1. [0, 1] -> a
    2. a[0] -> a (since if a[0] = [0, 1] there would be no recursion)

    If we extend the chain (a = b = c = d = ...) what is the pattern?

    I couldn’t think of a test that would let me dissociate if what is happening is

    1. a = x
    2. b = a
    3. c = a
    4. d = a

    or

    1. a = x
    2. b = a
    3. c = b
    4. d = c

    I might think of something tomorrow.

    1. 3

      Every Python object has an infinitely recursive set of attributes because methods are functions and functions are objects and all objects have methods. It’s a fun way to hit a stack overflow chasing them down.