2014-01-05 76 views
1

我正在創建一個名爲pyma的簡單包,可在pypi上獲得。在運行時創建一個動態命名的函數

我提供了一種方法來計算一個名爲NDayEMA(n, data)的函數在N天的指數移動平均線。 (實際上,它是一個名爲NDayEMA的類,具有一個名爲compute()的功能,但在此處無關)。

我試圖在運行時爲用戶創建一個動態命名的函數作爲快捷方式。

例如:

NDayEMA(30, data) 

EMA30(data) 

將是相同的和

EMA23(data) 
EMA1023(data) 
EMA12(data) 

也將是可用的。

我知道我需要一些reg-ex和處理,這在你的答案中是不需要的;我會自己得到它!我正在尋找如何接收用戶提供的函數的名稱,並創建一個具有該名稱的函數,而不會引發錯誤消息。

這是一個來自Laravel PHP framework的PHP等價物。

$user = DB::table('users')->where_email_and_password('[email protected]', 'secret'); 

回答

2

我同意阿里 - 你試圖做的事情並不真正給你帶來任何好處,所以可能不值得去做。

但是,如果您絕對願意,您可以濫用模塊加載/ __getattr__並破解此post中所述的解決方案。

基本上,如果我們有一個名爲foo.py一個文件,該文件是這樣的:

def hello(n): 
    print n 

class NDayEMA(object): 
    def __init__(self, n, day): 
     self.n = n 
     self.day = day 

然後,你需要改變foo.py的內容是這樣的:

import sys 

class Testing(object): 
    @staticmethod 
    def hello(n): 
     print n 

    class NDayEMA(object): 
     def __init__(self, n, day): 
      self.n = n 
      self.day = day 

    def __getattr__(self, attr): 
     if attr.startswith('EMA'): 
      n = int(attr[3:]) 
      return lambda day: self.NDayEMA(n, day) 
     else: 
      raise AttributeError 

sys.modules[__name__] = Testing() 

__getattr__方法在您試圖調用對象內缺少的屬性或方法時調用。但是,不存在可用於模塊的__getattr__函數。因此,我們所要做的就是將模塊轉換成一個類,然後用最後一個類替換模塊。

我們現在可以導入foo並執行以下操作:

import foo 

foo.hello(3) 

a = foo.EMA39('test') 
b = foo.EMA1000('test') 

print a.n 
print b.n 

print 'done' 
6

這並不完全回答你的問題,但我建議不要做你在問什麼。你已經有一個方法將數字和數據作爲參數,所以把數字轉換成不同的方法名稱似乎沒有你當前的方法更方便。

+0

好吧,我明白你的意思。我仍然覺得這個功能對用戶來說非常優雅。它有什麼缺點嗎?或者只是有一些糟糕的工作/價值比例? Laravel如何使用動態命名函數,它不好嗎? – PyWebDesign

+0

缺點是你會使用大量的hacky元編程技術,這可能會減慢你的圖書館,但沒有任何它有時會帶來的好處。 Rails和其他一些框架使用find_by動態方法來做一些奇妙的事情,但這是他們決定做出的一個折衷;他們實際上已經不再那麼做了,因爲它通常會損害可維護性,使文檔查找變得更困難,並且通常比其他等價物慢。 – Ari

相關問題