Welcome, guest | Sign In | My Account | Store | Cart

Interpolate variables and expressions in strings the ruby way. This is similar in functionality to recipe 496885, though implemented differently and with a different interpolation syntax.

Python, 17 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import sys, re
def interp(string):
  locals  = sys._getframe(1).f_locals
  globals = sys._getframe(1).f_globals
  for item in re.findall(r'#\{([^}]*)\}', string):
    string = string.replace('#{%s}' % item,
                            str(eval(item, globals, locals)))
  return string

test1 = 'example'
def tryit():
  test2 = 1
  # variable interpolation
  print interp('This is an #{test1} (and another #{test1}) and an int (#{test2})')
  # expression interpolation
  print interp('This is an #{test1 + " (and another " + test1 + ")"} and an int (#{test2})')
tryit()

Ruby uses an inline string interpolation syntax using #{} (which combines perl's ${} and $() into one). It interpolates expressions as well as variables. This recipe emulates that functionality in python. Other recipies offer similar functionality (335308, 496885), though either without expression interpolation, or with an interpolation syntax which I find to be esoteric and hard to use.

Caveat: As with recipe 496885, this recipe is insecure in contexts where arbitrary input is possible, as it uses eval for evaluation of expressions; so don't use it in untrusted contexts.

2 comments

Ramon Felciano 16 years, 4 months ago  # | flag

What about instance variables? Is there a straighforward way to extend this recipe to allow for instance variables as well as locals and globals? This would be useful in order to allow the use of these templates in a __str__ or similar function that might access instance vars.

I don't understand... Hmmm...not sure I get what you're asking...this works fine for me...

...
class Foo:
  def __init__(self):
    self.bar = "happy"
  def test(self):
    print interp("This is a test of ivars: are we #{self.bar}? Yes!")

def tryit():
  f = Foo()
  f.test()
  print interp("This is a test of ivars: are we #{f.bar}? Yes!")
tryit()

# prints
# This is a test of ivars: are we happy? Yes!
# This is a test of ivars: are we happy? Yes!

What am I missing?

Created by Jordan Callicoat on Sat, 24 Feb 2007 (PSF)
Python recipes (4591)
Jordan Callicoat's recipes (4)

Required Modules

Other Information and Tasks