PEP-498 updates: specify str.interpolate() and beef up some of the discussion text. Still needs work on the XXX marked sections.
This commit is contained in:
parent
eaf9ea6841
commit
2b710a1d86
120
pep-0498.txt
120
pep-0498.txt
|
@ -41,6 +41,9 @@ values. Some examples are::
|
|||
>>> f'He said his name is {name!r}.'
|
||||
"He said his name is 'Fred'."
|
||||
|
||||
This PEP proposes a new method on the str type: str.interpolate. This
|
||||
method will be used to implement f-strings.
|
||||
|
||||
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
|
||||
|
@ -139,6 +142,11 @@ order for this to work::
|
|||
>>> outer(42)()
|
||||
'x=42'
|
||||
|
||||
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.
|
||||
|
||||
Guido stated [#]_ that any solution to better string interpolation
|
||||
would not use locals() or globals().
|
||||
|
||||
|
@ -185,21 +193,34 @@ Expressions cannot contain ':' or '!' outside of strings or parens,
|
|||
brackets, or braces. The exception is that the '!=' operator is
|
||||
special cased.
|
||||
|
||||
str.interpolate()
|
||||
-----------------
|
||||
|
||||
str.interpolate 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(), it does interpret and apply the optional conversion
|
||||
character and format specifier. Thus, a field name may not contain the
|
||||
characters ':' or '}', nor the strings '!s' and '!r'.
|
||||
|
||||
Code equivalence
|
||||
----------------
|
||||
|
||||
The exact code that is executed when converting expressions to strings
|
||||
is unspecified by this PEP. However, it is specified that once the
|
||||
expression is evaluated, the result's __format__() method will be
|
||||
called with the given format specifier.
|
||||
An f-string is evaluated at run time as a call to str.interpolate().
|
||||
|
||||
For example, this code::
|
||||
|
||||
f'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi'
|
||||
|
||||
May be evaluated as::
|
||||
Will be be evaluated as::
|
||||
|
||||
'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi'.interpolate({'expr1': expr1, 'expr2': expr2, 'expr3': expr3})
|
||||
|
||||
Note that the string on which interpolate() is being called is
|
||||
identical to the value of the f-string.
|
||||
|
||||
''.join(['abc', expr1.__format__('spec1'), repr(expr2).__format__('spec2'), 'def', str(expr3).__format__(''), 'ghi'])
|
||||
|
||||
Expression evaluation
|
||||
---------------------
|
||||
|
@ -258,10 +279,11 @@ yields the value::
|
|||
|
||||
'ab10cstr< hi >de'
|
||||
|
||||
While the exact code that is executed when evaluating this f-string is
|
||||
not specified, one possible strategy is to evaluate::
|
||||
While the exact method of this runtime concatenation is unspecified,
|
||||
the above code might evaluate to::
|
||||
|
||||
''.join(['ab', x.__format__(''), 'c', 'str<', y.__format__('^4'), '>', 'de'])
|
||||
|
||||
''.join(['ab', '{x}'.interpolate({'x': x}), 'c', 'str<', 'str<{y:^4}>'.interpolate({'y': y}), 'de'])
|
||||
|
||||
Error handling
|
||||
--------------
|
||||
|
@ -310,24 +332,20 @@ or::
|
|||
File "<stdin>", line 2, in <module>
|
||||
ValueError: Sign not allowed in string format specifier
|
||||
|
||||
Leading whitespace in expressions is skipped
|
||||
--------------------------------------------
|
||||
Leading and trailing whitespace in expressions is skipped
|
||||
---------------------------------------------------------
|
||||
|
||||
Because expressions may begin with a left brace ('{'), there is a
|
||||
problem when parsing such expressions. For example::
|
||||
For ease of readability, leading and trailing whitespace in
|
||||
expressions is ignored. However, this does not affect the string or
|
||||
keys passed to str.interpolate().
|
||||
|
||||
>>> f'{{k:v for k, v in [(1, 2), (3, 4)]}}'
|
||||
'{k:v for k, v in [(1, 2), (3, 4)]}'
|
||||
>>> x = 100
|
||||
>>> f'x = { x }'
|
||||
'x = 100'
|
||||
|
||||
In this case, the doubled left braces and doubled right braces are
|
||||
interpreted as single braces, and the string becomes just a normal
|
||||
string literal. There is no expression evaluation being performed.
|
||||
This would be evaluated as::
|
||||
|
||||
To allow for expressions to begin with a left brace, whitespace
|
||||
characters at the beginning of an expression are skipped::
|
||||
|
||||
>>> f'{ {k:v for k, v in [(1, 2), (3, 4)]}}'
|
||||
'{1: 2, 3: 4}'
|
||||
'x = { x }'.interpolate({' x ': 100})
|
||||
|
||||
Discussion
|
||||
==========
|
||||
|
@ -337,14 +355,15 @@ Most of the discussions on python-ideas [#]_ focused on a few issues:
|
|||
- Whether to allow full Python expressions.
|
||||
- How to designate f-strings, and how to specify the location of
|
||||
expressions in them.
|
||||
- How to concatenate adjacent strings and f-strings.
|
||||
|
||||
XXX: more on the above issues.
|
||||
|
||||
Similar support in other languages
|
||||
----------------------------------
|
||||
|
||||
XXX: Placeholder.
|
||||
Wikipedia has a good discussion of string interpolation in other
|
||||
programming languages [#]_. This feature is implemented in many
|
||||
languages, with a variety of syntaxes and restrictions.
|
||||
|
||||
Differences between f-string and str.format expressions
|
||||
-------------------------------------------------------
|
||||
|
@ -377,6 +396,25 @@ use variables as index values::
|
|||
See [#]_ for a further discussion. It was this observation that led to
|
||||
full Python expressions being supported in f-strings.
|
||||
|
||||
Triple-quoted f-strings
|
||||
-----------------------
|
||||
|
||||
Triple quoted f-strings are allowed. These strings are parsed just as
|
||||
normal triple-quoted strings are. After parsing, the normal f-string
|
||||
logic is applied, and str.interpolate() is called.
|
||||
|
||||
Raw f-strings
|
||||
-------------
|
||||
|
||||
Raw and f-strings may be combined. For example they could be used to
|
||||
build up regular expressions::
|
||||
|
||||
>>> header = 'Subject'
|
||||
>>> fr'{header}:\s+'
|
||||
'Subject:\\s+'
|
||||
|
||||
In addition, raw f-strings may be combined with triple-quoted strings.
|
||||
|
||||
No binary f-strings
|
||||
-------------------
|
||||
|
||||
|
@ -385,6 +423,8 @@ combine 'f' with 'b' string literals. The primary problem is that an
|
|||
object's __format__() method may return Unicode data that is not
|
||||
compatible with a bytes string.
|
||||
|
||||
#XXX: maybe allow this, but encode the output as ascii?
|
||||
|
||||
!s and !r are redundant
|
||||
-----------------------
|
||||
|
||||
|
@ -421,6 +461,27 @@ Lambdas may be used inside of parens::
|
|||
>>> f'{(lambda x: x*2)(3)}'
|
||||
'6'
|
||||
|
||||
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
|
||||
.interpolate() is called on it:
|
||||
|
||||
>>> name = 'Eric'
|
||||
>>> fi'Name: {name}'
|
||||
|
||||
Could be translated as::
|
||||
|
||||
gettext.gettext('Name: {name}').interpolate({'name': name})
|
||||
|
||||
If gettext.gettext() returned '{name} es mi nombre', then the
|
||||
resulting string would be 'Eric es mi nombre'.
|
||||
|
||||
Any such internationalization work will be specified in an additional
|
||||
PEP.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
|
@ -445,6 +506,15 @@ References
|
|||
.. [#] Avoid locals() and globals()
|
||||
(https://mail.python.org/pipermail/python-ideas/2015-July/034701.html)
|
||||
|
||||
.. [#] str.format_map() documentation
|
||||
(https://docs.python.org/3/library/stdtypes.html#str.format_map)
|
||||
|
||||
.. [#] Format string syntax
|
||||
(https://docs.python.org/3/library/string.html#format-string-syntax)
|
||||
|
||||
.. [#] Wikipedia article on string interpolation
|
||||
(https://en.wikipedia.org/wiki/String_interpolation)
|
||||
|
||||
.. [#] Start of python-ideas discussion
|
||||
(https://mail.python.org/pipermail/python-ideas/2015-July/034657.html)
|
||||
|
||||
|
|
Loading…
Reference in New Issue