f



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

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?
0
Veek
12/10/2016 7:06:23 AM
comp.lang.python 77058 articles. 6 followers. Post Follow

4 Replies
653 Views

Similar Articles

[PageSpeed] 37

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.

0
Steve
12/10/2016 8:52:02 AM
Steve D'Aprano wrote:

> 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
> 
> 
> 
> 
> 

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?








0
Veek
12/11/2016 6:40:37 AM
On Sat, Dec 10, 2016 at 11:40 PM, Veek M <vek.m1234@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.
0
Ian
12/11/2016 7:21:18 AM
Ian Kelly wrote:

> On Sat, Dec 10, 2016 at 11:40 PM, Veek M <vek.m1234@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.

Ah! thanks guys, now it works great. (I still need to ponder all this 
anyhow but yay!)
0
Veek
12/11/2016 8:52:39 AM
Reply: