Python 2.6 introduced the string.format method with a slightly different syntax from the existing% operator. Background Older '%' string formatter. Prior to python 2.6, a simpler string formatter '%' was available. It was easy to use but the number of arguments that it could accept were limited.
Python 2.6 introduced the
str.format()
method with a slightly different syntax from the existing %
operator. Which is better and for what situations?- The following uses each method and has the same outcome, so what is the difference?
- Furthermore when does string formatting occur in Python? For example, if my logging level is set to HIGH will I still take a hit for performing the following
%
operation? And if so, is there a way to avoid this?
NorthIsUpNorthIsUp
16 Answers
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:yet, if
name
happens to be (1, 2, 3)
, it will throw a TypeError
. To guarantee that it always prints, you'd need to dowhich is just ugly.
.format
doesn't have those issues. Also in the second example you gave, the .format
example is much cleaner looking.Why would you not use it?
- not knowing about it (me before reading this)
- having to be compatible 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 in your
log.debug
example, the expression 'some debug info: %s'%some_info
will first evaluate to, e.g. 'some debug info: roflcopters are active'
, then that string will be passed to log.debug()
. ClaudiuClaudiu
Something that the modulo operator ( % ) can't do, afaik:
result
Very useful.
Another point:
format()
, being a function, can be used as an argument in other functions: Results in:
eyquemeyquem
Assuming you're using Python's
logging
module, you can pass the string formatting arguments as arguments to the .debug()
method rather than doing the formatting yourself:which avoids doing the formatting unless the logger actually logs something.
WoobleWooble
As of Python 3.6 (2016) you can use f-strings to substitute variables:
Note the
f'
prefix. If you try this in Python 3.5 or earlier, you'll get a SyntaxError
.See https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings
Colonel PanicColonel Panic
PEP 3101 proposes the replacement of the
%
operator with the new, advanced string formatting in Python 3, where it would be the default.BrainStormBrainStorm
But please be careful, just now I've discovered one issue when trying to replace all
%
with .format
in existing code: '{}'.format(unicode_string)
will try to encode unicode_string and will probably fail.Just look at this Python interactive session log:
s
is just a string (called 'byte array' in Python3) and u
is a Unicode string (called 'string' in Python3):When you give a Unicode object as a parameter to
%
operator it will produce a Unicode string even if the original string wasn't Unicode:but the
.format
function will raise 'UnicodeEncodeError':and it will work with a Unicode argument fine only if the original string was Unicode.
or if argument string can be converted to a string (so called 'byte array')
rslnxrslnx
Yet another advantage of
.format
(which I don't see in the answers): it can take object properties.Or, as a keyword argument:
This is not possible with
%
as far as I can tell.matiasgmatiasg
As I discovered today, the old way of formatting strings via
%
doesn't support Decimal
, Python's module for decimal fixed point and floating point arithmetic, out of the box.Example (using Python 3.3.5):
Output:
0.00000000000000000000000312375239000000009907464850 0.00000000000000000000000312375239000000000000000000
There surely might be work-arounds but you still might consider using the
format()
method right away. balubalu
%
gives better performance than format
from my test.Test code:
Python 2.7.2:
Result:
Python 3.5.2
Result
It looks in Python2, the difference is small whereas in Python3,
%
is much faster than format
.Thanks @Chris Cogdon for the sample code.
lcltjlcltj
As a side note, you don't have to take a performance hit to use new style formatting with logging. You can pass any object to
logging.debug
, logging.info
, etc. that implements the __str__
magic method. When the logging module has decided that it must emit your message object (whatever it is), it calls str(message_object)
before doing so. So you could do something like this:This is all described in the Python 3 documentation (https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles). However, it will work with Python 2.6 as well (https://docs.python.org/2.6/library/logging.html#using-arbitrary-objects-as-messages).
One of the advantages of using this technique, other than the fact that it's formatting-style agnostic, is that it allows for lazy values e.g. the function
expensive_func
above. This provides a more elegant alternative to the advice being given in the Python docs here: https://docs.python.org/2.6/library/logging.html#optimization.David SandersDavid Sanders
If your python >= 3.6, F-string formatted literal is your new friend.
It's more simple, clean, and better performance.
zhengcaozhengcao
One situation where
%
may help is when you are formatting regex expressions. For example, raises
IndexError
. In this situation, you can use:This avoids writing the regex as
'{type_names} [a-z]{{2}}'
. This can be useful when you have two regexes, where one is used alone without format, but the concatenation of both is formatted.Jorge LeitãoJorge Leitão
I would add that since version 3.6, we can use fstrings like the following
Which give
My name is john smith
Everything is converted to strings
Result:
mylist = ['foo', 'bar']
you can pass function, like in others formats method
Giving for example
Hello, here is the date : 16/04/2018
Sylvan LE DEUNFFSylvan LE DEUNFF
RoushanRoushan
But one thing is that also if you have nested curly-braces, won't work for format but
%
will work.Example:
U9-ForwardU9-Forward
Felix MartinezFelix Martinez
protected by Moinuddin QuadriJan 31 '17 at 21:55
Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
Would you like to answer one of these unanswered questions instead?