Я хотел бы создать таблицу поиска, и для этого я думаю об использовании словаря. В словаре будут ключи, соответствующие целому числу (или, в моем случае, перечисляемому типу из класса Enum
), а значениями будут 2, 3 или 4 пустых массива. Но мне как-то неохота использовать такой подход, так как в этом словаре огромное количество информации, и 99% ее может вообще не использоваться для каких-то задач. Таким образом, нет смысла создавать единый объект, содержащий всю информацию для поиска, и хотя я размышляю, я почти уверен, что есть лучший подход для выполнения того, что я хочу сделать.
Итак, исходя из мира C++, я бы создал unordered_map
типов enum для указателей на функции, где в функции я бы создал массив 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)