print 'Hello %s %s' % (first, last)
hello(last='Lecocq', first='Dan')
In fact, you can programmatically gain insight into functions with the inspect module. But suppose you want to be able to accept an arbitrary number ofparameters. For example, for a printf equivalent. Or where I encountered it in wanting to read a module name from a configuration file, as wellas the arguments to instantiate it. In this case, you’d get the moduleand class as a string and then a dictionary of the arguments to make aninstance of it. Of course, Python always has a way. In this case,**kwargs.
This is actually dictionary unpacking, taking all the keys in adictionary and mapping them to argument names. For example, in the above example, I could say:
Of course, in that case it’s a little verbose, but if you’re getting a dictionary of arguments programmatically, then it’s invaluable. Butwait, there’s more! Not only can you use the **dict operator to map adictionary into parameters, but you can accept arbitrary parameters with it, too!
for key, value in kwargs.items():
print '%s => %s' % (key, value)
kw(**{'hello':'Howdy!', 'first':'Dan'})
kw(hello='Howdy!', first='Dan')
Magic! No matter how you invoke the function, it has access to the parameters. You can even split the difference, making some parameters named andsome parameters variable. For example, if you wanted to create aninstance of a class that you passed a name in for, initialized with thearguments you give it:
# The built-in __import__ does just what it sounds like
m = __import__(module)
# Now get the class in that module
c = getattr(m, cls)
# Now make an instance of it, given the args
return c(**kwargs)
factory('datetime', 'datetime', year=2011, month=11, day=8)
factory('decimal', 'Decimal', value=7)
This is one place where Python’s flexibility is extremely useful.