title: How to pass down multiple parameter through several functions
body: <p>Let's assume we have an exposed function (Level 0). We call this function with various parameter. Internally this function calls a second function (Level 1) but does not use any of the given parameters other than calling a third function (Level 2) with them as arguments. It might do some other stuff however.</p>
  
  <p>My Question is. How can we pass down the arguments without creating too much noise in the middle layer function (Level 1)? I list some possible ways beneath. Be warned however that some of them are rather ugly and only there for completeness reasons. I'm looking for some established guideline rather than individual personal opinion on the topic</p>
  
  <pre><code># Transport all of them individually down the road.
  # This is the most obvious way. However the amount of parameter increases the
  # noise in A_1 since they are only passed along
  def A_0(msg, term_print):
      A_1(msg, term_print)
  
  def A_1(msg, term_print):
      A_2(msg, term_print)
  
  def A_2(msg, term_print):
      print(msg, end=term_print)
  
  
  # Create parameter object (in this case dict) and pass it down.
  # Reduces the amount of parameters. However when only reading the source of B1
  # it is impossible to determine what par is
  def B_0(msg, term_print):
      B_1({'msg': msg, 'end': term_print})
  
  def B_1(par):
      B_2(par)
  
  def B_2(par):
      print(par['msg'], end=par['end'])
  
  
  # Use global variables. We all know the pitfalls of global variables. However
  # in python there are at least limited to their module
  def C_0(msg, term_print):
      global MSG, TERM_PRINT
  
      MSG = msg
      TERM_PRINT = term_print
      C_1()
  
  def C_1():
      C_2()
  
  def C_2():
      print(MSG, end=TERM_PRINT)
  
  
  # Use the fact that python creates function objects. We can now append those
  # objects. This makes some more 'localised' variables than shown before. However
  # this also makes the code harder to maintain. When we change D_2 we have to alter
  # D_0 as well even though it never directly calls it
  def D_0(msg, term_print):
      D_2.msg = msg
      D_2.term_print = term_print
      D_1()
  
  def D_1():
      D_2()
  
  def D_2():
      print(D_2.msg, end=D_2.term_print)
  
  
  # Create a class with the functions E_1, E_2 to enclose the variables.
  class E(dict):
      def E_1(self):
          self.E_2()
  
      def E_2(self):
          print(self['msg'], end=self['end'])
  
  def E_0(msg, term_print):
      E([('msg', msg), ('end', term_print)]).E_1()
  
  
  # Create a nested scope. This make it very hard to read the function. Furthermore
  # F_1 cannot be called directly from outside (without abusing the construct)
  def F_0(msg, term_print):
      def F_1():
          F_2()
  
      def F_2():
          print(msg, end=term_print)
  
      F_1()
  
  
  A_0('What', ' ')
  B_0('is', ' ')
  C_0('the', ' ')
  D_0('best', ' ')
  E_0('way', '')
  F_0('?', '\n')
  </code></pre>