473,661 Members | 2,431 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

expanding dictionary to function arguments

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.

# Example 1 - This works:
# Prints "hello world!"
def foo (arg1='greeting s', arg2='planet', arg3='.'):
print arg1 + ' ' + arg2 + arg3
args = {'arg1':'hello' , 'arg2':'world', 'arg3':'!'}
foo (**args)

# Example 2 - This does not work:
# raises TypeError: foo() got an unexpected keyword argument 'arg4')
def foo (arg1='greeting s', arg2='planet', arg3='.'):
print arg1 + ' ' + arg2 + arg3
args = {'arg1':'hello' , 'arg2':'world', 'arg3':'!', 'arg4':'ignore' }
foo (**args)

As a practical application, I have a project where I have a config file

that defines a large number of keys and values. I read the config
file into a dictionary called "options". I also have an API module with
many
functions that I want to call with arguments taken directly from the
"options" dictionary. The key names in the "options" dictionary match
the argument names of the functions in my API.

# The ugly, brutish way:
options = read_config ("options.conf" )
extract_audio (options['source_video_f ilename'])
compress_audio (options['audio_raw_file name'],
options['audio_compress ed_filename'], options['audio_sample_r ate'],
options['audio_bitrate'])
mux (options['source_video_f ilename'],
options['audio_compress ed_filename'], options['output_video_f ilename'])

I know that the keys in my "options" dictionary match the arguments
of the functions in the API library, so I would like to do this:
options = read_config ("options.conf" )
extract_audio (**options)
compress_audio (**options)
mux (**options)

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.
"""
if hasattr(func,'i m_func'): # Handle case when func is a class
method.
func = func.im_func
argcount = func.func_code. co_argcount
required_args = dict([(k,args.get(k)) for k in
func.func_code. co_varnames[:argcount]])
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?

Yours,
Noah

Nov 2 '05 #1
4 3351
Noah a écrit :
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.


If you have control over the API functions declarations, makes them so:

def my_api_func(arg 1='', arg2='whatever' , **kwargs):
code_here

Nov 2 '05 #2

Bruno Desthuilliers a écrit :
Noah a écrit :
If you have control over the API functions declarations, makes them so:
def my_api_func(arg 1='', arg2='whatever' , **kwargs):
code_here


Unfortunately I cannot change the API functions.
I should have mentioned that.

Yours,
Noah

Nov 2 '05 #3
Noah wrote:
Bruno Desthuilliers a écrit :
Noah a écrit :
If you have control over the API functions declarations, makes them so:
def my_api_func(arg 1='', arg2='whatever' , **kwargs):
code_here

Unfortunately I cannot change the API functions.
I should have mentioned that.


Yeps... That what I thought, but you didn't mention it, and it was not
that clear (or it's me being stupid...).

I'm no great expert, but apart from writing a generic decorator for the
API objects and decorating them all with your smart_apply function -
which won't by you much in this case imho -, I don't see a much better
solution...

Some guru around ???

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom. gro'.split('@')])"
Nov 2 '05 #4
On 1 Nov 2005 17:17:00 -0800, "Noah" <no**@noah.or g> 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,'i m_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:argcou nt]]
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_a rgcount]
ndefaults = len(func.func_d efaults 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.appe nd(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(*actualarg s)
_f.func_name = func.func_name
return _f
and then wrap like

extract_audio = call_with_args_ from_dict(extra ct_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
Nov 2 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
1894
by: Jack Carter | last post by:
I have been delegated to produce a tool that has python embedded in it. The desire is to have a command line interface that inherits all the python scripting functionality so people can use the tool either with a flat commandline entry like you would a debugger or with a script using scoping, loops and conditional. I am going from knowing nothing about python to almost nothing so the learning curve is rather
15
2978
by: Stefan Behnel | last post by:
Hi! I'm trying to do this in Py2.4b1: ------------------------------- import logging values = {'test':'bla'} logging.log(logging.FATAL, 'Test is %(test)s', values) -------------------------------
125
7155
by: Raymond Hettinger | last post by:
I would like to get everyone's thoughts on two new dictionary methods: def count(self, value, qty=1): try: self += qty except KeyError: self = qty def appendlist(self, key, *values): try:
16
1702
by: David Bear | last post by:
I know there must be a better way to phrase this so google understands, but I don't know how.. So I'll ask people. Assume I have a list object called 'alist'. Is there an easy way to create a dictionary object with the members of 'alist' being the keys in the dictionary, and the value of the keys set to null? --
8
1347
by: s99999999s2003 | last post by:
hi i have a dictionary defined as execfunc = { 'key1' : func1 } to call func1, i simply have to write execfunc . but if i have several arguments to func1 , like execfunc = { 'key1' : func1(**args) }
2
1813
by: Noah | last post by:
Is there a simple way to get a dictionary of argument names and their default values for a method or function? I came up with one solution, but I feel like Python must have a simpler way. Python provide a way to get a sequence of argument names and a different way to get a sequence of default argument values. Since default values have to come at the end of an argument list you can match up the values in the
4
1508
by: 63q2o4i02 | last post by:
Hi, I'm writing a hand-written recursive decent parser for SPICE syntax parsing. In one case I have one function that handles a bunch of similar cases (you pass the name and the number of tokens you're looking for). In another case I have a function that handles a different set of tokens and so it can't use the same arguments as the first one, and in fact takes no arguments. However, these functions are semantically similar and are...
36
3795
by: James Harris | last post by:
Initial issue: read in an arbitrary-length piece of text. Perceived issue: handle variable-length data The code below is a suggestion for implementing a variable length buffer that could be used to read text or handle arrays of arbitrary length. I don't have the expertise in C of many folks here so I feel like I'm offering a small furry animal for sacrifice to a big armour plated one... but will offer it anyway. Please do suggest...
0
2301
by: James Mills | last post by:
On Fri, Oct 31, 2008 at 8:49 AM, mark floyd <emfloyd2@gmail.comwrote: Mark, this is correct behavior. You have 3 positional arguments in the function definition. You _must_ aupply _all_ 3 of them. If you wish for b to be optional, then you must give it a default value. def foo(a, b=None, c=None): print a
0
8855
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8758
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8545
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7364
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5653
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4179
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4346
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2762
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1743
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.