Python string formatting

I recently did a lot of music programming, and as such, I do such things to deal with the missing metadata in some songs:

default = {'title': 'Unknown title', 'artist': 'unknown Artist'}
default.update(song)
print '{title} - {artist}'.format(**default)

Is there a cleaner way to do this? I tried overriding __missing__ like this, but missing keys still throw a KeyError:

class Song(dict):
    # dictionary with some nice stuff to make it nicer

    def __missing__(self, key):
        return 'Unknown {key}'.format(key = key)

Edit: Sorry, I should have been more clear, basically this should work.

s = Song()
print '{notAKey}'.format(s)

Several people indicated that ** are not needed.

Edit 2: I “solved” my problem, at least until I was satisfied. Whether it is debatable or not cleaner, but it works for me.

from string import Formatter

class DefaultFormatter(Formatter):

    def get_value(self, key, args, kwargs):
        # Try standard formatting, then return 'unknown key'

        try:
            return Formatter.get_value(self, key, args, kwargs)
        except KeyError:
            return kwargs.get(key, 'Unknown {0}'.format(key))

class Song(dict):

    def format(self, formatString):
        # Convenience method, create a DefaultFormatter and use it

        f = DefaultFormatter()
        return f.format(formatString, **self)

So the following will be returned "Unknown notAKey"

k = Song()
print k.format('{notAKey}')
+5
source share
5 answers

: .

, , . , , dict.

, , , . , , . , , .

, , , .

+6

. '{title} - {artist}'.format(**default)

defaultdict collections?

from collections import defaultdict

class Song(defaultdict):
    def __missing__(self, key):
        return 'Unknown {key}'.format(key = key)

: python, , , , KeyError?:

+3

, **foo, foo dict. - , , , .

+1

Jared, , :

>>> class Song(dict):
...     def __getitem__(self, key):
...             if key in self.keys(): return super(Song, self).__getitem__(key)
...             return 'Unknown {key}'.format(key=key)
... 
>>> s = Song()
>>> s['foo']
'Unknown foo'
>>> s['foo'] = 1
>>> s['foo']
1
-1

Well, one option that I can think of is to use a method that can provide you with default values ​​by default, namely getattr. If you convert your dict to an object that turns keys into attributes, you can use safe getattrto get values:

class AttributeDict(): 
    def __init__(self, source_dict):
        self._ATTRIBUTE_DICT_source_dict = source_dict
        for key in source_dict.keys():
            setattr(self, str(key), source_dict[key])

Now you can simply use:

song = AttributeDict(song)
artist = getattr(song, 'artist', 'Unknown Artist')
-1
source

All Articles