merge
This commit is contained in:
commit
eb8155bac5
91
pep-0498.txt
91
pep-0498.txt
|
@ -208,6 +208,25 @@ Expressions cannot contain ':' or '!' outside of strings or parens,
|
||||||
brackets, or braces. The exception is that the '!=' operator is
|
brackets, or braces. The exception is that the '!=' operator is
|
||||||
special cased.
|
special cased.
|
||||||
|
|
||||||
|
Escape sequences
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Scanning an f-string for expressions happens after escape sequences
|
||||||
|
are decoded. Because hex(ord('{')) == 0x7b, the f-string
|
||||||
|
f'\\u007b4*10}' is decoded to f'{4*10}', which evaluates as the integer
|
||||||
|
40::
|
||||||
|
|
||||||
|
>>> f'\u007b4*10}'
|
||||||
|
'40'
|
||||||
|
>>> f'\x7b4*10}'
|
||||||
|
'40'
|
||||||
|
>>> f'\x7b4*10\N{RIGHT CURLY BRACKET}'
|
||||||
|
'40'
|
||||||
|
|
||||||
|
These examples aren't generally useful, they're just to show that
|
||||||
|
escape sequences are processed before f-strings are parsed for
|
||||||
|
expressions.
|
||||||
|
|
||||||
Code equivalence
|
Code equivalence
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
@ -360,6 +379,25 @@ Leading and trailing whitespace in expressions is skipped
|
||||||
For ease of readability, leading and trailing whitespace in
|
For ease of readability, leading and trailing whitespace in
|
||||||
expressions is ignored.
|
expressions is ignored.
|
||||||
|
|
||||||
|
Evaluation order of expressions
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The expressions in an f-string are evaluated in left-to-right
|
||||||
|
order. This is detectable only if the expressions have side effects::
|
||||||
|
|
||||||
|
>>> def fn(l, incr):
|
||||||
|
... result = l[0]
|
||||||
|
... l[0] += incr
|
||||||
|
... return result
|
||||||
|
...
|
||||||
|
>>> lst = [0]
|
||||||
|
>>> f'{fn(lst,2)} {fn(lst,3)}'
|
||||||
|
'0 2'
|
||||||
|
>>> f'{fn(lst,2)} {fn(lst,3)}'
|
||||||
|
'5 7'
|
||||||
|
>>> lst
|
||||||
|
[10]
|
||||||
|
|
||||||
Discussion
|
Discussion
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
@ -403,7 +441,7 @@ used. A quick search of Python's standard library shows only a handful
|
||||||
of uses of string.Template, but hundreds of uses of str.format().
|
of uses of string.Template, but hundreds of uses of str.format().
|
||||||
|
|
||||||
Another proposed alternative was to have the substituted text between
|
Another proposed alternative was to have the substituted text between
|
||||||
\{ and } or between \{ and \}. While this syntax would probably be
|
\\{ and } or between \\{ and \\}. While this syntax would probably be
|
||||||
desirable if all string literals were to support interpolation, this
|
desirable if all string literals were to support interpolation, this
|
||||||
PEP only supports strings that are already marked with the leading
|
PEP only supports strings that are already marked with the leading
|
||||||
'f'. As such, the PEP is using unadorned braces to denoted substituted
|
'f'. As such, the PEP is using unadorned braces to denoted substituted
|
||||||
|
@ -473,6 +511,15 @@ use variables as index values::
|
||||||
See [#]_ for a further discussion. It was this observation that led to
|
See [#]_ for a further discussion. It was this observation that led to
|
||||||
full Python expressions being supported in f-strings.
|
full Python expressions being supported in f-strings.
|
||||||
|
|
||||||
|
Furthermore, the limited expressions that str.format() understands
|
||||||
|
need not be valid Python expressions. For example::
|
||||||
|
|
||||||
|
>>> '{i[";]}'.format(i={'";':4})
|
||||||
|
'4'
|
||||||
|
|
||||||
|
For this reason, the str.format() "expression parser" is not suitable
|
||||||
|
for use when implementing f-strings.
|
||||||
|
|
||||||
Triple-quoted f-strings
|
Triple-quoted f-strings
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -593,15 +640,45 @@ having 2 expressions::
|
||||||
|
|
||||||
f'{x:.{width}}'
|
f'{x:.{width}}'
|
||||||
|
|
||||||
Expressions with side effects
|
The same expression used multiple times
|
||||||
-----------------------------
|
---------------------------------------
|
||||||
|
|
||||||
xxx
|
Every expression in braces in an f-string is evaluated exactly
|
||||||
|
once. If the same expression is used more than once in the same
|
||||||
|
f-string, it will be evaluated multiple times. However, it's undefined
|
||||||
|
which result will show up in the resulting string value. For purposes
|
||||||
|
of this section, two expressions are the same if they have the exact
|
||||||
|
same literal text defining them. For example, '{i}' and '{i}' are the
|
||||||
|
same expression, but '{i}' and '{ i}' are not, due to the extra space
|
||||||
|
in the second expression.
|
||||||
|
|
||||||
Expressions used multiple times
|
For example, given::
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
xxx
|
>>> def fn(lst):
|
||||||
|
... lst[0] += 1
|
||||||
|
... return lst[0]
|
||||||
|
...
|
||||||
|
>>> lst=[0]
|
||||||
|
>>> f'{fn(lst)} {fn(lst)}'
|
||||||
|
'1 2'
|
||||||
|
|
||||||
|
The resulting f-string might have the value '1 2', '2 2', '1 1', or
|
||||||
|
even '2 1'.
|
||||||
|
|
||||||
|
However::
|
||||||
|
|
||||||
|
>>> lst=[0]
|
||||||
|
>>> f'{fn(lst)} { fn(lst)}'
|
||||||
|
'1 2'
|
||||||
|
|
||||||
|
This f-string will always have the value '1 2'. This is due to the two
|
||||||
|
expressions not being the same: the space in the second example makes
|
||||||
|
the two expressions distinct.
|
||||||
|
|
||||||
|
This restriction is in place in order to allow for a possible future
|
||||||
|
extension allowing translated strings, wherein the expression
|
||||||
|
substitutions would be identified by their text values as they show up
|
||||||
|
between the braces.
|
||||||
|
|
||||||
References
|
References
|
||||||
==========
|
==========
|
||||||
|
|
|
@ -166,7 +166,7 @@ following semantics::
|
||||||
__slots__ = ("raw_template", "parsed_fields", "field_values")
|
__slots__ = ("raw_template", "parsed_fields", "field_values")
|
||||||
|
|
||||||
def __new__(cls, raw_template, parsed_fields, field_values):
|
def __new__(cls, raw_template, parsed_fields, field_values):
|
||||||
self = super().__new__()
|
self = super().__new__(cls)
|
||||||
self.raw_template = raw_template
|
self.raw_template = raw_template
|
||||||
self.parsed_fields = parsed_fields
|
self.parsed_fields = parsed_fields
|
||||||
self.field_values = field_values
|
self.field_values = field_values
|
||||||
|
|
Loading…
Reference in New Issue