Why doesn't string.Formatter.format have a "self" parameter?

Viewed 262

When reading the source code of the string module of python, I am confused by the class Formatter.

The format method (not static nor class method) in the Formatter class does NOT have self as input parameter def format(*args, **kwargs):, but somehow use it directly within the method. self, *args = args.

Please explain this usage.

class Formatter:
    def format(*args, **kwargs):
        if not args:
            raise TypeError("descriptor 'format' of 'Formatter' object "
                            "needs an argument")
        self, *args = args  # allow the "self" keyword be passed
        try:
            format_string, *args = args # allow the "format_string" keyword be passed
        except ValueError:
            if 'format_string' in kwargs:
                ...
            else:
                ...
        return self.vformat(format_string, args, kwargs)
2 Answers

self is assumed to be the first arg in *args, and unpacked in this line:

self, *args = args

Declaring an instance method without self in the signature is unusual in Python.

By looking at the git history for the method signature line we can see that originally self was present.

It was removed because its presence caused an error if the format string contained a variable named self, for example 'I am my{self}'. The unusual pattern of unpacking self from args was introduced to fix the bug.

The bug report and discussion is here.

This is an example of the error, from the bug report:

>>> string.Formatter().format('the self is {self}', self='bozo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: format() got multiple values for argument 'self'

I assume you are familiar with the *args syntax in the argument. This is just an arbitrary list of unnamed arguments. Then you have

self, *args = args  # allow the "self" keyword be passed

That comment is pretty explicit. Your are splitting args, which is a list, into a first element (which we usually call self, but is just a regular argument, always the first one in an object method), and the rest. Thus, we read self, and all is well - not immediately, but in the function.

The only use case I can see here is from

if not args:
        raise TypeError("descriptor 'format' of 'Formatter' object "
                        "needs an argument")

This means we are expecting to do stuff like

Formatter.format(formatterObj,format_string,...)

a lot (not sure why, something like a factory?), so in case we forget to send the self - formatterObj in my example, we get a verbose error. Possibly to support Formatter like objects that do not have a format method, but do have a vformat method. Seems rather unlikely though.

Related