我想创建一个查找表,为此我正在考虑使用字典。字典将具有对应于整数的键(或者在我的情况下对应于类Enum
中的枚举类型),并且值将是2,3或4个numpy数组。但不知怎的,我不愿意使用这种方法,因为这本词典有大量的信息,其中99%可能根本不用于某些问题。那么构建包含所有查找信息的单个对象是没有意义的,即使我在猜测,我几乎可以肯定,有更好的方法来实现我想要的要做。
所以来自C ++世界,我会为函数指针创建一个unordered_map
枚举类型,在函数中我将创建一个static
数组(这样它只会被创建一次)然后我会返回数组指针。通过这种方式,我只会实例化查找表中实际需要的部分,而不是整个程序。
但我尝试在Python中做类似的事情,所以我想知道实现这一目标的最有效方法。
修改
所以这就是我到目前为止所提出的。我混合了@AaronDigulla和@DanielRoseman提出的建议,尽管可能不再需要@runonce
。 dict
的子类重写__getitem__
方法并检查字典中是否存在密钥。如果它没有,它会调用一个函数(在字典键值的连接字符串上使用eval()
)。我将不胜感激给定代码的任何改进。它看起来很复杂,但它确实有效,所以我想知道它是否可以进一步简化。
import collections, types
import numpy as np
Quadrature = collections.namedtuple("Quadrature", "wgt xi eta zeta")
category_map = { "t3" : "tri" #... more types
}
class Integrator(dict):
def __init__(self, *args, **kwargs):
self.update(*args, **kwargs)
def __getitem__(self, key):
if not key in self:
fn = '{}_{}gp'.format(category_map[key[0]], str(key[1]))
super().__setitem__(key, eval(fn)())
val = super().__getitem__(key)
return val
def __repr__(self):
dictrepr = dict.__repr__(self)
return '%s(%s)' % (type(self).__name__, dictrepr)
def update(self, *args, **kwargs):
print ('update', args, kwargs)
for k, v in dict(*args, **kwargs).items():
self[k] = v
def run_once(f):
def wrapper(*args, **kwargs):
if not wrapper.has_run:
wrapper.has_run = True
return f(*args, **kwargs)
wrapper.has_run = False
return wrapper
@run_once
def tri_3gp():
xi = np.array([2/3., 1/6., 1/6.])
eta = np.array([1/6., 1/6., 2/3.])
wgt = np.array([2/3., 2/3., 2/3.]);
return Quadrature(wgt, xi, eta, None)
答案 0 :(得分:1)
你可以用Python做同样的事情。实际上,它更容易,因为函数本身就是一流的对象:您可以将它们存储在字典中并根据需要调用它们。
要替换静态数组,可以使用某种记忆,例如标准的全局查找数组。
global_dict = {}
def func1():
if 'param1' not in global_dict:
global_dict['param1'] = my_complicated_function_for_param_1()
return global_dict['param1'] = my_complicated_function_for_param_1()
lookup_dict = {
'param1': func1,
...
}
# now do the lookup:
my_result = lookup_dict[my_param]()
你当然可能想要从计算函数中分解逻辑:装饰器可能是一个很好的方法。
答案 1 :(得分:1)
在Python中这很简单。看到这个问题如何创建"运行一次"装饰者:Efficient way of having a function only execute once in a loop
现在您可以使用函数在地图中创建数据。装饰者将确保它们最多运行一次(第一次调用它们)。然后循环就像这样:
@run_once
def funcForKey():
...
lookup_dict = {
'key': funcForKey,
...
}
result = lookup_dict[x]()
()
调用该函数后的[]
。
您也可以尝试上课:
class Data(object):
@run_once
def key(self):
...
data = Data()
现在您可以查找如下值:
a = 'key'
result = getattr(data, a)()
或者,如果名称在运行时是常量,则只需:
result = data.key()