On 4/20/2021 11:13 AM, Eric V. Smith wrote:
On 4/20/2021 10:56 AM, Ethan Furman wrote:
urllib.urlencode currently uses `str()` on its non-bytes objects before encoding the result.  This causes a compatibility break when integer module constants are converted to IntEnum, as `str(IntEnum.MEMBER)` no longer returns the integer representation; however, `format()` does still return the integer representation.

The fix is to add a separate branch to check if the argument is an Enum, and use the value if so -- but it got me wondering: in general, are there differences between calling str() vs calling format() on Python objects?

If there's no format string, then object___format___impl() just calls PyObject_Str(). So unless the object overrides __format__, they're the same.

I should mention that if you're going to implement __format__ and you don't care about the format specifier, then I'd do what object.__format__ does and raise an error for any non-empty format specifier. That way you can add a format specifier in the future and not worry that people are relying on passing in arbitrary format specs, which is a backward compatibility problem. That's why the error case was added to object.__format__: see https://bugs.python.org/issue7994 .

Eric

int does override __format__, in _PyLong_FormatAdvancedWriter(). It has a comment that says:

    /* check for the special case of zero length format spec, make
       it equivalent to str(obj) */

So even in the case of it, str(obj) should be the same as format(obj).

I thoughtPEP 3101 specifies this behavior, but I don't see it there. It's hopelessly out of date, anyway. The docs for format() say these weasel words: "The default format_spec is an empty string which usually gives the same effect as calling str(value).". They're vague because a user defined type could do anything in __format__, including ignore this advice. But I think all of the built-in types conform to it.

Eric



_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/BYVXDW7QHCZ45TFPRAW5ALYMFSDYX47Y/
Code of Conduct: http://python.org/psf/codeofconduct/
-- 
Eric V. Smith