[Tutor] Using string formatting inside function docstrings

Peter Otten __peter__ at web.de
Sat Apr 11 09:27:28 EDT 2020


boB Stepp wrote:

> On Sat, Apr 11, 2020 at 12:57 AM boB Stepp <robertvstepp at gmail.com> wrote:
> 
>> This runs:
>>
>> def fmt(*args):
>>     """Prints arguments of %s.""" % args[0]
>>     for i, arg in enumerate(args):
>>         print("arg #%s = %s " % (i, arg), end="")
>>     print()
>>
>>
>> fmt("Robert", "V.", "Stepp")
>>
>> Giving:
>>
>> bob at Dream-Machine1:~/Projects/Tutor_Help$ python3 s*
>> arg #0 = Robert arg #1 = V. arg #2 = Stepp
>>
>> But my original idea of using this for the docstring:
>>
>> """Prints arguments of %s.""" % args
>>
>> Throws an exception:
>>
>> bob at Dream-Machine1:~/Projects/Tutor_Help$ python3 s*
>> Traceback (most recent call last):
>>   File "str_fmt.py", line 11, in <module>
>>     fmt("Robert", "V.", "Stepp")
>>   File "str_fmt.py", line 5, in fmt
>>     """Prints arguments of %s.""" % args
>> TypeError: not all arguments converted during string formatting
> 
> Ah, I see why now.  There is only one "%s", but it is expecting three
> "%s" based on the number of arguments passed in.  It is too late to be
> trying to be too clever!

If you want to use %-formatting safely you have to write an explicit tuple:

"""Prints arguments of %s.""" % (args,)

By the way, what you are formatting is not a docstring, just a throwaway 
value:

>>> def fmt(*args):
...     """Prints arguments of %s.""" % args[0]
...     for i, arg in enumerate(args):
...         print("arg #%s = %s " % (i, arg), end="")
...     print()
... 
>>> fmt.__doc__ is None
True

How you format the string you throw away doesn't matter ;)

>>> def fmt(*args):
...     f"""Prints arguments of {args[0]}."""
... 
>>> fmt.__doc__ is None
True

> The intriguing part was the idea of using string formatting inside a
> function, method or class docstring.  Why would one want to do this?
> Can anyone give an interesting and practical example?

Not very interesting, but practical -- occasionally I generate a docstring 
in a factory function:

>>> def make_startswith(prefix):
...     def startswith(s):
...         return s.startswith(prefix)
...     startswith.__doc__ = f"Check if `s` starts with {prefix!r}."
...     return startswith
... 
>>> startswith = make_startswith("http://")
>>> help(startswith)
Help on function startswith in module __main__:

startswith(s)
    Check if `s` starts with 'http://'.

>>>




More information about the Tutor mailing list