Python: passing parameters over functions
<p>Python Experts,</p>

<p>I have been trying to implement BST using Python and here is my code for the insert function:</p>

<p><strong>Draft 1:</strong></p>

<pre><code>def insert(self, val):
    newNode = self._Node(val)

    if (self._root is None):
        self._root = newNode
    else:
        self._insert(self._root,val)

def _insert(self, node, val):

    if node is None:
        node = self._Node(val)

    elif val &gt;= node._val:

        self._insert(node._right, val)
    else:
        self._insert(node._left, val)
</code></pre>

<p>But, I'm unable to construct the tree except the root. I'm guessing I messed up somewhere with the parameters passing over the two functions because when I modify the code as below, I get it alright:</p>

<p><strong>Draft 2:</strong></p>

<pre><code>def insert(self, val):
    newNode = self._Node(val)

    if (self._root is None):
        self._root = newNode
    else:
        self._insert(self._root,val)

def _insert(self, node, val):

    if val &gt;= node._val:
        if node._right is None:
                node._right = self._Node(val)
        else:
                self._insert(node._right, val)
    else:
        if node._left is None:
                node._left = self._Node(val)
        else:
                self._insert(node._left, val)
</code></pre>

<p>I'm trying hard to understand why the draft 2 works but draft 1 doesn't. Any help here? Thanks in advance!</p>

<p>The fundamental misunderstanding you have is how variable assignment works and interacts with Python's evaluation strategy: <a href="https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing" rel="nofollow">call-by-sharing.</a></p>

<p>Essentially, in your first draft, when you do the following:</p>

<pre><code>def _insert(self, node, val):

    if node is None:
        node = self._Node(val)
    ...
</code></pre>

<p>You are simply assigning to the name (variable) <code>node</code> the value of <code>self._Node(val)</code> but then when you leave the scope, the new object is destroyed! Even though <code>node</code> used to refer to the value that was passed in by the method call, simple assignment doesn't mutate the object that is referenced by the name, rather, it <em>reassigns the name.</em></p>

<p>In your second draft, however:</p>

<pre><code>def _insert(self, node, val):

    if val &gt;= node._val:
        if node._right is None:
            node._right = self._Node(val)
        else:
            self._insert(node._right, val)
</code></pre>

<p>You <em>are mutating an object</em> i.e.: `node._right = self._Node(val)</p>

<p>Here is a simple example that is hopefully illuminating:</p>

<pre><code>&gt;&gt;&gt; def only_assign(object):
...   x = 3
...   object = x
... 
&gt;&gt;&gt; def mutate(object):
...   object.attribute = 3
... 
&gt;&gt;&gt; class A:
...   pass
... 
&gt;&gt;&gt; a = A()
&gt;&gt;&gt; a
&lt;__main__.A object at 0x7f54c3e256a0&gt;
&gt;&gt;&gt; only_assign(a)
&gt;&gt;&gt; a
&lt;__main__.A object at 0x7f54c3e256a0&gt;
&gt;&gt;&gt; mutate(a)
&gt;&gt;&gt; a.attribute
3
</code></pre>

python