如何从函数外部获取函数参数和值?

时间:2011-04-14 19:17:09

标签: python

我已经搜索了一下,试图找出这个,但没有得到我正在寻找的解决方案。

这是我的用例:

  • 我想根据f / m的参数和值来计算函数/方法doc-string中的表达式,但是从函数外部(在被调用时但在函数外部执行
  • 我无法静态更改我正在评估的源代码(无法写入新功能),但动态更改(即在运行时包装函数或添加属性)是可以接受的
  • 我更喜欢在标准库中使用工具,但是如果能够轻松完成任务,我愿意尝试使用外部库

以下是我想要做的一个简单示例:

def f1(a,b):
    """a==b"""
    pass

def f2(f):
    f_locals = "get f's args and values before f is executed"
    return eval(f.__doc__,None,f_locals)

>>> f2(f1(2,2))

2 个答案:

答案 0 :(得分:3)

虽然我不知道您为什么要这样做,但您使用inspect模块可以实现您所描述的内容。这个例子与我能提出的原始示例非常接近。

from inspect import getcallargs
def f1(a,b):
   """a==b"""
   pass

def f2(f, *f_args, **f_kwargs):
    f_callargs = getcallargs(f, *f_args, **f_kwargs)
    return eval(f.__doc__, None, f_callargs)

f2(f1, 2, 2)

这应输出True

请记住,这假定了传递给f2的任何此类函数的参数和文档字符串的很多内容,其中最重要的是没有一个被检查的函数是恶意的或格式错误的。你为什么不想正常调用函数,为什么不想改变函数?

修改:正如Pajton指出的那样,getcallargs更合适,并删除了对dictzip的调用。上面的代码已经更新,以反映这一点。

答案 1 :(得分:1)

我不确定这是否是你要找的,但这里有一个没有检查模块的替代方案。

#!/usr/bin/python
# -*- coding: utf-8-unix -*-
"""
This is a sample implementation of Inline.pm (Perl) in Python.

Using @inline decorator, it is now possible to write any code
in any language in docstring, and let it compile down to executable
Python code at runtime.

For this specific example, it simply evals input docstring, so
code in docstring must be in Python as well.
"""

# Language compiler for MyLang
class MyLang:
    @classmethod
    def compile(self, docstring):
        # For this example, this simply generates code that
        # evals docstring.
        def testfunc(*arg, **kw):
            return eval(docstring, None, kw)
        return testfunc

# @inline decorator
def inline(lang):
    def decorate(func):
        parm = func.__code__.co_varnames[0:func.__code__.co_argcount]
        fgen = lang.compile(func.__doc__)
        def wrap(*arg, **kw):
            # turn all args into keyword-args
            kw.update(dict(zip(parm, arg)))
            return fgen(**kw)
        return wrap
    return decorate

@inline(MyLang)
def myadd(a, b):
    """a + b"""

print(myadd(1, 9))
print(myadd(b = 8, a = 2))
print(myadd(a = 3, b = 7))