开发者

Passing function from another class to this class

开发者 https://www.devze.com 2023-03-06 14:09 出处:网络
I know, title is hard to understand. So, i have this class: class ConfigDict(dict): def __init__(self, dic):

I know, title is hard to understand.

So, i have this class:

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'

And what i want - i create instance of this class with dict as parameter:

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

It's working, thats good. But i want pass function as argument in dict from ConfigDict class without importing methods from ConfigDict.

For example, i want do this:

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

I know that required in ConfigDict do nothing now. Expected result is:

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

So, after creating instance of ConfigDict with {'a' : ('b', required['test'], valid())} dict, i want that this instance in __init__ method make loop in all dict elements, and if founds tuple in value, execute founded nested function in itselfs.

Is here any way to do this without importing all methods from ConfigDict?

EDIT:

As i expected i must better explain what i need.

Ok, we take this fragment:

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

This made us new instance of ConfigDict. These functions in touple is used to validate value, in this case it is 'b'. I made few changes waiting for response, so calling this class is now look that:

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

I can call functions like that:

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

What is work's very well, but there's one thing - it not pass to required function the value. ConfigDicts.required should get an array and value, in this case 'b'. I don't expect to find way to do this myself, except using everywhere lambda's what i like to avoid.

So, my question been bit changed - is there a any way to get 'b' value from inside required function? I can pass 'b' a开发者_JAVA百科s argument directly into required, but i expect to have many functions call in tuple, passing value for each make a little mess in code.

Also, anyone please, edit title of my post, i lack of words to describe this problem :)


Use a lambda function:

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

This would require you to explicitly pass self as a parameter (From the __init__ method, it would look like dict['a'][1](self)).

You can find out if something is a tuple like this:

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

And if you need to, you can find out if something is a function like so:

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


Your English is a bit hard to understand, and your question contains some errors (or just inconsistencies), so I'm not sure what exactly you want, but here's one thing the may work for you:

(Edit) Try this:

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

Output:

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'}


This is a cop-out, but you're really flexing here to write something that'd probably be much better accomplished (better understood, fewer subtle bugs) by a Domain Specific Language.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号