Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

% string formatting - what special method is used for %d?

40 views
Skip to first unread message

Veek M

unread,
Dec 10, 2016, 2:06:38 AM12/10/16
to
When we do:

print '%s %d' % ('hello', 10)

what special method is being invoked internally within the string-
format-specifier?

format() invokes format__
print invokes __str__

I'm basically trying to make sense of:

raise TypeError('urkle urkle %s' % list(dictionary))
<=> raise TypeError('urkle urkle %s' % [ key1, val1, key2, val2 ]

So, the % operator reads the format specifier and notices %s and
therefore calls __str__ in the list class to figure out how to represent
[ key1, val1, key2, val2 ].

However what if I use %d? How do the other format specs work?

Steve D'Aprano

unread,
Dec 10, 2016, 3:52:14 AM12/10/16
to
On Sat, 10 Dec 2016 06:06 pm, Veek M wrote:

> When we do:
>
> print '%s %d' % ('hello', 10)
>
> what special method is being invoked internally within the string-
> format-specifier?

%d requires the argument to be an int, or able to be converted to int using
the __int__ special method.


py> class X(object):
... def __int__(self):
... return 42
...
py> "%d" % X()
'42'



> format() invokes format__
> print invokes __str__

print actually invokes __str__ or __repr__, whichever is available.



> I'm basically trying to make sense of:
>
> raise TypeError('urkle urkle %s' % list(dictionary))
> <=> raise TypeError('urkle urkle %s' % [ key1, val1, key2, val2 ]


The raise TypeError part of the code is irrelevant to your question. You
should always simplify your code to only the part that is relevant.

raise TypeError(some_string)

behaves the same regardless of how some_string is made.


> So, the % operator reads the format specifier and notices %s and
> therefore calls __str__ in the list class to figure out how to represent
> [ key1, val1, key2, val2 ].
>
> However what if I use %d? How do the other format specs work?


The format specifiers are similar to these:

%s => str(obj), which ends up calling __str__ or __repr__

%r => repr(obj), which ends up calling __repr__ or __str__

%c => chr(obj), or obj must be a string of length 1

%d %i %u => int(obj), which ends up calling __int__

%x %X => int(obj), then convert to hexadecimal

%o => int(obj), then convert to octal

%e %E %f %g %G => float(obj), which ends up calling __float__

%% => a literal % sign





--
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

Veek M

unread,
Dec 11, 2016, 1:41:01 AM12/11/16
to
Well take a look at this:
###########################################
#!/usr/bin/python

class Foo(int):
def __init__(self, value):
self.value = value

def __str__(self):
print '__str__'
return str(self.value)

def __int__(self):
print '__int__'
return self.value + 1


#'%s' % Foo(10) # %s is mapped to __str__
'%d' % Foo(20)
###########################################

here, '__str__' prints because when you do:
'%s' % x
the __str__ method is invoked. So internally %s invokes __str__
independent of print.

However the next line doesn't trigger any similar invocation with
__int__ or__str__? (but int(Foo(10)) would invoked __int__)

Is there a way to trigger special methods using %d etc OR is this
restricted to %s and why?








Ian Kelly

unread,
Dec 11, 2016, 2:22:18 AM12/11/16
to
On Sat, Dec 10, 2016 at 11:40 PM, Veek M <vek....@gmail.com> wrote:
> Well take a look at this:
> ###########################################
> #!/usr/bin/python
>
> class Foo(int):
> def __init__(self, value):
> self.value = value
>
> def __str__(self):
> print '__str__'
> return str(self.value)
>
> def __int__(self):
> print '__int__'
> return self.value + 1
>
>
> #'%s' % Foo(10) # %s is mapped to __str__
> '%d' % Foo(20)
> ###########################################
>
> here, '__str__' prints because when you do:
> '%s' % x
> the __str__ method is invoked. So internally %s invokes __str__
> independent of print.
>
> However the next line doesn't trigger any similar invocation with
> __int__ or__str__? (but int(Foo(10)) would invoked __int__)

This is probably because Foo inherits from int. Foo(20) is already an
int so there is no conversion to be done; Python simply uses the int
value and ignores the __int__ method in this case.

> Is there a way to trigger special methods using %d etc OR is this
> restricted to %s and why?

For an object that is already an int, probably not.

However you may want to revisit your decision to make Foo inherit from
int and question whether that is really sensible if you're also
wanting to override the __int__ method. What does that mean if
something is an int but also provides a method to convert to int? It's
a contradiction.

Veek M

unread,
Dec 11, 2016, 3:53:01 AM12/11/16
to
Ah! thanks guys, now it works great. (I still need to ponder all this
anyhow but yay!)
0 new messages