String formatting

Outside of the text interpolation provided by specific Ren'Py Text displayables (including menus, say boxes, text buttons and similar) if you need to format a string containing other variables you need to use Python techniques.

String.format()

This allows a string to control the formatting of parameters passed to the format method. The position of each field is marked in the input string with {}. In the simplest case the fields are just used in order:


    $ name = "Jim"
    $ age = 21
    $ tmp = "My name is {} and I am {} years old.".format(name, age)
    "[tmp]"

My name is Jim and I am 21 years old.

By using format specifiers the output can be controlled. For example using fixed point to nicely output weights:


    $ massKg = 56.789
    $ tmp = "I weigh {:.1f} kilos. That's {:.0f} pounds.".format(massKg, massKg*2.2)
    "[tmp]"

I weigh 56.8 kilos. That's 125 pounds.

Using a decimal number in the field specification picks a specific argument given to format. The same argument can be then be used more than once.


    $ tm = "\N{TRADE MARK SIGN}"
    $ tmp = "Symbol {0} decimal {1:d} hex {1:#x}.".format(tm, ord(tm))
    "[tmp]"

Symbol ™ decimal 8482 hex 0x2122.

The format() method can also take keyword arguments that can then be selected by name:


    $ tmp = "My name is {name}. I'm an {zodiac}.".format(name="Sheila", zodiac="Aries")
    "[tmp]"

My name is Sheila. I'm an Aries.
Note: This highlights a potential problem with substituting strings. If Sheila had been a Capricorn, then an wouldn't work, it would have to be a instead. It can be even harder with other languages where the article has to agree with the grammatical gender of the noun.

The field selector can look at the attributes of an object, such as the (fictional) set of stats for the player:


    $ tmp = "Health: {0.hp}/{0.hpMax}".format(pcStats)
    "[tmp]"

Health: 7/10

The field selector can also index a sequence like the tuple [1] here, or a list:


    python:
        book = (
            "on interactive storytelling",
            "Chris Crawford",
            "978-0-321-27890-8",
            "New Riders",
        )
    $ tmp = "'{0[0]}' by {0[1]}\nISBN: {0[2]}".format(book)
    "[tmp]"

'on interactive storytelling' by Chris Crawford
ISBN: 978-0-321-27890-8

As the { and } characters are used to mark field substitutions if you want either in your output you need to double them up: {{ and }}.

Field specification

Between the curly brackets you can include a field specification. This is one or more characters in the following order:

  1. Field selector
    Optionally either a decimal number that selects one of the arguments passed to format, or a key name which selects from the keyword arguments to format. This can be followed by zero or more .attribute_name or [element_index] to select attributes or indexes of the supplied field.
    Note: You cannot mix automatic field selection and numbered field selection.
  2. Conversion
    Optionally a ! followed by a conversion character:
    CharacterMeaning
    a Calls ascii() on the selected field before formatting. This is similar to repr() except any non-ascii characters are replaced with escape codes.
    r Calls repr() on the selected field before formatting. In many cases this will return a string that could be used in python source to define the value. For example strings have single quotes at the start and end.
    s Calls str() on the selected field before formatting.
  3. Format specification
    Optionally a : followed by a format specifier. This allows detailed control over how the field is formatted. The format specifier can also be supplied by another field using a nested field replacement such as {0:{1}}.

F-strings Ren'Py 8.x, Python 3.x

Coming soon™

"Old" string formatting

This is the version of string formatting before Python 2.7 and Python 3. It largely emulates the way the C language sprintf() works. You may still find old Ren'Py examples that use this method. There doesn't seem to be any indication that it is likely to be removed anytime soon but you should probably avoid it for new code.
See Old string formatting  for the syntax and printf string formatting  for the format specifiers.

It uses the % modulus operator to provide text interpolation. Each % in the string is followed by a format specifier that must include a type conversion character and is replaced by the value on the right hand side of the modulus operator.
Note: The format specifier is similar, but not the same as, the ones used in the previous two methods and Ren'Py's text interpolation.


    $ name = "Fred"
    $ tmp = "My name is %s." % name
    "[tmp]"

Multiple values can be substituted in order by making the right hand side a tuple:

    $ name = "Fred"
    $ age = 21
    $ tmp = "My name is %s and I am %d years old." % (name, age)
    "[tmp]"

Alternatively a dictionary (or other kind of map) can be used for the right hand side allowing parameters to be named:

    $ name = "Fred"
    $ age = 21
    $ params = {'name': name, 'age': age}
    $ tmp = "My name is %(name)s and I am %(age)d years old." % params
    "[tmp]"