4

In Python, I'd like to create a string block with embedded expressions.
In Ruby, the code looks like this:

def get_val
  100
end

def testcode
s=<<EOS

This is a sample string that references a variable whose value is: #{get_val}
Incrementing the value: #{get_val + 1}

EOS
  puts s
end

testcode
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
hopia
  • 4,880
  • 7
  • 32
  • 54
  • do you need just to format a value or do you need to include expressions that require code execution? – jfs Mar 18 '12 at 23:42

6 Answers6

5

Update: since Python 3.6, there are formatted string literals (f-strings) which enable a literal string interpolation: f"..{get_val()+1}..."


If you need more than just a simple string formatting provided by str.format() and % then templet module could be used to insert Python expressions:

from templet import stringfunction

def get_val():
    return 100

@stringfunction
def testcode(get_val):
    """
    This is a sample string
    that references a function whose value is: ${ get_val() }
    Incrementing the value: ${ get_val() + 1 }
    """

print(testcode(get_val))

Output

This is a sample string
that references a function whose value is: 100
Incrementing the value: 101

Python Templating with @stringfunction.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • It's a little inconvenient to import an external module but this is what I'm looking for. – hopia Mar 19 '12 at 03:31
4

Using the format method:

>>> '{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>> '{}, {}, {}'.format('a', 'b', 'c')  # 2.7+ only
'a, b, c'
>>> '{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>> '{2}, {1}, {0}'.format(*'abc')      # unpacking argument sequence
'c, b, a'
>>> '{0}{1}{0}'.format('abra', 'cad')   # arguments' indices can be repeated
'abracadabra'

Format by name:

>>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
'Coordinates: 37.24N, -115.81W'
>>> coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
>>> 'Coordinates: {latitude}, {longitude}'.format(**coord)
'Coordinates: 37.24N, -115.81W'
Laurens
  • 2,420
  • 22
  • 39
  • 1
    Python 3 has `.format_map()` method: `Coordinates: {latitude}, {longitude}'.format_map(coord)` – jfs Mar 19 '12 at 01:53
2

The equivalent program in modern Python uses f-strings. (The f-string syntax is a relatively recent addition.)

def get_val():
    return 100

def testcode():
    s = f"""

This is a sample string that references a variable whose value is: {get_val()}
Incrementing the value: {get_val() + 1}

"""
    print(s)

testcode()
gilch
  • 10,813
  • 1
  • 23
  • 28
2

Use format method:

>>> get_val = 999
>>> 'This is the string containing the value of get_val which is {get_val}'.format(**locals())
'This is the string containing the value of get_val which is 999'

**locals passes a dictionary of local variables as keyword arguments. {get_val} in the string denotes the place where the variable's get_val value should be printed. There are other formatting options. See the docs of format method.

This would make the things almost as in Ruby. (with the only difference that in Ruby you have to put # befor the curly brackets #{get_val}).

If you need to output incremented get_val, I see no other way to print it apart from the following:

>>> 'This is the string containing the value of get_val+1 which is {get_val_incremented}'.format(get_val_incremented = get_val + 1,**locals())
'This is the string containing the value of get_val+1 which is 1000'
ovgolovin
  • 13,063
  • 6
  • 47
  • 78
  • Why the `**locals` in the second example? Also, you could just use the positional variant with `{0}` in the case of only one replacement. – Niklas B. Mar 18 '12 at 23:16
  • @NiklasB. `**locals` in the second example will only be needed if there would be some other variables displayed in the string (it would be easier in the future to add them to the string). If the srting is fixed and no changes are anticipated, `**locals()` in the second example is redundant. – ovgolovin Mar 18 '12 at 23:18
2

As a C and Ruby programmer, I like the classic printf-like approach:

>>> x = 3
>>> 'Sample: %d' % (x + 1)
'Sample: 4'

Or in the case of multiple arguments:

>>> 'Object %(obj)s lives at 0x%(addr)08x' % dict(obj=repr(x), addr=id(x))
'Object 3 lives at 0x0122c788'

I can already feel how people are gonna beat me up for this. However, I find this especially nice because it works the same way in Ruby.

Niklas B.
  • 92,950
  • 18
  • 194
  • 224
1

Polyglot.org answers a lot of questions like these for PHP, Perl, Python and Ruby.

steenslag
  • 79,051
  • 16
  • 138
  • 171