[Python-Dev] PEP 461 - Adding % and {} formatting to bytes

Ethan Furman ethan at stoneleaf.us
Fri Jan 17 17:07:03 CET 2014


On 01/16/2014 11:47 PM, Steven D'Aprano wrote:
> On Thu, Jan 16, 2014 at 08:23:13AM -0800, Ethan Furman wrote:
>
>> As I understand it, str.format will call the object's __format__.  So, for
>> example, if I say:
>>
>>    u'the value is: %d' % myNum(17)
>>
>> then it will be myNum.__format__ that gets called, not int.__format__;
>
> I seem to have missed something, because I am completely confused... Why
> are you talking about str.format and then show an example using % instead?

Sorry, PEP 46x fatigue.  :/

It should have been

     u'the value is {:d}'.format(myNum(17))

and yes I meant the str type.


> %d calls __str__, not __format__. This is in Python 3.3:
>
> py> class MyNum(int):
> ...     def __str__(self):
> ...             print("Calling MyNum.__str__")
> ...             return super().__str__()
> ...     def __format__(self):
> ...             print("Calling MyNum.__format__")
> ...             return super().__format__()
> ...
> py> n = MyNum(17)
> py> u"%d" % n
> Calling MyNum.__str__
> '17'

And that's a bug we fixed in 3.4:

Python 3.4.0b1 (default:172a6bfdd91b+, Jan  5 2014, 06:39:32)
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.

--> class myNum(int):
...   def __int__(self):
...     return 7
...   def __index__(self):
...     return 11
...   def __float__(self):
...     return 13.81727
...   def __str__(self):
...     print('__str__')
...     return '1'
...   def __repr__(self):
...     print('__repr__')
...     return '2'
...
--> '%d' % myNum()
'0'
--> '%f' % myNum()
'13.817270'


After all, consider:

>>> '%d' % True
'1'
>>> '%s' % True
'True'

So, in fact, on subclasses __str__ should *not* be called to get the integer representation.  First we do a conversion 
to make sure we have an int (or float, or ...), and then we call __str__ on our tried and trusted genuine core type.


> The *worst* solution would be to completely ignore MyNum.__str__.
> That's a nasty violation of the Principle Of Least Surprise, and will
> lead to confusion ("why isn't my class' __str__ method being called?")

Because you asked for a numeric representation, not a string representation [1].

--
~Ethan~


[1] for all the gory details, see:
     http://bugs.python.org/issue18780
     http://bugs.python.org/issue18738


More information about the Python-Dev mailing list