Although many new-comers are intrigued by the compulsory indentation rule, I have been surprised to discover that even though whitespace does not usually feature as a formatting-specification, nevertheless Python sometimes requires an absence of whitespace.

Will this behavior/requirement continue when using (a pre-release version featuring) the new parser?


Whitespace has meaning to us - when it comes to indentation defining (not merely illustrating) blocks of code. However, the rest of the time, it is ignored by Python. (yes, this discussion disdains comments!) For example, whitespace is no problem when it comes to defining a list:

month_names = ['Januari', 'Februari', 'Maart',      # These are the
               'April',   'Mei',      'Juni',       # Dutch names...

Similarly, a totally blank line will be equally-totally ignored.

As my eye-sight ages (it's older than my teeth!), I find code easier to read when there is more whitespace - and it becomes more difficult to parse when whitespace is omitted. For example, I receive regular comments/criticisms for writing an argument list with spaces inside the parentheses, eg

    def func( arg1, arg2, ):

Whilst there are some 'standards' which decry such practice, I note that many IDEs will offer to add such spaces, auto-magically, as a config/option. So, apparently I'm not unique - just 'special'?

I don't use 'back-slash continuity' very often (at the expense of more parens!), and was intrigued to discover in experiments; that not only is a space before the back-slash considered optional, but sometimes a space is not necessary at all, eg

>>> if\
... True: print( 'yes' )
...
yes
>>> ifTrue: print( 'yes' )
yes

although Python won't let me go-crazy:

>>> if True andFalse: print( 'yes' )
  File "<stdin>", line 1
    if True andFalse: print( 'yes' )
            ^
SyntaxError: invalid syntax
>>> if Tr\
... ue: print( 'yes' )
  File "<stdin>", line 2
    if Tr\
ue: print( 'yes' )
    ^
SyntaxError: invalid syntax

The legal statement: <<<2.1.9. Whitespace between tokens
Except at the beginning of a logical line or in string literals, the whitespace characters space, tab and formfeed can be used interchangeably to separate tokens. Whitespace is needed between two tokens only if their concatenation could otherwise be interpreted as a different token (e.g., ab is one token, but a b is two tokens).>>>

Thus, (a little later on the same page): <<<One syntactic restriction not indicated by these productions is that whitespace is not allowed between the stringprefix or bytesprefix and the rest of the literal.>>> Thus, it must be expressed as "b'bytes'" and not "b 'bytes'". Admittedly, such separation hadn't occurred to me, in much the same way that "print ()" doesn't seem correct, but...

When we break the language-elements into "tokens" the 'bytes' and the argument-list's parentheses are separate from the preceding "b" or function-name, albeit semantically inseparable.

For f-strings/formatted string literals, the most usual form is:

    "{" f_expression ["="] ["!" conversion] [":" format_spec] "}"

Remembering that this is BNF, see the space separating the closing-brace from anything preceding it - how else would we separate the components to comprehend?

Returning to Python:

>>> one = 1    # is the loneliest number...
>>> f'{ one }'
'1'
>>> f'{ one:03 }'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Unknown format code '\x20' for object of type 'int'
>>> f'{ one:03}'
'001'

Notice the presence/absence of the final space.

>>> pi = 3.14159   # better to import math
>>> f'{ pi!r:10 }'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Unknown format code '\x20' for object of type 'str'
>>> f'{ pi!r:10}'
'3.14159   '
>>> f'{ pi!r }'
  File "<stdin>", line 1
SyntaxError: f-string: expecting '}'
>>> f'{ pi!r}'
'3.14159'

So, the f-string will work if the braces include only an expression surrounded by spaces. However, if one adds a conversion or format-specification, that final space becomes a no-no. Eh what!

To be fair, the 'book of words' does say: "A replacement field ends with a closing curly bracket '}'.". No mention of whitespace. No mention that a replacement field consisting only of an f_expression, will be treated differently by allowing a space.

Version 3.8 introduced the "=" short-cut:

>>> f"{ foo = }" # preserves whitespace
" foo = 'bar'"

Note the comment! Yet, the manual's examples continue:

>>> line = "The mill's closed"
>>> f"{line = }"
'line = "The mill\'s closed"'
>>> f"{line = :20}"
"line = The mill's closed   "

Hey, why does this second example dispense with the braces-internal spaces? Sure enough, when I check it for myself:

>>> line = "The mill's closed"
>>> f'{line = :20 }'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Unknown format code '\x20' for object of type 'str'
>>> f'{ line = :20}'
" line = The mill's closed   "
>>> f'{line = :20}'
"line = The mill's closed   "

Should the closing brace be considered part of a conversion or format-specification? The space (I'd like to add) cannot be considered part of a conversion or format-specification (see BNF, see text of web.ref)!


(when you compare how long it took me to (speed) type this message, and how long it took me to figure-out that my 'excess space' was causing a fault in an f-string, the time-cost was about the same. Grrr! (the relative frustrations-caused, somewhat different!)


Will be interested in explanations, and improvements to understanding.
(but not so much in 'corrections' to my (mis-)behavior - I already pay that price!)

If you're operating at the 'bleeding edge', will be interested to hear how the 'new parser' handles same.


Web.Ref:
https://docs.python.org/3/reference/lexical_analysis.html
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to