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.
精彩评论