我想动态设置实例方法的默认键参数。例如,使用
class Module(object):
def __init__(self, **kargs):
set-default-key-args-of-method(self.run, kargs) # change run arguments
def run(self, **kargs):
print kargs
我们会:
m = Module(ans=42)
m.run.im_func.func_code.co_argcount # => 2
m.run.im_func.func_code.co_varnames # => ('self','ans','kargs')
m.run.im_func.func_defaults # => (42,)
m.run() # print {'ans':42}
我尝试了一些带有types.CodeType(我真的不懂)的函数(不是一个方法)并让它工作(很好 not-to-fail ),但是添加的键参数没有显示在函数的kargs字典中(它只打印{})
必须仅对当前实例进行更改。实际上,我现在正在使用一个类(我在脑海中是我的OO)所以我想用类方法来做,但函数可能更好。类似的东西:
def wrapped_run(**kargs):
def run(**key_args):
print key_args
return wrap-the-run-function(run, kargs)
run = wrapped_run(ans=42)
run.func_code.co_argcount # => 1
run.func_code.co_varnames # => ('ans','key_args') ## keep the 'key_args' or not
run.func_defaults # => (42,)
run() # print {'ans':42}
欢迎任何建议或想法。
关于上下文的一点:
Module类是一种函数包装器,可用于自动包含数据流系统中的低端函数,但添加中间过程。我希望模块运行函数(实际上,它可能是它的__call___函数)拥有正确的API,以便数据流系统能够透明地生成正确的模块输入。
我正在使用python 2.7
答案 0 :(得分:2)
kwargs
是一本字典,我们需要做的就是保存以供日后使用。然后用户可以用它们的值覆盖它。
class Module(object):
def __init__(self, **kwargs):
self.defaults = kwargs
def run(**kwargs):
values = dict(self.defaults.items() + kwargs.items())
print values
修改强>
您是否正在寻找lambda
函数生成?
def wrapfunc(**kwargs):
def run(kwargs):
print kwargs
return lambda x: run(dict(kwargs.items() + x.items()))
run = wrapfunc(ans=42)
run({})
run({'ans':12})
答案 1 :(得分:2)
你可能正在寻找这样的东西:
class Module(object):
def __init__(self, **kargs):
old_run = self.run.im_func
def run(self,**kwargs):
kargs_local = kargs.copy()
kargs.update(kwargs)
return old_run(self,**kargs)
self.run = run.__get__(self,Module)
def run(self,**kargs):
print kargs
m1 = Module(foo=3,bar='baz')
m1.run()
print type(m1.run)
m2 = Module(foo=4,qux='bazooka')
m2.run()
print type(m2.run)
我刚刚在上一个函数周围创建了一个包装器实例方法。 (部分受this post启发)。
可替换地:
from functools import partial
from types import MethodType
class Module(object):
def __init__(self, **kargs):
self.run = MethodType(partial(self.run.im_func,**kargs),self,Module)
def run(self,**kargs):
print kargs
但是这仍然不能提供您正在寻找的API ......
答案 2 :(得分:0)
这听起来不是一个好主意。不要使用函数签名,最好将一组默认值定义为实例变量,并在函数中使用它:
class Module(object):
def __init__(self, **kwargs):
self.run_defaults = kwargs
def run(self, **kwargs):
actual_values = self.run_defaults.copy()
actual_values.update(kwargs)
print actual_values
答案 3 :(得分:0)
为了关闭,我给出了唯一找到的解决方案:使用exec
(由 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()
example
功能打印:
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'}
然而:
repr