Search code examples
pythonstringoverridingf-string

Python expressions in f-strings do not return same result as str() conversion for subclasses?


For example, we override the __str__ method in Decimal then call it two different ways

from decimal import Decimal
class D(Decimal):
    def __str__(self):
        return super().normalize().__str__()
num = D('1.0')
print(f"{num}")
print(f"{str(num)}")

outputs

1.0
1

But they should both output 1. It seems like the first print is calling Decimal.__str__ instead of D.__str__ for some reason. Why does this happen and how do I fix the behavior?


Solution

  • You'll need to override __format__ too (see the f-string PEP, search for __format__).

    from decimal import Decimal
    
    
    class D(Decimal):
        def __str__(self):
            return super().normalize().__str__()
    
        def __format__(self, format_spec):
            return super().normalize().__format__(format_spec)
    
    
    num = D('1.0')
    print(f"{num}")
    print(f"{str(num)}")
    

    prints out

    1
    1