2014-03-18 56 views
0

我想動態創建與模塊中的函數名稱相關聯的類中的函數。新功能必須能夠調用模塊中的原始功能。但是,在下面的示例代碼中,似乎可能存在內存/唯一性問題,其中創建的函數被覆蓋。我想知道如何解決這個問題。動態python函數創建覆蓋函數def

我有一個文件mymod.py,我將導入爲一個模塊:

def exec_test0(): 
    print "i am exec_test0" 

def exec_test1(): 
    print "i am exec_test1" 

和一個類定義需要讀取模塊文件test.py

import mymod as mm 

class MyClass(): 
    def __init__(self): 
     self.l = [fn for fn in dir(mm) if fn.startswith('exec_')] 
     self.create_method() 

    def create_method(self): 
     # i expect this to create new methods with unique properties 
     # as attributes of an object of this class 
     for fn_exec in self.l: 
      # this is the function template 
      # that i want to call the relevant function from the 
      # module mymod (mm) 
      def method(self): 
       method_to_call = getattr(mm, fn_exec) 
       method_to_call() 

      # this should create a new name based on the fn_exec 
      # and assign method to it 
      name_def = fn_exec.replace('exec_', 'do_') 
      setattr(self.__class__, name_def, method) 

if __name__ == '__main__': 
    my_obj = MyClass() 
    my_obj.do_test0() 
    my_obj.do_test1() 

運行的輸出test.py是:

i am exec_test1 
i am exec_test1 

我想到:

任何有關如何實現這一目標的幫助非常感謝!

更新:答案在下面給出,但我要在這裏寫一個簡短的修改,並在該類中的新功能的擴展接受輸入。

方法create_method()test.py應如下面的接受的答案所概述進行更新:

def create_method(self): 
    # i expect this to create new methods with unique properties 
    # as attributes of an object of this class 
    for fn_exec in self.l: 
     # this is the function template 
     # that i want to call the relevant function from the 
     # module mymod (mm) 
     # because this run at runtime, it requires a param instead 
     def method(self, fn=fn_exec): 
      method_to_call = getattr(mm, fn) 
      method_to_call() 

     # this should create a new name based on the fn_exec 
     # and assign method to it 
     name_def = fn_exec.replace('exec_', 'do_') 
     setattr(self.__class__, name_def, method) 

此外,如果一個人需要將參數傳遞給該方法,諸如輸入some_inputcreate_method()將被更新像這樣:

def create_method(self): 
    # i expect this to create new methods with unique properties 
    # as attributes of an object of this class 
    for fn_exec in self.l: 
     # this is the function template 
     # that i want to call the relevant function from the 
     # module mymod (mm) 
     # because this run at runtime, it requires a param instead 
     def method(self, some_input, fn=fn_exec): 
      method_to_call = getattr(mm, fn) 
      method_to_call() 
      print(some_input) 

     # this should create a new name based on the fn_exec 
     # and assign method to it 
     name_def = fn_exec.replace('exec_', 'do_') 
     setattr(self.__class__, name_def, method) 

和主塊可能看起來像:

if __name__ == '__main__': 
    my_obj = MyClass() 
    my_obj.do_test0('a') 
    my_obj.do_test1('b') 

這將有以下的輸出:

i am exec_test0 
a 
i am exec_test1 
b 

回答

2

method身體名fn_exec不計算直到method稱爲,在這一點fn_exec有它率先在for循環的最後一個值。在method定義使用時確保它的價值,你需要使用默認參數值:

def method(self, fn=fn_exec): 
    method_to_call = getattr(mm, fn) 
    method_to_call() 

method定義,fn設置等於當前值fn_exec,所以這是用於定義method_to_call的值。

0

這與關閉如何在Python中工作有關。添加的方法,如:

def make_wrapper(self, method_to_call): 
    def method(self): 
     method_to_call() 

並更改create_method()到:

def create_method(self): 
    for fn_exec in self.l: 
     method_to_call = getattr(mm, fn_exec) 
     method = self.make_wrapper(method_to_call) 

     name_def = fn_exec.replace('exec_', 'do_') 
     setattr(self.__class__, name_def, method) 

因爲你是在一個實例這樣做,我建議設置實例上的方法(和有約束力的自我),而不是將它們直接設置在課程上:

setattr(self, name_def, method.__get__(self, self.__class__)) 
# Instead of 
setattr(self.__class__, name_def, method)