2011-05-16 228 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

这是一种逃避,但是你真的弯曲这里写一些东西,很可能是更好的成就(更好的理解,更少的微妙的错误)通过域特定语言。