将函数从另一个类传递给此类

时间:2011-05-16 22:22:18

标签: python

我知道,标题很难理解。

所以,我有这个课程:

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'

我想要的是 - 我用dict作为参数创建这个类的实例:

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

它正常运作,这很好。但是我希望在ConfigDict类的dict中传递函数作为参数而不从ConfigDict导入方法 例如,我想这样做:

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

我知道ConfigDict中的required现在什么都不做。预期结果是:

>> 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())} dict创建ConfigDict实例后,我希望__init__方法中的这个实例在所有dict元素中生成循环,如果在值中创建了元组,则在自身中执行创建的嵌套函数

如果没有从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,但我希望在元组中调用很多函数,为每个函数传递值会使代码变得有些混乱。

此外,有人请,编辑我的帖子的标题,我缺乏描述这个问题的词语:)

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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'}

答案 2 :(得分:0)

这是一个警察,但你真的在这里写一些东西,通过领域特定语言写一些可能更好(更好理解,更少微妙的错误)的东西。