For the sake of closure, I give the only solution that was found: use exec
(proposed by mgilson)
import os, new
class DynamicKargs(object):
"""
Class that makes a run method with same arguments
as those given to the constructor
"""
def __init__(self, **kargs):
karg_repr = ','.join([str(key)+'='+repr(value) \
for key,value in kargs.iteritems()])
exec 'def run(self,' + karg_repr + ',**kargs):\n return self._run(' + karg_repr + ',**kargs)'
self.run = new.instancemethod(run, self)
def _run(self, **kargs):
print kargs
# this can also be done with a function
def _run(**kargs):
print kargs
def dynamic_kargs(**kargs):
karg_repr = ','.join([str(key)+'='+repr(value) for key,value in kargs.iteritems()])
exec 'def run(' + karg_repr + ',**kargs):\n return _run(' + karg_repr + ',**kargs)'
return run
# example of use
# --------------
def example():
dyn_kargs = DynamicKargs(question='ultimate', answer=42)
print 'Class example \n-------------'
print 'var number:', dyn_kargs.run.im_func.func_code.co_argcount
print 'var names: ', dyn_kargs.run.im_func.func_code.co_varnames
print 'defaults: ', dyn_kargs.run.im_func.func_defaults
print 'run print: ',
dyn_kargs.run()
print ''
dyn_kargs = dynamic_kargs(question='foo', answer='bar')
print 'Function example \n----------------'
print 'var number:', dyn_kargs.func_code.co_argcount
print 'var names: ', dyn_kargs.func_code.co_varnames
print 'defaults: ', dyn_kargs.func_defaults
print 'run print: ',
dyn_kargs()
The example
function prints:
Class example
-------------
var number: 3
var names: ('self', 'answer', 'question', 'kargs')
defaults: (42, 'ultimate')
run print: {'answer': 42, 'question': 'ultimate'}
Function example
----------------
var number: 2
var names: ('answer', 'question', 'kargs')
defaults: ('bar', 'foo')
run print: {'answer': 'bar', 'question': 'foo'}
However:
- there might be problem if arguments value are not well represented by their
repr
- I think it is too complicated (thus not pythonic), and personally, I did not use it