Search code examples
pythonstring-formatting

f-string format specifier with None throws TypeError


Using plain f-strings with a NoneType object works:

>>> a = None
>>> f'{a}'
'None'

However, when using a format specifier, it breaks---as does str.format():

>>> f'{a:>6}'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to NoneType.__format__

>>> '{:>6}'.format(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to NoneType.__format__

Unexpectedly, (for me, at least) the old C-style string formatting works:

>>> '%10s' % a
'      None'

What is going on here? I don't understand why f'{a:>6}' doesn't evaluate to ' None'. Why should a format specifier break it?

Is this a bug in python? If it is a bug, how would I fix it?


Solution

  • None doesn't support format specifiers. It's up to each object type to determine how it wants to handle format specifiers, and the default is to reject them:

    The __format__ method of object itself raises a TypeError if passed any non-empty string.

    None inherits this default.

    You seem to be expecting None to handle format specifiers the same way strings do, where '{:>6}'.format('None') == ' None'. It kind of sounds like you expect all types to handle format specifiers the way strings do, or you expect the string behavior to be the default. The way strings handle format specifiers is specific to strings; other types have their own handling.


    You might be thinking, hey, why doesn't %10s fail too? First, the s requests that the argument be converted to a string by str before any further processing. Second, all conversion specifier handling in printf-style string formatting is performed by str.__mod__; it never delegates to the arguments to figure out what a conversion specifier means.