String Formatting in Python 3

String formatting in Python

The previous answers have used % formatting, which is being phased out in Python 3.0+. Assuming you're using Python 2.6+, a more future-proof formatting system is described here:

http://docs.python.org/library/string.html#formatstrings

Although there are more advanced features as well, the simplest form ends up looking very close to what you wrote:

>>> "[{0}, {1}, {2}]".format(1, 2, 3)
[1, 2, 3]

String formatting in Python 3

Here are the docs about the "new" format syntax. An example would be:

"({:d} goals, ${:d})".format(self.goals, self.penalties)

If both goals and penalties are integers (i.e. their default format is ok), it could be shortened to:

"({} goals, ${})".format(self.goals, self.penalties)

And since the parameters are fields of self, there's also a way of doing it using a single argument twice (as @Burhan Khalid noted in the comments):

"({0.goals} goals, ${0.penalties})".format(self)

Explaining:

  • {} means just the next positional argument, with default format;
  • {0} means the argument with index 0, with default format;
  • {:d} is the next positional argument, with decimal integer format;
  • {0:d} is the argument with index 0, with decimal integer format.

There are many others things you can do when selecting an argument (using named arguments instead of positional ones, accessing fields, etc) and many format options as well (padding the number, using thousands separators, showing sign or not, etc). Some other examples:

"({goals} goals, ${penalties})".format(goals=2, penalties=4)
"({goals} goals, ${penalties})".format(**self.__dict__)

"first goal: {0.goal_list[0]}".format(self)
"second goal: {.goal_list[1]}".format(self)

"conversion rate: {:.2f}".format(self.goals / self.shots) # '0.20'
"conversion rate: {:.2%}".format(self.goals / self.shots) # '20.45%'
"conversion rate: {:.0%}".format(self.goals / self.shots) # '20%'

"self: {!s}".format(self) # 'Player: Bob'
"self: {!r}".format(self) # '<__main__.Player instance at 0x00BF7260>'

"games: {:>3}".format(player1.games) # 'games: 123'
"games: {:>3}".format(player2.games) # 'games: 4'
"games: {:0>3}".format(player2.games) # 'games: 004'

Note: As others pointed out, the new format does not supersede the former, both are available both in Python 3 and the newer versions of Python 2 as well. Some may say it's a matter of preference, but IMHO the newer is much more expressive than the older, and should be used whenever writing new code (unless it's targeting older environments, of course).

String formatting in python 3 without print function

this "%s" format has been borrowed from C printf format, but is much more interesting because it doesn't belong to print statement. Note that it involves just one argument passed to print (or to any function BTW):

print("%s%s" % (a,a))

and not (like C) a variable number of arguments passed to some functions that accept & understand them:

printf("%s%s,a,a);

It's a standalone way of creating a string from a string template & its arguments (which for instance solves the tedious issue of: "I want a logger with formatting capabilities" which can be achieved with great effort in C or C++, using variable arguments + vsprintf or C++11 variadic recursive templates).

Note that this format style is now considered legacy. Now you'd better use format, where the placeholders are wrapped in {}.

One of the direct advantages here is that since the argument is repeated you just have to do:

int("{0}{0}".format(a))

(it references twice the sole argument in position 0)

Both legacy and format syntaxes are detailed with examples on https://pyformat.info/

or since python 3.6 you can use fstrings:

>>> a = 12
>>> int(f"{a}{a}")
1212

How to set the spaces in a string format in Python 3

Using str.format

>>> length = 20
>>> string = "some string"
>>> print('{1:>{0}}'.format(length, string))
some string

String formatting: % vs. .format vs. f-string literal

To answer your first question... .format just seems more sophisticated in many ways. An annoying thing about % is also how it can either take a variable or a tuple. You'd think the following would always work:

"Hello %s" % name

yet, if name happens to be (1, 2, 3), it will throw a TypeError. To guarantee that it always prints, you'd need to do

"Hello %s" % (name,)   # supply the single argument as a single-item tuple

which is just ugly. .format doesn't have those issues. Also in the second example you gave, the .format example is much cleaner looking.

Only use it for backwards compatibility with Python 2.5.


To answer your second question, string formatting happens at the same time as any other operation - when the string formatting expression is evaluated. And Python, not being a lazy language, evaluates expressions before calling functions, so the expression log.debug("some debug info: %s" % some_info) will first evaluate the string to, e.g. "some debug info: roflcopters are active", then that string will be passed to log.debug().

Python 3 Nesting String format

Your "nested" format string needs to be formatted twice. Any curly braces you want to keep for the second time needs to be escaped in the first, thus { becomes {{ and } becomes }}. Also, since you can't use the f prefix twice, You can explicitly call format for the second formatting.

What you're looking for is this:

for i in range(1, size + 1):
line = f"{i}" * i
print(f"{{0:>{size}}}".format(line))

So first string formatting turns f"{{0:>{size}}}" into {0:>3}, thus when reaching the explicit calling of format you basically get print("{0:>3}".format(line)).

python 3 string formatting (alignment)

You could try:

"{:>10d}".format(n) where n is an int to pad-left numbers and

"{:>10s}".format(s), where s is a string to pad-left strings

Edit: choosing 10 is arbitrary.. I would suggest first determining the max length.

But I'm not sure this is what you want..
Anyways, this link contains some info on string formatting:

String formatting

You can try this:

def align(word, number):
return "{:<10s}{:>10d}".format(word, number)

This will pad-right your string with 10 spaces and pad-left your number with 10 spaces, giving the desired result
Example:

align('Hello', 3454)
align('nice', 222)
align('bye', 45433)
align('well', 3424)


Related Topics



Leave a reply



Submit