A similar feature was proposed in PEP 215 . PEP 215 proposed to support a subset of Python expressions, and did not support the type-specific string formatting (the __format__() method) which was introduced with PEP 3101 .

F-strings provide a way to embed expressions inside string literals, using a minimal syntax. It should be noted that an f-string is really an expression evaluated at run time, not a constant value. In Python source code, an f-string is a literal string, prefixed with 'f', which contains expressions inside braces. The expressions are replaced with their values. Some examples are:

This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms.

Python supports multiple ways to format text strings. These include %-formatting , str.format() , and string.Template . Each of these methods have their advantages, but in addition have disadvantages that make them cumbersome to use in practice. This PEP proposed to add a new string formatting mechanism: Literal String Interpolation. In this PEP, such strings will be referred to as "f-strings", taken from the leading character used to denote such strings, and standing for "formatted strings".

Guido stated that any solution to better string interpolation would not use locals() or globals() in its implementation. (This does not forbid users from passing locals() or globals() in, it just doesn't require it, nor does it allow using these functions under the hood.)

In addition, using locals() or globals() introduces an information leak. A called routine that has access to the callers locals() or globals() has access to far more information than needed to do the string interpolation.

This returns an error because the compiler has not added a reference to x inside the closure. You need to manually add a reference to x in order for this to work:

In the discussions on python-dev , a number of solutions where presented that used locals() and globals() or their equivalents. All of these have various problems. Among these are referencing variables that are not otherwise used in a closure. Consider:

And neither %-formatting nor string.Template can control formatting such as:

In this sense, string.Template and %-formatting have similar shortcomings to str.format() , but also support fewer formatting options. In particular, they do not support the __format__ protocol, so that there is no way to control how a specific object is converted to a string, nor can it be extended to additional types that want to control how they are converted to strings (such as Decimal and datetime ). This example is not possible with string.Template :

F-strings provide a concise, readable way to include the value of Python expressions inside strings.

Even in its simplest form there is a bit of boilerplate, and the value that's inserted into the placeholder is sometimes far removed from where the placeholder is situated:

However, str.format() is not without its issues. Chief among them is its verbosity. For example, the text value is repeated here:

str.format() was added to address some of these problems with %-formatting. In particular, it uses normal function call syntax (and therefor supports multiple parameters) and it is extensible through the __format__() method on the object being converted to a string. See PEP 3101 for a detailed rationale. This PEP reuses much of the str.format() syntax and machinery, in order to provide continuity with an existing Python string formatting mechanism.

To be defensive, the following code should be used:

But if msg were ever to be a tuple, the same code would fail:

%-formatting is limited as to the types it supports. Only ints, strs, and doubles can be formatted. All other types are either not supported, or converted to one of these types before formatting. In addition, there's a well-known trap where a single value is passed:

This PEP is driven by the desire to have a simpler way to format strings in Python. The existing ways of formatting are either error prone, inflexible, or cumbersome.

In source code, f-strings are string literals that are prefixed by the letter 'f' or 'F'. Everywhere this PEP uses 'f', 'F' may also be used. 'f' may be combined with 'r' or 'R', in either order, to produce raw f-string literals. 'f' may not be combined with 'b': this PEP does not propose to add binary f-strings. 'f' may not be combined with 'u'.

When tokenizing source files, f-strings use the same rules as normal strings, raw strings, binary strings, and triple quoted strings. That is, the string must end with the same character that it started with: if it starts with a single quote it must end with a single quote, etc. This implies that any code that currently scans Python code looking for strings should be trivially modifiable to recognize f-strings (parsing within an f-string is another matter, of course).

Once tokenized, f-strings are parsed in to literal strings and expressions. Expressions appear within curly braces '{' and '}' . While scanning the string for expressions, any doubled braces '{{' or '}}' inside literal portions of an f-string are replaced by the corresponding single brace. Doubled literal opening braces do not signify the start of an expression. A single closing curly brace '}' in the literal portion of a string is an error: literal closing curly braces must be doubled '}}' in order to represent a single closing brace.

The parts of the f-string outside of braces are literal strings. These literal portions are then decoded. For non-raw f-strings, this includes converting backslash escapes such as '

' , '\"' , "\'" , '\xhh' , '\uxxxx' , '\Uxxxxxxxx' , and named unicode characters '\N{name}' into their associated Unicode characters .

Backslashes may not appear anywhere within expressions. Comments, using the '#' character, are not allowed inside an expression.

Following each expression, an optional type conversion may be specified. The allowed conversions are '!s' , '!r' , or '!a' . These are treated the same as in str.format() : '!s' calls str() on the expression, '!r' calls repr() on the expression, and '!a' calls ascii() on the expression. These conversions are applied before the call to format() . The only reason to use '!s' is if you want to specify a format specifier that applies to str , not to the type of the expression.

F-strings use the same format specifier mini-language as str.format . Similar to str.format() , optional format specifiers maybe be included inside the f-string, separated from the expression (or the type conversion, if specified) by a colon. If a format specifier is not provided, an empty string is used.

So, an f-string looks like:

f ' <text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> ... '

The expression is then formatted using the __format__ protocol, using the format specifier as an argument. The resulting value is used when building the value of the f-string.

Note that __format__() is not called directly on each value. The actual code uses the equivalent of type(value).__format__(value, format_spec) , or format(value, format_spec) . See the documentation of the builtin format() function for more details.

Expressions cannot contain ':' or '!' outside of strings or parentheses, brackets, or braces. The exception is that the '!=' operator is allowed as a special case.

Escape sequences Backslashes may not appear inside the expression portions of f-strings, so you cannot use them, for example, to escape quotes inside f-strings: >>> f'{\'quoted string\'}' File "<stdin>", line 1 SyntaxError: f-string expression part cannot include a backslash You can use a different type of quote inside the expression: >>> f'{"quoted string"}' 'quoted string' Backslash escapes may appear inside the string portions of an f-string. Note that the correct way to have a literal brace appear in the resulting string value is to double the brace: >>> f'{{ {4*10} }}' '{ 40 }' >>> f'{{{4*10}}}' '{40}' Like all raw strings in Python, no escape processing is done for raw f-strings: >>> fr'x={4*10}

' 'x=40\

' Due to Python's string tokenizing rules, the f-string f'abc {a['x']} def' is invalid. The tokenizer parses this as 3 tokens: f'abc {a[' , x , and ']} def' . Just like regular strings, this cannot be fixed by using raw strings. There are a number of correct ways to write this f-string: with a different quote character: f"abc {a['x']} def" Or with triple quotes: f'''abc {a['x']} def'''

Code equivalence The exact code used to implement f-strings is not specified. However, it is guaranteed that any embedded value that is converted to a string will use that value's __format__ method. This is the same mechanism that str.format() uses to convert values to strings. For example, this code: f'abc{expr1:spec1}{expr2!r:spec2}def{expr3}ghi' Might be evaluated as: 'abc' + format(expr1, spec1) + format(repr(expr2), spec2) + 'def' + format(expr3) + 'ghi'

Expression evaluation The expressions that are extracted from the string are evaluated in the context where the f-string appeared. This means the expression has full access to local and global variables. Any valid Python expression can be used, including function and method calls. Because the f-strings are evaluated where the string appears in the source code, there is no additional expressiveness available with f-strings. There are also no additional security concerns: you could have also just written the same expression, not inside of an f-string: >>> def foo(): ... return 20 ... >>> f'result={foo()}' 'result=20' Is equivalent to: >>> 'result=' + str(foo()) 'result=20' Expressions are parsed with the equivalent of ast.parse('(' + expression + ')', '<fstring>', 'eval') . Note that since the expression is enclosed by implicit parentheses before evaluation, expressions can contain newlines. For example: >>> x = 0 >>> f'''{x ... +1}''' '1' >>> d = {0: 'zero'} >>> f'''{d[0 ... ]}''' 'zero'

Format specifiers Format specifiers may also contain evaluated expressions. This allows code such as: >>> width = 10 >>> precision = 4 >>> value = decimal.Decimal('12.34567') >>> f'result: {value:{width}.{precision}}' 'result: 12.35' Once expressions in a format specifier are evaluated (if necessary), format specifiers are not interpreted by the f-string evaluator. Just as in str.format() , they are merely passed in to the __format__() method of the object being formatted.

Concatenating strings Adjacent f-strings and regular strings are concatenated. Regular strings are concatenated at compile time, and f-strings are concatenated at run time. For example, the expression: >>> x = 10 >>> y = 'hi' >>> 'a' 'b' f'{x}' '{c}' f'str<{y:^4}>' 'd' 'e' yields the value: 'ab10{c}str< hi >de' While the exact method of this run time concatenation is unspecified, the above code might evaluate to: 'ab' + format(x) + '{c}' + 'str<' + format(y, '^4') + '>de' Each f-string is entirely evaluated before being concatenated to adjacent f-strings. That means that this: >>> f'{x' f'}' Is a syntax error, because the first f-string does not contain a closing brace.

Error handling Either compile time or run time errors can occur when processing f-strings. Compile time errors are limited to those errors that can be detected when scanning an f-string. These errors all raise SyntaxError . Unmatched braces: >>> f'x={x' File "<stdin>", line 1 SyntaxError: f-string: expecting '}' Invalid expressions: >>> f'x={!x}' File "<stdin>", line 1 SyntaxError: f-string: empty expression not allowed Run time errors occur when evaluating the expressions inside an f-string. Note that an f-string can be evaluated multiple times, and work sometimes and raise an error at other times: >>> d = {0:10, 1:20} >>> for i in range(3): ... print(f'{i}:{d[i]}') ... 0:10 1:20 Traceback (most recent call last): File "<stdin>", line 2, in <module> KeyError: 2 or: >>> for x in (32, 100, 'fifty'): ... print(f'x = {x:+3}') ... 'x = +32' 'x = +100' Traceback (most recent call last): File "<stdin>", line 2, in <module> ValueError: Sign not allowed in string format specifier

Leading and trailing whitespace in expressions is ignored For ease of readability, leading and trailing whitespace in expressions is ignored. This is a by-product of enclosing the expression in parentheses before evaluation.