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:
-
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. -
Conversion
Optionally a!
followed by a conversion character:Character Meaning a
Calls ascii()
on the selected field before formatting. This is similar torepr()
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. -
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]"