更改函数参数列表

时间:2016-10-30 09:15:48

标签: python

我有以下功能:

def f(x, y):
    print('x: %s' % x)
    print('y: %s' % y)

我希望有一个包装器,如:

def g(**kwargs):
    print('hello')
    f(**kwargs)
    print('world')

包装器g是装饰器将返回的函数,因此它不能完全调用f函数,而是调用具有任何参数列表的任何函数,因此这对于提供函数{ {1}} f

在定义**kwargs函数之后,我想返回g函数,但是从g函数复制了参数列表,并且名称为f函数。我在下面试过这个:

f

但是在调用import types f_code = f.__code__ g_code = g.__code__ g.__code__ = types.CodeType( f_code.co_argcount, g_code.co_nlocals, g_code.co_stacksize, g_code.co_flags, g_code.co_code, g_code.co_consts, g_code.co_names, f_code.co_varnames, g_code.co_filename, f_code.co_name, g_code.co_firstlineno, g_code.co_lnotab, g_code.co_freevars, g_code.co_cellvars ) 函数后,我得到了分段错误。

我用谷歌搜索了如何以更高层次的方式解决这个问题,但我没有满足任何解决方案。我尝试了g,但它没有更改参数列表,我尝试@functools.wraps但它根本没有调用装饰器功能。也许你知道更好的解决方案吗?

更新

基本上下面有更多扩展示例:

@decorator.decorator

运行此程序失败,错误如下:

funcs = {}

def h(fi, *args, **kwargs):
    def g(*args, **kwargs):
        print('hello')
        result = fi(**kwargs)
        print('world')
        return result
    funcs[fi.func_code.co_name] = g
    return g

@h
def f(x, y):
    print('%s %s' % (x, y))
    return 5

# z index is unneeded, so should be filtered
extended_arguments = {'x': 1, 'y': 2, 'z': 3}

func = funcs['f']
func_code = func.func_code
arguments = {
    i: x for i, x in extended_arguments.items()
    if x in func_code.co_varnames[:func_code.co_argcount]
}
func(**arguments)

这是我想要实施的确切案例。

尝试使用exec:

hello
Traceback (most recent call last):
  File "x.py", line 26, in <module>
    func(**arguments)
  File "x.py", line 6, in g
    result = fi(**kwargs)
TypeError: f() takes exactly 2 arguments (0 given)

产生以下错误:

funcs = {}

def h(fi, *args, **kwargs):
    fi_code = fi.func_code
    exec(
        '''
def g(%s*args, **kwargs):
    print('hello')
    result = fi(**kwargs)
    print('world')
    return result
        ''' % ''.join(
            '%s, ' % varname
            for varname in fi_code.co_varnames[:fi_code.co_argcount]
        )
    )
    funcs[fi_code.co_name] = g
    return g

@h
def f(x, y):
    print('%s %s' % (x, y))
    return 5

# z index is unneeded, so should be filtered
extended_arguments = {'x': 1, 'y': 2, 'z': 3}

func = funcs['f']
func_code = func.func_code
arguments = {
    i: x for i, x in extended_arguments.items()
    if i in func_code.co_varnames[:func_code.co_argcount]
}
func(**arguments)

0 个答案:

没有答案