On 1 Nov 2005 17:17:00 -0800, "Noah" <[EMAIL PROTECTED]> wrote:
>I have a dictionary that I would like to expand to satisfy a >function's agument list. I can used the ** syntax to pass a dictionary, >but >this only works if each key in the dictionary matches an argument. >I cannot pass a dictionary that has more keys than the function has >arguments. [...] >I created the following function to do what I am describing. >This isn't too bad, but I thought that perhaps there was some >secret Python syntax that will do this for me. > >def apply_smart (func, args): > """This is similar to func(**args), but this won't complain about > extra keys in 'args'. This ignores keys in 'args' that are > not required by 'func'. This passes None to arguments that are > not defined in 'args'. That's fine for arguments with a default >valeue, but > that's a bug for required arguments. I should probably raise a >TypeError. > """ Ok, so why not do it? ;-) > if hasattr(func,'im_func'): # Handle case when func is a class >method. > func = func.im_func skipself = True else: skipself = False > argcount = func.func_code.co_argcount Make arg list and call with it instead of > required_args = dict([(k,args.get(k)) for k in >func.func_code.co_varnames[:argcount]]) > return func(**required_args) try: required_args = [args[k] for k in func.func_code.co_varnames[skipself:argcount]] except KeyError: raise TypeError, '%s(...) missing arg %r'%(func.func_name, k) return func(*required_args) > >So, I now I can do this: > options = read_config ("options.conf") > apply_smart (extract_audio, options) > apply_smart (compress_audio, options) > apply_smart (mux, options) > >Neat, but is that the best I can do? > I suppose you could replace your local bindings of extract_audio, compress_audio, and mux with wrapper functions of the same name that could cache the func and arg names in closure variables, e.g., using a decorator function (virtually untested) def call_with_args_from_dict(func): argnames = func.func_code.co_varnames[hasattr(func, 'im_func'):func.func_code.co_argcount] ndefaults = len(func.func_defaults or ()) if ndefaults: defnames = argnames[-ndefaults:] argnames = argnames[:-ndefaults] else: defnames = [] def _f(**args): try: actualargs = [args[argname] for argname in argnames] for argname in defnames: if argname not in args: break actualargs.append(args[argname]) except KeyError: raise TypeError, '%s(...) missing arg(s) %r'%( func.func_name, [argname for argname in argnames if argname not in args]) return func(*actualargs) _f.func_name = func.func_name return _f and then wrap like extract_audio = call_with_args_from_dict(extract_audio) or use as a decorator if you are defining the function to be wrapped, e.g., @call_with_args_from_dict def mux(firstarg, second, etc): ... Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list