title: Python string interpolation implementation
body: <p>[EDIT 00]: I've edited several times the post and now even the title, please read below.</p>
  
  <p>I just learned about the format string method, and its use with dictionaries, like the ones provided by <code>vars()</code>, <code>locals()</code> and <code>globals()</code>, example:</p>
  
  <pre><code>name = 'Ismael'
  print 'My name is {name}.'.format(**vars())
  </code></pre>
  
  <p>But I want to do:</p>
  
  <pre><code>name = 'Ismael'
  print 'My name is {name}.' # Similar to ruby
  </code></pre>
  
  <p>So I came up with this:</p>
  
  <pre><code>def mprint(string='', dictionary=globals()):
      print string.format(**dictionary)
  </code></pre>
  
  <p>You can interact with the code here:
  <a href="http://labs.codecademy.com/BA0B/3#:workspace" rel="nofollow noreferrer">http://labs.codecademy.com/BA0B/3#:workspace</a></p>
  
  <p>Finally, what I would love to do is to have the function in another file, named <code>my_print.py</code>, so I could do:</p>
  
  <pre><code>from my_print import mprint
  
  name= 'Ismael'
  mprint('Hello! My name is {name}.')
  </code></pre>
  
  <p>But as it is right now, there is a problem with the scopes, how could I get the the main module namespace as a dictionary from inside the imported mprint function. (not the one from <code>my_print.py</code>)</p>
  
  <p>I hope I made myself uderstood, if not, try importing the function from another module. (the traceback is in the link)</p>
  
  <p>It's accessing the <code>globals()</code> dict from <code>my_print.py</code>, but of course the variable name is not defined in that scope, any ideas of how to accomplish this?</p>
  
  <p>The function works if it's defined in the same module, but notice how I must use <code>globals()</code> because if not I would only get a dictionary with the values within <code>mprint()</code> scope.</p>
  
  <p>I have tried using nonlocal and dot notation to access the main module variables, but I still can't figure it out.</p>
  
  <hr>
  
  <p>[EDIT 01]: I think I've figured out a solution:</p>
  
  <p>In my_print.py:</p>
  
  <pre><code>def mprint(string='',dictionary=None):
      if dictionary is None:
          import sys
          caller = sys._getframe(1)
          dictionary = caller.f_locals
      print string.format(**dictionary)
  </code></pre>
  
  <p>In test.py:</p>
  
  <pre><code>from my_print import mprint
  
  name = 'Ismael'
  country = 'Mexico'
  languages = ['English', 'Spanish']
  
  mprint("Hello! My name is {name}, I'm from {country}\n"
         "and I can speak {languages[1]} and {languages[0]}.")
  </code></pre>
  
  <p>It prints:</p>
  
  <pre><code>Hello! My name is Ismael, I'm from Mexico
  and I can speak Spanish and English.
  </code></pre>
  
  <p>What do you think guys? That was a difficult one for me!</p>
  
  <p>I like it, much more readable for me.</p>
  
  <hr>
  
  <p>[EDIT 02]: I've made a module with an <code>interpolate</code> function, an <code>Interpolate</code> class and an attempt for a <code>interpolate</code> class method analogous to the function.</p>
  
  <p>It has a small test suite and its documented!</p>
  
  <p>I'm stuck with the method implementation, I don't get it.</p>
  
  <p>Here's the code: <a href="http://pastebin.com/N2WubRSB" rel="nofollow noreferrer">http://pastebin.com/N2WubRSB</a></p>
  
  <p>What do you think guys?</p>
  
  <hr>
  
  <p>[EDIT 03]: Ok I have settled with just the <code>interpolate()</code> function for now.</p>
  
  <p>In <code>string_interpolation.py</code>:</p>
  
  <pre><code>import sys
  
  
  def get_scope(scope):
      scope = scope.lower()
      caller = sys._getframe(2)
      options = ['l', 'local', 'g', 'global']
  
      if scope not in options[:2]:
          if scope in options[2:]:
              return caller.f_globals
          else:
              raise ValueError('invalid mode: {0}'.format(scope))
      return caller.f_locals
  
  
  def interpolate(format_string=str(),sequence=None,scope='local',returns=False):
      if type(sequence) is str:
          scope = sequence
          sequence = get_scope(scope)
      else:
          if not sequence:
              sequence = get_scope(scope)
  
      format = 'format_string.format(**sequence)'
      if returns is False:
          print eval(format)
  
      elif returns is True:
          return eval(format)
  </code></pre>
  
  <p>Thanks again guys! Any opinions?</p>
  
  <hr>
  
  <p>[EDIT 04]:</p>
  
  <p>This is my last version, it has a test, docstrings and describes some limitations I've found:
  <a href="http://pastebin.com/ssqbbs57" rel="nofollow noreferrer">http://pastebin.com/ssqbbs57</a></p>
  
  <p>You can quickly test the code here:
  <a href="http://labs.codecademy.com/BBMF#:workspace" rel="nofollow noreferrer">http://labs.codecademy.com/BBMF#:workspace</a></p>
  
  <p>And clone grom git repo here:
  <a href="https://github.com/Ismael-VC/python_string_interpolation.git" rel="nofollow noreferrer">https://github.com/Ismael-VC/python_string_interpolation.git</a></p>