Flushed out more text. Other than removing !s, !r, and !a, I think I am mostly done.
This commit is contained in:
parent
1d6b74f376
commit
29a1f236da
157
pep-0498.txt
157
pep-0498.txt
|
@ -25,12 +25,12 @@ strings.
|
|||
This PEP does not propose to remove or deprecate any of the existing
|
||||
string formatting mechanisms.
|
||||
|
||||
f-strings provide a way to combine string literals with Python
|
||||
expressions, using a minimal syntax. It should be noted that an
|
||||
f-string is really an expression evaluated at run time, not a constant
|
||||
value. An f-string is a string, prefixed with 'f', that contains
|
||||
expressions inside braces. The expressions are replaced with their
|
||||
values. Some examples are::
|
||||
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', that
|
||||
contains expressions inside braces. The expressions are replaced with
|
||||
their values. Some examples are::
|
||||
|
||||
>>> import datetime
|
||||
>>> name = 'Fred'
|
||||
|
@ -110,11 +110,11 @@ inside strings.
|
|||
|
||||
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 __format__, 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::
|
||||
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::
|
||||
|
||||
>>> value = 1234
|
||||
>>> f'input={value:#0.6x}'
|
||||
|
@ -164,6 +164,11 @@ 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.
|
||||
|
||||
If locals() and globals() were used, and if a future extension to this
|
||||
PEP would add an internationalization layer before str.interpolate()
|
||||
is called, a malicious translator could get access to additional
|
||||
variables in the callers context.
|
||||
|
||||
Guido stated [#]_ that any solution to better string interpolation
|
||||
would not use locals() or globals().
|
||||
|
||||
|
@ -214,20 +219,44 @@ special cased.
|
|||
str.interpolate()
|
||||
-----------------
|
||||
|
||||
str.interpolate(mapping) will be a new method. It takes one argument:
|
||||
a mapping of field names to values. This method is the same as
|
||||
str.format_map() [#]_, with one difference: it does not interpret the
|
||||
field_name [#]_ in any way. The field_name is only used to look up the
|
||||
replacement value in the supplied mapping object. Like str.format()
|
||||
and str.format_map(), str.interpolate() does interpret and apply the
|
||||
optional conversion and format_spec. Thus, a field_name may not
|
||||
contain the characters ':' or '}', nor the strings '!s', '!r', or
|
||||
'!a'.
|
||||
str.interpolate(mapping) will be a new method on the str type. It
|
||||
takes one argument: a mapping of field names to values. This method is
|
||||
the same as str.format_map() [#]_, with one difference: it does not
|
||||
interpret the field_name [#]_ in any way. The field_name is only used
|
||||
to look up the replacement value in the supplied mapping object. Like
|
||||
str.format() and str.format_map(), str.interpolate() does interpret
|
||||
and apply the optional conversion and format_spec. Thus, a field_name
|
||||
may not contain the characters ':' or '}', nor the strings '!s', '!r',
|
||||
or '!a'.
|
||||
|
||||
Examples::
|
||||
|
||||
>>> name = 'Guido'
|
||||
>>> 'name={name}'.interpolate({'name': name})
|
||||
'name=Guido'
|
||||
|
||||
>>> '{date} was on a {date:%A}. It was {weather}.'.interpolate({'weather': 'sunny', 'date': datetime.date(1991, 10, 12)})
|
||||
'1991-10-12 was on a Saturday. It was sunny.'
|
||||
|
||||
Like str.format_map(), only the field_name portion inside braces is
|
||||
used to look up values in the mapping. The format_spec is not used as
|
||||
part of this lookup. Thus::
|
||||
|
||||
>>> 'name={name:10}'.interpolate({'name': name})
|
||||
'name=Guido '
|
||||
|
||||
But::
|
||||
|
||||
>>> 'name={name:10}'.interpolate({'name:10': name})
|
||||
'name=Guido '
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
KeyError: 'name'
|
||||
|
||||
Code equivalence
|
||||
----------------
|
||||
|
||||
An f-string is evaluated at run time as a call to str.interpolate().
|
||||
An f-string is evaluated at run time using a call to str.interpolate().
|
||||
|
||||
For example, this code::
|
||||
|
||||
|
@ -401,13 +430,77 @@ This would be evaluated as::
|
|||
Discussion
|
||||
==========
|
||||
|
||||
Most of the discussions on python-ideas [#]_ focused on a few issues.
|
||||
python-ideas discussion
|
||||
-----------------------
|
||||
|
||||
Most of the discussions on python-ideas [#]_ focused on three issues:
|
||||
|
||||
- How to denote f-strings,
|
||||
- How to specify the location of expressions in f-strings, and
|
||||
- Whether to allow full Python expressions.
|
||||
- How to designate f-strings, and how to specify the location of
|
||||
expressions in them.
|
||||
|
||||
XXX: more on the above issues.
|
||||
How to denote f-strings
|
||||
***********************
|
||||
|
||||
Because the compiler must be involved in evaluating the expressions
|
||||
contained in the interpolated strings, there must be some way to
|
||||
denote to the compiler which strings should be evaluated. This PEP
|
||||
chose a leading 'f' character preceeding the string literal. This is
|
||||
similar to how 'b' and 'r' prefixes change the meaning of the string
|
||||
itself, at compile time. Other prefixes were suggested, such as 'i'. No
|
||||
option seemed better than the other, so 'f' was chosen.
|
||||
|
||||
Another option was to support special functions, known to the
|
||||
compiler, such as Format(). This seems like too much magic for Python:
|
||||
not only is there a chance for collision with existing identifiers,
|
||||
the PEP author feels that it's better to signify the magic with a
|
||||
string prefix character.
|
||||
|
||||
How to specify the location of expressions in f-strings
|
||||
*******************************************************
|
||||
|
||||
This PEP supports the same syntax as str.format() for distinguishing
|
||||
replacement text inside strings: expressions are contained inside
|
||||
braces. There were other options suggested, such as string.Template's
|
||||
$identifier or ${expression}.
|
||||
|
||||
While $identifier is no doubt more familiar to shell scripters and
|
||||
users of some other languages, in Python str.format() is heavily
|
||||
used. A quick search of Python's standard library shows only a handful
|
||||
of uses of string.Template, but over 1000 uses of str.format().
|
||||
|
||||
Another proposed alternative was to have the substituted text between
|
||||
\{ and } or between \{ and \}. While this syntax would probably be
|
||||
desirable if all string literals were to support interpolation, this
|
||||
PEP only supports strings that are already marked with the leading
|
||||
'f'. As such, the PEP is using unadorned braces to denoted substituted
|
||||
text, in order to leverage end user familiarity with str.format().
|
||||
|
||||
Supporting full Python expressions
|
||||
**********************************
|
||||
|
||||
Many people on the python-ideas discussion wanted support for either
|
||||
only single identifiers, or a limited subset of Python expressions
|
||||
(such as the subset supported by str.format()). This PEP supports full
|
||||
Python expressions inside the braces. Without full expressions, some
|
||||
desirable usage would be forbidden::
|
||||
|
||||
>>> f'Column={col_idx+1}'
|
||||
>>> f'number of items: {len(items)}'
|
||||
|
||||
would become::
|
||||
|
||||
>>> col_number = col_idx+1
|
||||
>>> f'Column={col_number}'
|
||||
>>> n_items = len(items)
|
||||
>>> f'number of items: {n_items}'
|
||||
|
||||
While it's true that very ugly expressions could be included in the
|
||||
f-strings, this PEP takes the position that such uses should be
|
||||
addressed in a linter or code review::
|
||||
|
||||
>>> f'mapping is { {a:b for (a, b) in ((1, 2), (3, 4))}}'
|
||||
'mapping is {1: 2, 3: 4}'
|
||||
|
||||
Similar support in other languages
|
||||
----------------------------------
|
||||
|
@ -528,13 +621,13 @@ Lambdas may be used inside of parens::
|
|||
Future extensions:
|
||||
==================
|
||||
|
||||
XXX: By using another leading character (say, 'i'), we could extend
|
||||
this proposal to cover internationalization and localization. The idea
|
||||
is that the string would be passed to some lookup function before
|
||||
By using another leading character (say, 'i'), we could extend this
|
||||
proposal to cover internationalization and localization. The idea is
|
||||
that the string would be passed to some lookup function before
|
||||
.interpolate() is called on it::
|
||||
|
||||
>>> name = 'Eric'
|
||||
>>> fi'Name: {name}'
|
||||
>>> i'Name: {name}'
|
||||
|
||||
Could be translated as::
|
||||
|
||||
|
@ -551,8 +644,10 @@ field_names are not found in the mapping argument. The choices might
|
|||
be: use the field_name, use a default (possibly empty) string, or
|
||||
raise an exception.
|
||||
|
||||
References
|
||||
==========
|
||||
There would obviously need to be some way to specify to the compiler
|
||||
what lookup function would be called.
|
||||
|
||||
References ==========
|
||||
|
||||
.. [#] %-formatting
|
||||
(https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting)
|
||||
|
|
Loading…
Reference in New Issue