If you think about it, in addition to the fact that unpacking variable arguments is unpacked immediately, there is the fact that format does not necessarily accept its arguments in the order, as in '{2} {1} {0}' .
You can get around this if format just took the sequence, rather than requiring separate arguments, by building a sequence that does the right thing. Here's a trivial example:
class DefaultList(list): def __getitem__(self, idx): try: return super(DefaultList, self).__getitem__(idx) except IndexError: return '-'
Of course, your real version will wrap an arbitrary iterable, not a subclass of list , and you may have to use tee or the internal cache and pull out new values โโon request, only by default when you get past the end. (You might want to find the โlazy listโ or โlazy sequenceโ recipes in ActiveState because there are some that do this.) But that's enough to show this example.
Now how does this help us? This is not true; *lst on a DefaultList will simply try to make a tuple of the thing, giving us exactly the same number of arguments that we already had. But what if you had a version of format that could just take a sequence of arguments instead? Then you can just pass your DefaultList and it will work.
And you have this: Formatter.vformat .
>>> string.Formatter().vformat('{0} {1} {2}', DefaultList([0, 1]), {}) '0 1 -'
However, there is an even simpler way if you use Formatter explicitly instead of implicitly using the str method. You can simply override its get_value method and / or its check_unused_args :
class DefaultFormatter(string.Formatter): def __init__(self, default): self.default = default
Of course, you still have to wrap your iterator in what the Sequence protocol provides.
While we are in this, your problem can be solved more directly if the language has a "iterable unpacking" protocol. See here for a python stream of ideas suggesting such a thing and all the problems that this idea has. (Also note that the format function would make this more complicated, because it would have to use the decompression protocol directly, rather than relying on the interpreter to do it magically. But assuming this is the case, then you just need to write a very simple and universal wrapper around any iterable that handles __unpack__ for it.)