2011-05-16 137 views
0

我知道,標題很難理解。將另一個類的函數傳遞給這個類

所以,我有這個類:

class ConfigDict(dict): 

    def __init__(self, dic): 
     super(ConfigDict, self).__init__(dic) 

    def required(self, keys_array, function): 
     print 'required' 

    def valid(self, function = None): 
     print 'valid' 

,我想什麼 - 我用字典創建該類的實例作爲參數:

ConfigDict({'a' : 'b'}) 

它的工作,那是很好的。但我想從ConfigDict類的字典中傳遞函數作爲參數,而無需從ConfigDict中導入方法。
例如,我想這樣做:

ConfigDict({'a' : ('b', required(['test'], valid))}) 

我知道required在ConfigDict現在什麼也不做。預期的結果是:

>> ConfigDict({'a' : ('b', required(['test'], valid()))}) 
required called with ['test'], valid for {a : b} 
valid called from required with None for {a : b} 

所以,用{'a' : ('b', required['test'], valid())}字典創建ConfigDict的實例後,我想,這種情況下在__init__方法使循環中的所有字典的元素,如果創建於一值的元組,執行在itselfs成立嵌套函數。

在這裏有沒有辦法做到這一點,而無需從ConfigDict導入所有方法?

編輯:

如我所料,我必須更好地解釋我需要什麼。

好吧,我們以這個片段:

ConfigDict({'a' : ('b', required(['test'], valid))}) 

這使我們ConfigDict的新實例。這些touple功能用於驗證,在這種情況下它是'b'。我做了一些改動等待響應,因此調用這個類是現在看的是:

cd = ConfigDict() 
cd.feed({'a' : 'b'}) 

我可以調用這樣的功能:

cd.feed({'a' : ('b', cg.required(['test']))}) 

什麼是工作的非常好,但有一兩件事 - 它不傳遞給required函數的值。 ConfigDicts.required應該得到一個數組值,在這種情況下爲'b'。我不希望自己找到辦法來做到這一點,除了使用無處不在的lambda的我想避免的。

所以,我的問題有點改變 - 有沒有什麼辦法可以從得到'b'required函數?我可以直接將'b'作爲參數傳入required,但我希望有多個函數調用元組,每個值都會在代碼中造成一些混亂。

而且,任何人請,我的文章的編輯,我缺乏的話來形容這個問題:)

回答

1

你的英語有點難以理解,並且你的問題包含一些錯誤(或者只是不一致),所以我不確定你到底想要什麼,但是這裏有一件事可能適用於你:

(編輯)試試這個:

class CallWrapper(object): 
    def __init__(self, fn): 
     self.fn = fn 

    def __call__(self, *args, **kwargs): 
     self.args = args 
     self.kwargs = kwargs 
     return self 

    def invoke_with_value(self, value): 
     return self.fn(value, *self.args, **self.kwargs) 

class ConfigDict(dict): 
    def __init__(self, ldic): 
     myvars = globals() 
     for name in dir(self): 
      attr = getattr(self, name) 
      if callable(attr) and not name.startswith('_'): 
       myvars[name] = CallWrapper(attr) 

     wrapped_dic = eval(ldic.func_code, myvars) 

     dic = {} 
     for key, value in wrapped_dic.iteritems(): 
      # Check if value is a tuple with call wrappers 
      if isinstance(value, tuple) and len(value) > 1 and \ 
         isinstance(value[1], CallWrapper): 
       wrappers = value[1:] 
       value = value[0] 
       for wrapper in wrappers: 
        # Run wrappers 
        result = wrapper.invoke_with_value(value) 
        if result: 
         value = result # Wrapper modified value 

      dic[key] = value # No wrappers 

     super(ConfigDict, self).__init__(dic) 

    def prefix(self, value, pref): 
     print 'prefix called for value: ', value 
     return pref + '_' + value 

    def required(self, value, keys_array): 
     print 'required called for value: ', value 
     print 'with keys: ', keys_array 

    def valid(self, value): 
     print 'valid called for value: ', value 

cfg = ConfigDict(lambda: {'A': ('a', required(['test']), valid()), 
          'B': ('b', prefix('hello')), 
          'C': 'c'}) 
print cfg 

輸出:

required called for value: a 
with keys: ['test'] 
valid called for value: a 
prefix called for value: b 
{'A': 'a', 'C': 'c', 'B': 'hello_b'} 
+0

只有一點點?不錯的進展,一個月前我甚至無法理解我自己;)這幾乎正是我要找的,謝謝。 – Galmi 2011-05-17 00:08:24

+0

我測試了你的代碼,我發現這很好,但是沒有做到我所期望的,除了在ConfigDict中調用函數。在幾分鐘內我編輯我的帖子,嘗試解釋我需要的更簡單。 – Galmi 2011-05-17 00:42:22

+0

現在工作:)再次謝謝你。 – Galmi 2011-05-17 02:57:30

2

使用lambda功能:

ConfigDict({'a' : ('b', lambda self: self.required(['test'], valid))}) 

這就需要你明確地傳遞self爲一個參數(來自__init__方法,它看起來像dict['a'][1](self))。

你可以找到,如果事情是這樣的元組:

>>> isinstance((1, 2, 3), tuple) 
True 
>>> isinstance(1, tuple) 
False 

如果你需要,你可以找到,如果事情是像這樣的功能:

>>> import inspect 
>>> def f(): 
    print "I'm a function" 
>>> inspect.isfunction(f) 
True 
>>> inspect.isfunction(5) 
False 
>>> inspect.isfunction(lambda d: d) 
True 
0

這是一種逃避,但是你真的彎曲這裏寫一些東西,很可能是更好的成就(更好的理解,更少的微妙的錯誤)通過域特定語言。