title: How the lazy function in django.utils.functional invokes the actual function and why debugging tools failed to reproduce the results?
body: <p>I am trying to understand how the lazy() function works in the Django module django.utils.functional. One thing I don't understand is what decides when the actual function gets invoked. </p>
  
  <p>This is the script I used to test the lazy function:</p>
  
  <pre><code>from django.utils.functional import lazy
  
  
  def func1(x, y):
      print("Task is executing ... ")
      return x + y
  
  print("===== Sec 1")
  
  lazy_func1 = lazy(func1)
  
  print("\n===== Sec 2")
  
  x = lazy_func1(3, 99878)
  print(type(x))
  
  print("\n===== Sec 3")
  
  print(lazy_func1(3, 1000))
  
  print("=====")
  </code></pre>
  
  <p>The output of the above script is:</p>
  
  <pre><code>===== Sec 1
  
  ===== Sec 2
  &lt;class 'django.utils.functional.lazy.&lt;locals&gt;.__proxy__'&gt;
  
  ===== Sec 3
  Task is executing ... 
  1003
  =====
  </code></pre>
  
  <p>So x = lazy_func(3, 1000) does not invoke the function, which is expected. However, while print(type(x)) does not invoke the actual function, print(x) does. Why is it like this? </p>
  
  <p>Another wired thing is that when I tried use a debugging tool (pycharm debug) to follow the source code to check what is happening under the hook, some totally different outputs are generated:</p>
  
  <pre><code>Connected to pydev debugger (build 162.1967.10)
  
  ===== Sec 1
  
  ===== Sec 2
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  &lt;class 'django.utils.functional.lazy.&lt;locals&gt;.__proxy__'&gt;
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  
  ===== Sec 3
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  1003
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  Task is executing ... 
  =====
  
  Process finished with exit code 0
  </code></pre>
  
  <p>So with a debugging tool, both print(type(x)) and print(x) invokes the functions a couple of times. Why does the debugging tool seem to mess up the lazy function? What is the implication of this? Does this mean that we cannot use a debugging tool to debug lazy functions?</p>