簡體   English   中英

Python:如何將 arguments 傳遞給 function 的 __code__?

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

以下作品:

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

垃圾郵件

但是如果spam占用 arguments 怎么辦?

def spam(eggs):
    print "spam and", eggs
exec(spam.__code__)

TypeError: spam() 只接受 1 個參數(給定 0)

鑒於,我無法訪問 function 本身,而只能訪問代碼 object,我如何在執行時將 arguments 傳遞給代碼 object? eval可以嗎?

編輯:由於大多數讀者傾向於不相信它的有用性,請參閱以下用例:

我想將小的 Python 函數保存到文件中,以便可以從另一台計算機調用它們。 (這里不用說,這個用例嚴重限制了可能的功能。)酸洗 function object 本身不能工作,因為這只會保存名稱和定義 ZC1C425268E68385D1AB5074C1ZA 的模塊。 相反,我可以腌制__code__的 __code__。 當我再次解開它時,對 function 的引用當然消失了,這就是為什么我不能調用 function 的原因。 我只是在運行時沒有它。

另一個用例:

我在一個文件中處理多個函數,這些函數計算一些數據並將其存儲在硬盤上。 計算消耗大量時間,所以我不想每次都執行這些函數,但只有在 function 的實現發生變化時才執行。

我有一個針對整個模塊而不是 function 運行的版本。 它通過查看實現模塊的文件的修改時間來工作。但如果我有許多不想在單個文件中分離的功能,這不是一個選項。

我完全反對使用 __code__。

盡管我是一個好奇的人,但理論上有人可以這樣做:

code # This is your code object that you want to execute

def new_func(eggs): pass
new_func.__code__ = code
new_func('eggs')

再說一次,我永遠不想看到這個被使用。 如果您想在運行時加載代碼,您可能需要查看__import__

你能把 function 改成帶任何 arguments 嗎? 然后從可以提供給exec的 locals/globals 中查找變量:

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

(為什么不把整個 function 作為字符串發送?pickle "def spam(eggs): print 'spam and', eggs" ,然后在另一邊exec字符串(驗證后)。)

我認為在您的大型應用程序中可能有一些設計考慮因素可能使您不關心這個問題,例如可能將一些“已知良好且有效”的函數集合作為執行代理知道的模塊分發或其他東西。

也就是說,一個 hacky 解決方案是:

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

代碼 object 是 function 的一部分,因此上面的幾個答案建議創建一個虛擬 function 並將其__code__替換為您的codeObject 這是避免制作和丟棄新的__code__的另一種方法:

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

(在 Python 2.7 中測試,其中spam.__code__被命名為spam.func_code 。)

我的方法,我覺得它更漂亮

def f(x):
    print(x, x+1)

g = type(f)(f.__code__, globals(), "optional_name")

g(3)

我認為您不能將 arguments 傳遞給execeval ,以便將它們傳遞給代碼 object。

您可以使用 exec/eval 的字符串版本,例如exec("spam(3)")

您可以創建另一個綁定參數的代碼 object,然后執行:

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

(我認為您也可以使用functools.partial來實現這一點,但沒有讓它發揮作用)。

編輯:

在閱讀了您的其他解釋后,我想到了從代碼 object 重新建立正確的 function 的方法。 這種簡單的方法對我有用(在 python2.5 中):

def bar():pass
bar.func_code = spam.func_code
bar(3)  # yields "spam and 3"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM