Python - I dont know how to x works in this code
Question: 
    def test(x):
       def add(y):
          return x+y
       def mul(y):
           return x*y
       return "test"
    

will var `x` go to GC?


Answer: Python uses reference counting to manage _objects_ , not variables. If you
want to know when the object referenced by `x` is cleared from memory, you
need to keep track of how many references there are to it. `x` is just one
such reference.

But, if there are _no other references_ to the same object (`x` is the only
reference to it), then yes, that object will be deleted from memory, because
both `add` and `mul` are not returned by `test`.

`x` is used as a closure by those two nested functions, and thus the object
referenced by `x` would gain two additional references (via the function
object closures). But since the function objects are deleted when the function
ends (as they are just locals within `test`), so will their closures, and so
the end result is that there are no more references to the object referenced
by `x` at the end of the `test()` call as there were at the start of the call.

It doesn't matter here that closure cells are somewhat special in that they
track a variable, not an object directly. Closures are just objects too to
Python (albeit with special support in the interpreter to help track the
original reference), so they are subject to reference counting too.

You can use [`sys.getrefcount()`
function](https://docs.python.org/3/library/sys.html#sys.getrefcount) to see
how many references there are to an object:

    
    
    >>> import sys
    >>> def test(x):
    ...    def add(y):
    ...       return x+y
    ...    def mul(y):
    ...        return x*y
    ...    return "test"
    ...
    >>> value = 'foo bar'
    >>> sys.getrefcount(value)
    2
    >>> test(value)
    'test'
    >>> sys.getrefcount(value)
    2
    

The refcount did not change, so `test` never resulted in additional references
after the function completed. This changes if you actually returned the nested
functions:

    
    
    >>> def test2(x):
    ...    def add(y):
    ...       return x+y
    ...    def mul(y):
    ...        return x*y
    ...    return {'+': add, '*': add}
    ...
    >>> test_result = test2(value)
    >>> test_result
    {'+': <function add at 0x104e85b90>, '*': <function add at 0x104e85b90>}
    >>> sys.getrefcount(value)
    3
    >>> del test_result['+']
    >>> sys.getrefcount(value)
    3
    >>> del test_result['*']
    >>> sys.getrefcount(value)
    2
    

The two functions both reference the same closure cell, which in turn
references the value of `x`, so while those two function objects still exist
the reference count goes up by one. Deleting both functions cleared the
closure cell (the refcount for that object went down to 0), and the reference
count dropped again.

As soon as the refcount for the `'foo bar'` string goes to 0, it'll too be
deleted. In the above examples it is always 2, because both the name `value`
and the `sys.getrefcount()` function reference it whenever I try to access the
reference count.

