On 5/2/2021 5:44 AM, Steven D'Aprano wrote:
On Sun, May 02, 2021 at 04:09:21AM -0000, Valentin Berlier wrote:

Let's say i have a matrix of numbers:

matrix = [[randint(7, 50) / randint(1, 3) for _ in range(4)] for _ in range(4)]

I want to format and display each row so that the columns are nicely lined up. 
Maybe also display the sum of the row at the end of each line:

for row in matrix:
     print(''.join(f'{n:>8.3f}' for n in row) + f' | {sum(row):>8.3f}')

This gives me a nicely formatted table. Now with the proposal:

for row in matrix:
     print(f'{n for n in row:>8.3f} | {sum(row):>8.3f}')
As a general rule, we should avoid needless generator expressions that
just iterate over themselves:

     n for n in row

is just the same as

     row

except it creates a pointless generator to iterate over something that
is already iterable.

Your proposed f-string syntax:

     f'{n for n in row:>8.3f} | {sum(row):>8.3f}'

is already legal except for the first format specifier. Removing that:

     f'{n for n in row} | {sum(row):>8.3f}'

gives us working code. I don't believe that we ought to confuse the
format specifier syntax by making the f format code have magical powers
when given an in-place generator expression, and otherwise have the
regular meaning for anything else.

Better to invent a new format code, which I'm going to spell as 'X' for
lack of something better, that maps a format specifier to every
element of any iterable (not just generator comprehensions):

     f'{row:X>8.3f} | {sum(row):>8.3f}'

meaning, format each element of row with `>8.3f`.

I'm completely opposed to all of this, but I'll note that you don't want the thing that gives instructions to the f-string mechanism to be part of the format specifier, you'd want it to be a conversion flag like !r and !s. The format spec is reserved for the object being formatted. The way this is specified, you'd either have to change the f-string mechanics to start interpreting format specs, or have every iterable understand what "X" means.

For example, "X" is already understood by datetime as part of its format spec "language":

>>> f'{datetime.now() - timedelta(days=3):X days ago it was a %A}'
'X days ago it was a Thursday'

I don't think you'd want f-strings to hijack that expression because it starts with "X". Better to do something like:

f'{row!X:>8.3f} | {sum(row):>8.3f}'

But I'll reiterate that I'm opposed. Sometimes you just need to do the formatting outside of an f-string. Terseness shouldn't be the ultimate goal.

The idea is that you would be able to embed a comprehension in
f-string interpolations,
When the only tool you have is a hammer, every problem looks like it is
crying out for a comprehension *wink*

Or crying out for an f-string!

The thing I'd like everyone to remember is that the format spec language as implemented by some (but not all) of the built-in types isn't the only format spec language around, and indeed it's not the only used by built-in types.

--

Eric V. Smith

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/EWSBTWIPLGHF6LPRXLHOGIJGVBQZ6B6Q/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to