开发者

How to get a functions arguments and values from outside the function?

开发者 https://www.devze.com 2023-02-25 09:36 出处:网络
I have searched a little bit to try to figure this one out but didn\'t get a solution that I was exactly looking for.

I have searched a little bit to try to figure this one out but didn't get a solution that I was exactly looking for.

This is my use case:

  • I would like to evaluate expressions from a functions/methods doc-string against the f/m's parameters and values, but from outside the function (when being called but outside execution of the function
  • I can't statically change the source code I am evaluating (cant write in new functionality) 开发者_运维知识库but dynamically changing (i.e. wrapping the function or adding attributes at run-time) is acceptable
  • I would prefer to stick with tools in the standard library but am willing to try external libraries if it will make the task a breeze

Here is a simple example of what I am trying to do:

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))


While I have no clue why you would want to do this, what you've described can be achieved with the inspect module. This example is as close to your original example that I can come up with.

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)

This should output True.

Keep in mind that this assumes a great many things about the arguments and docstrings of any such functions passed to f2, not the least of which is that none of the examined functions are malicious or malformed. Why don't you want to call functions normally, and why don't you want to change functions?

Edit: As Pajton pointed out, getcallargs is more appropriate here, and removes the calls to both dict and zip. The above code has been updated to reflect this.


I'm not sure if this is what you are looking for, but here's an alternative without inspect module.

#!/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))
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号