Jas*_*n S 9 python arguments function
假设我有这个功能:
def f(x,y):
return x+y
Run Code Online (Sandbox Code Playgroud)
如果我使用inspect.getargspec(f).args
我得到['x','y']
的结果.大.
现在假设我想g(a,b)
在运行时创建另一个函数,我不知道参数名称a
,b
直到运行时:
def g(a,b):
return f(a,b)
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?Lambdas几乎是正确的,除了我只能在编译时分配参数名称.
g = lambda *p: f(*p)
Run Code Online (Sandbox Code Playgroud)
不知何故,我想在运行时基于列表L(例如L=['a','b']
)动态创建函数,这样inspect.getargspec(g).args == L
.
这是一种有点hacky的方法,它首先通过修改从现有函数创建一个新函数,然后用它替换原始代码。之所以冗长,主要是因为该types.CodeType()
调用有太多参数。Python 3 版本有些不同,因为许多属性function.func_code
被重命名,并且调用顺序也types.CodeType()
略有改变。
我从 @aaronasterling 的回答中得到了这个想法(他说他是从 Michael Foord 的 Voidspace 博客条目 #583 标题为Selfless Python中得到这个想法的)。它可以很容易地制作成装饰器,但根据您告诉我们的预期用途,我认为这没有帮助。
import sys
import types
def change_func_args(function, new_args):
""" Create a new function with its arguments renamed to new_args. """
if sys.version_info[0] < 3: # Python 2?
code_obj = function.func_code
assert(0 <= len(new_args) <= code_obj.co_argcount)
# The arguments are just the first co_argcount co_varnames.
# Rreplace them with the new argument names in new_args.
new_varnames = tuple(new_args[:code_obj.co_argcount] +
list(code_obj.co_varnames[code_obj.co_argcount:]))
new_code_obj = types.CodeType(code_obj.co_argcount,
code_obj.co_nlocals,
code_obj.co_stacksize,
code_obj.co_flags,
code_obj.co_code,
code_obj.co_consts,
code_obj.co_names,
new_varnames,
code_obj.co_filename,
code_obj.co_name,
code_obj.co_firstlineno,
code_obj.co_lnotab,
code_obj.co_freevars,
code_obj.co_cellvars)
modified = types.FunctionType(new_code_obj, function.func_globals)
else: # Python 3
code_obj = function.__code__
assert(0 <= len(new_args) <= code_obj.co_argcount)
# The arguments are just the first co_argcount co_varnames.
# Replace them with the new argument names in new_args.
new_varnames = tuple(new_args[:code_obj.co_argcount] +
list(code_obj.co_varnames[code_obj.co_argcount:]))
new_code_obj = types.CodeType(code_obj.co_argcount,
code_obj.co_posonlyargcount,
code_obj.co_kwonlyargcount,
code_obj.co_nlocals,
code_obj.co_stacksize,
code_obj.co_flags,
code_obj.co_code,
code_obj.co_consts,
code_obj.co_names,
new_varnames,
code_obj.co_filename,
code_obj.co_name,
code_obj.co_firstlineno,
code_obj.co_lnotab)
modified = types.FunctionType(new_code_obj, function.__globals__)
function.__code__ = modified.__code__ # replace code portion of original
if __name__ == '__main__':
import inspect
def f(x, y):
return x+y
def g(a, b):
return f(a, b)
print('Before:')
print('inspect.getargspec(g).args: {}'.format(inspect.getargspec(g).args))
print('g(1, 2): {}'.format(g(1, 2)))
change_func_args(g, ['p', 'q'])
print('')
print('After:')
print('inspect.getargspec(g).args: {}'.format(inspect.getargspec(g).args))
print('g(1, 2): {}'.format(g(1, 2)))
Run Code Online (Sandbox Code Playgroud)