动态地向方法添加关键参数

Juh*_*uh_ 7 python methods dynamic named-parameters

我想动态设置实例方法的默认键参数。例如,与

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
Run Code Online (Sandbox Code Playgroud)

我们会有:

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}
Run Code Online (Sandbox Code Playgroud)

我尝试了一些带有 types.CodeType(我不太了解)的函数(不是方法)并让它工作(很好不会失败),但是添加的键参数没有显示在 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}
Run Code Online (Sandbox Code Playgroud)

欢迎任何建议或想法。

关于上下文的一点:

Module 类是某种函数包装器,可用于自动将低端函数包含在数据流系统中,但添加中间过程。我希望模块运行函数(实际上,它可能是 __call___ 函数)具有正确的 API,以便数据流系统能够很好地透明地生成正确的模块输入。

我正在使用 python 2.7

Juh*_*uh_ 1

为了结束,我给出了找到的唯一解决方案:使用(由mgilsonexec 提出)

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()
Run Code Online (Sandbox Code Playgroud)

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'}
Run Code Online (Sandbox Code Playgroud)

然而:

  • 如果参数值不能很好地代表它们,则可能会出现问题repr
  • 我认为它太复杂了(因此不是Pythonic),而且我个人没有使用它