2012-09-20 50 views
1

在Python中我可以創建一個類無類聲明:合成功能

MyClass = type('X', (object,), dict(a=1)) 

有沒有一種方法來創建無「高清」的功能? 那隻要我有...

d={} # func from string 
exec'''\ 
def synthetics(s): 
    return s*s+1 
''' in d 

>>> d.keys() 
['__builtins__', 'synthetics'] 
>>> d['synthetics'] 
<function synthetics at 0x00D09E70> 
>>> foo = d['synthetics'] 
>>> foo(1) 
2 
+2

'lambda'函數? – eumiro

+0

@ eumiro - :)我期待更多的解決方法,但不錯的選擇。 – root

+3

但是在lambda表達式中,你不能有賦值語句或'print'語句等。 – Kevin

回答

5

技術上,是的,這是可能的。該類型的函數的是,像所有其他類型,該類型的實例構造函數:

FunctionType = type(lambda: 0) 
help(FunctionType) 

你可以從幫助看,你需要最少的代碼和全局。前者是一個編譯的字節碼對象;後者是一本字典。

爲了使代碼的對象,你可以使用代碼類型的構造函數:

CodeType = type((lambda: 0).func_code) 
help(CodeType) 

幫助說,這是「不爲微弱的心臟」這是真的。您需要將字節碼和其他一些東西傳遞給此構造函數。因此,獲取代碼對象的最簡單方法是使用另一個函數,或使用compile()函數。但它技術上可以完全合成生成代碼對象,如果你理解Python字節碼就夠了。 (我已經這樣做了,非常有限的基礎上,構建簽名保留包裝函數用於裝飾用途。)

PS - FunctionTypeCodeType也可通過types模塊可用。

1

有可能比下面更直接的方式,但這裏沒有def一個全面的功能。首先,使用一個簡單的lambda表達式得到一個功能對象:

>>> func = lambda: None 

然後,compile一些源代碼來獲得一個代碼對象並用它來替代lambda的代碼:

>>> func.__code__ = compile("print('Hello, world!')", "<no file>", "exec") 
>>> func() 
Hello, world! 
+0

@ larsmans - +1 – root

+1

函數類型也是:'func = types.FunctionType(compile(...),globals( ))' –