Question: How to make `format(self)` work in this case?

```
class Commit:
    number = None
    sha = None
    message = None
    identity = None

    def __init__(self, raw, number):
        r = raw.commits[number]

        self.number = number
        self.sha = r['sha']
        self.message = r['message']
        self.identity = raw.identities[r['identity']]

    def __str__(self):
        return """
Commit {number} {sha}
Message {message}
Identity {identity}
""".format(self)

    def __getitem__(self, attr):
        return getattr(self, attr)
    def __contains__(self, attr):
        return hasattr(self, attr)

```

If I then try to access individual attributes as

```
c = Commit(raw, 170)
print(c['sha'])

```

for instance, it works. However, if I `print(c)` directly, it says:

> 
> KeyError: 'number'
> 
> 
> 

I would have expected `format()` to pull the attributes it needs via `__getitem__()`.

How to make it work?

Answer: 
No, you'd have to use `**self` and support more mapping methods.

However, you'd be much better off using the format support for attribute access instead:

```
    def __str__(self):
        return """
Commit {0.number} {0.sha}
Message {0.message}
Identity {0.identity}
""".format(self)

```

Now it'll use attribute access to find `number`, `message`, etc. from the first positional argument to `.format()`, which is `self`.
You have a `self.number`, but want to access a `self['number']`. This is distinct...

Try `{0.number}` instead...