2012-05-10 38 views
1

我创建了一个类MyClass,其中包含大量的仿真数据。该课程将模拟结果归类为具有相似结构的不同模拟。结果可以用MyClass.get(foo)方法检索。它返回一个带有模拟ID /数组对的字典,对于每个模拟,数组的值为foo如何在python中创建自己的映射类型

现在我想在我的类中实现一个方法来将所有函数应用于foo的所有数组。它应该返回一个带有simulationID/function(foo)对的字典。

对于不需要附加参数的函数,我发现了以下的解决方案非常满意(注释总是欢迎:-)):

def apply(self, function, variable): 
    result={} 
    for k,v in self.get(variable).items(): 
     result[k] = function(v) 
    return result 

但是,对于需要额外的参数,我们没有看到一个功能如何以优雅的方式做到这一点。一个典型的操作将与barnp.trapz(foo, x=bar),其中两个foobar可以MyClass.get(...)

我想在这个方向retreived x值foo整合:

def apply(self, function_call): 
    """ 
    function_call should be a string with the complete expression to evaluate 
    eg: MyClass.apply('np.trapz(QHeat, time)') 

    """ 
    result={} 
    for SID in self.simulations: 
     result[SID] = eval(function_call, locals=...) 

    return result 

的问题是,我不知道如何传递本地映射对象。或者我正在寻找一个错误的方向。预先感谢您的帮助。

Roel

+1

你的第一个例子可以简化dpwn为一个字典表达式:'{k:function(v)for k,v in self。获得(可变).items()}'。 –

回答

1

我尝试重新创建类结构(相关部分)的方式,我猜测它是建立在您身边的(如果您可以提供简化的代码示例供人们玩/测试,它总是很方便)。

我想你要做的是将变量名称转换为从类中获得的变量,然后在传入的函数中使用这些变量。除此之外,因为每个变量实际上都是一个带有键(SID)的值的字典,所以您希望结果是一个结果字典,该函数应用于每个参数。

class test: 
    def get(self, name): 
     if name == "valA": 
      return {"1":"valA1", "2":"valA2", "3":"valA3"} 
     elif name == "valB": 
      return {"1":"valB1", "2":"valB2", "3":"valB3"} 
    def apply(self, function, **kwargs): 
     arg_dict = {fun_arg: self.get(sim_args) for fun_arg, sim_args in kwargs.items()} 
     result = {} 
     for SID in arg_dict[kwargs.keys()[0]]: 
      fun_kwargs = {fun_arg: sim_dict[SID] for fun_arg, sim_dict in arg_dict.items()} 
      result[SID] = function(**fun_kwargs) 
     return result 

def joinstrings(string_a, string_b): 
    return string_a+string_b 

my_test = test() 
result = my_test.apply(joinstrings, string_a="valA", string_b="valB") 
print result 

所以适用方法获取参数的字典,获取每个参数的特定类的数据,并创建与那些(arg_dict)有了新的说法字典。

SID键是从这个arg_dict中获得的,对于其中的每一个,计算函数结果并将其添加到结果字典中。

结果是:

{'1': 'valA1valB1', '3': 'valA3valB3', '2': 'valA2valB2'} 

的代码可以在许多方面改变,但我认为这将是最可读的。当然可以加入字典,而不是使用第一个元素的SID。

+0

这确实适用于我提供的示例。 – saroele

2

有两种方法。第一种方法是使用functools.partial

foo = self.get('foo') 
bar = self.get('bar') 
callable = functools.partial(func, foo, x=bar) 
self.apply(callable, variable) 

而第二种方法是使用由部分使用了相同的技术,你可以定义接受任意参数列表的功能:

def apply(self, function, variable, *args, **kwds): 
    result={} 
    for k,v in self.get(variable).items(): 
     result[k] = function(v, *args, **kwds) 
    return result 

注意,在这两种情况下功能签名保持不变。我不知道我会选择哪一个,也许是第一个案例,但我不知道您正在处理的背景。

+0

可能存在一个误解:您的解决方案对于那些在调用函数的名称空间中使用已知参数的函数确实有效。例子:但是这两种解决方案都不适用于np.trapz示例,因为'bar'也是一个字典,每次迭代都必须选择相应的数组。让我们再举一个例子:我想得到'foo'和'bar'的总和,所以结果中的键'SID'的值应该是'self.get(foo)[SID] + self.get( bar)[SID]' – saroele

+0

如果不同的函数具有不同的签名,则应用的语义对我来说是错误的,因为您必须为N个不同的签名编写N个函数。答案不清楚,例如它是什么'self.simulations'?它没有出现在任何地方。写一个数据集的例子。 –

+0

如果我的问题不是很清楚,我很抱歉。我承认我的问题有两个部分或两个解释。你的答案解决了第一个问题,但不是第二个问题。 @Dirk的答案解决了这两个问题。 – saroele

相关问题