Python: How to pass arguments to the __code__ of a function?

前端 未结 6 433
别那么骄傲
别那么骄傲 2020-12-02 20:55

The following works:

def spam():
    print \"spam\"
exec(spam.__code__)

spam

But what if spam

相关标签:
6条回答
  • 2020-12-02 21:25

    I am completely against this use of __code__.

    Although I am a curious person, and this is what someone theoretically could do:

    code # This is your code object that you want to execute
    
    def new_func(eggs): pass
    new_func.__code__ = code
    new_func('eggs')
    

    Again, I never want to see this used, ever. You might want to look into __import__ if you want to load code during run-time.

    0 讨论(0)
  • 2020-12-02 21:25

    I think there are probably some design considerations in your larger application that could make you not care about this problem, like perhaps having some collection of 'known good and valid' functions distributed as a module that the executing agents know about or something.

    That said, one hacky solution would be:

    >>> def spam(eggs):
    ...     print "spam and %s" % eggs
    ...     
    ... 
    >>> spam('bacon')
    spam and bacon
    >>> def util():
    ...     pass
    ...     
    ... 
    >>> util.__code__ = spam.__code__
    >>> util('bacon')
    spam and bacon
    >>> 
    
    0 讨论(0)
  • 2020-12-02 21:32

    My method, I thing it`s more beautiful

    def f(x):
        print(x, x+1)
    
    g = type(f)(f.__code__, globals(), "optional_name")
    
    g(3)
    
    0 讨论(0)
  • 2020-12-02 21:32

    I don't think you can pass arguments to either exec or eval, so that they are passed to the code object.

    You could resort to the string version of exec/eval, e.g. exec("spam(3)").

    You could create another code object that binds the argument, and then exec this:

    def spam_with_eggs():
       return spam(3)
    exec(spam_with_eggs.__code__)
    

    (I thought you could also achieve this with functools.partial, but didn't get it to work).

    EDIT:

    After reading your additional explanations I thought of ways to re-establish a proper function from the code object. This simple approach worked for me (in python2.5):

    def bar():pass
    bar.func_code = spam.func_code
    bar(3)  # yields "spam and 3"
    
    0 讨论(0)
  • 2020-12-02 21:33

    A code object is part of a function, so several answers above suggest creating a dummy function and replacing its __code__ with your codeObject. Here's another way that avoids making and throwing away a new __code__:

    import new
    newFunction = new.function(codeObject, globals())
    

    (Tested in Python 2.7, where spam.__code__ is named spam.func_code.)

    0 讨论(0)
  • 2020-12-02 21:41

    Can you change the function to not take any arguments? The variables is then looked up from the locals/globals where you can supply into exec:

    >>> def spam():
    ...   print "spam and", eggs
    ... 
    >>> exec(spam.__code__, {'eggs':'pasta'})
    spam and pasta
    

    (Why not just send the whole function as a string? Pickle "def spam(eggs): print 'spam and', eggs", and exec the string (after verification) on the other side.)

    0 讨论(0)
提交回复
热议问题