: str() vs format(): trivia question

@serhiy Moving my speculative discussion to python-ideas. CC as courtesy, comment from you is welcome but not necessarily expected. Serhiy Storchaka writes:
format() without format specifier and str() should return the same value in general, otherwise it will confuse users.
I think this is a good rule of thumb because it's a very plausible default for format(), and easy to explain. But then what is the purpose of format()? Why not just give str() the functionality of format(), and deprecate format() for future use? Or vice versa, format() might be the better name, but the backward compatibility implications given the pervasive use of str() would be awesome, and not in a good way. Given how pervasive both str and format are, and the fact that str also has both .format() and .__format__ methods, I guess I'm asking for a lot of trouble. But this plethora of approaches to providing a string presentation of an object seems designed to confuse users, and it's not clear to me that trying to maintain str(thing) == format(thing) necessary helps dissolve that confusion. Steve

On Thu, Apr 22, 2021 at 5:22 PM Stephen J. Turnbull <turnbull.stephen.fw@u.tsukuba.ac.jp> wrote:
str() is already bigger than it needs to be. It is the constructor for string objects, but it's also able to decode a bytes-like object or buffer, and can convert arbitrary objects to strings. It shouldn't also be responsible for *formatting* arbitrary objects, even though they'll end up as strings.
The normal job of format() is to format something in a specific way.
format(123456, "x") '1e240'
And that's also what's going to be used in an f-string:
f"{123456:x}" '1e240'
So if you're writing an f-string and you do this:
x = 123456; f"{x} {x:}" '123456 123456'
you would expect that the empty format string, and the omitted format string, will do the single most obvious method of formatting - just turn it into a string in whatever way the object things appropriate. Technically you CAN make str(x) and format(x) do different things, but you can also mess with other expectations:
I'd consider the one problem here (enums) to be a bug to be fixed, albeit one with backward compatibility issues, and then for the rest, just keep a general documented recommendation and leave it at that. ChrisA

22.04.21 10:21, Stephen J. Turnbull пише:
Technically, because the second argument of str() means encoding. So you would need either make format specifier a third positional parameter, str(price, None, None, '8.2f') or make it a keyword-only parameter, str(price, format_spec='8.l2'). Both are look ugly. And since a format specifier is mutually incompatible with encoding and errors, it is clear that there should be two distinct functions. Also, all existing __str__ methods do not accept additional arguments. There is no way to pass format specifier to it. So we need a new special method. We could name it __str_ex__, but __format__ seems a better name.
It is not hard to maintain because object.__format__ just calls __str__. If you do not implement __format__, you get it by default. If you implement __format__ you are free to do what you want. And usually, if you implement addition and multiplication, you have to maintain thing+thing == thing*2, but it does not mean that we need to merge addition and multiplication into single operation.

On Thu, Apr 22, 2021 at 5:22 PM Stephen J. Turnbull <turnbull.stephen.fw@u.tsukuba.ac.jp> wrote:
str() is already bigger than it needs to be. It is the constructor for string objects, but it's also able to decode a bytes-like object or buffer, and can convert arbitrary objects to strings. It shouldn't also be responsible for *formatting* arbitrary objects, even though they'll end up as strings.
The normal job of format() is to format something in a specific way.
format(123456, "x") '1e240'
And that's also what's going to be used in an f-string:
f"{123456:x}" '1e240'
So if you're writing an f-string and you do this:
x = 123456; f"{x} {x:}" '123456 123456'
you would expect that the empty format string, and the omitted format string, will do the single most obvious method of formatting - just turn it into a string in whatever way the object things appropriate. Technically you CAN make str(x) and format(x) do different things, but you can also mess with other expectations:
I'd consider the one problem here (enums) to be a bug to be fixed, albeit one with backward compatibility issues, and then for the rest, just keep a general documented recommendation and leave it at that. ChrisA

22.04.21 10:21, Stephen J. Turnbull пише:
Technically, because the second argument of str() means encoding. So you would need either make format specifier a third positional parameter, str(price, None, None, '8.2f') or make it a keyword-only parameter, str(price, format_spec='8.l2'). Both are look ugly. And since a format specifier is mutually incompatible with encoding and errors, it is clear that there should be two distinct functions. Also, all existing __str__ methods do not accept additional arguments. There is no way to pass format specifier to it. So we need a new special method. We could name it __str_ex__, but __format__ seems a better name.
It is not hard to maintain because object.__format__ just calls __str__. If you do not implement __format__, you get it by default. If you implement __format__ you are free to do what you want. And usually, if you implement addition and multiplication, you have to maintain thing+thing == thing*2, but it does not mean that we need to merge addition and multiplication into single operation.
participants (3)
-
Chris Angelico
-
Serhiy Storchaka
-
Stephen J. Turnbull