Ответ 1
Вы должны проверить PEP-3141 и стандартный модуль lib ABCMeta.
Подробное объяснение того, как использовать ABCMeta, всегда полезно PyMOTW иметь хорошую запись.
Я прототипирую новую систему в Python; функциональность в основном численная.
Важным требованием является возможность использования разных линейных алгебраических back-end: от отдельных пользовательских реализаций до общих библиотек, таких как Numpy. Реализация линейной алгебры (т.е. Фоновой) должна быть независимой от интерфейса.
Моя первоначальная архитектурная попытка выглядит следующим образом:
>>> v1 = Vector([1,2,3])
>>> v2 = Vector([4,5,6])
>>> print v1 * v2
>>> # prints "Vector([4, 10, 18])"
# this example uses numpy as the back-end, but I mean
# to do this for a general back-end
import numpy
def numpy_array(*args): # creates a numpy array from the arguments
return numpy.array(*args)
class VectorBase(type):
def __init__(cls, name, bases, attrs):
engine = attrs.pop("engine", None)
if not engine:
raise RuntimeError("you need to specify an engine")
# this implementation would change depending on `engine`
def new(cls, *args):
return numpy_array(*args)
setattr(cls, "new", classmethod(new))
class Vector(object):
__metaclass__ = VectorBase
# I could change this at run time
# and offer alternative back-ends
engine = "numpy"
@classmethod
def create(cls, v):
nv = cls()
nv._v = v
return nv
def __init__(self, *args):
self._v = None
if args:
self._v = self.new(*args)
def __repr__(self):
l = [item for item in self._v]
return "Vector(%s)" % repr(l)
def __mul__(self, other):
try:
return Vector.create(self._v * other._v)
except AttributeError:
return Vector.create(self._v * other)
def __rmul__(self, other):
return self.__mul__(other)
Этот простой пример работает следующим образом: класс Vector
сохраняет ссылку на векторный экземпляр, созданный контентом (numpy.ndarray
в примере); все арифметические вызовы реализуются интерфейсом, но их оценка отложена на задний план.
На практике интерфейс перегружает все соответствующие операторы и переадресации на внутренний сервер (в примере показаны только __mul__
и __rmul__
, но вы можете следить за тем, что это будет сделано для каждой операции).
Я готов потерять определенную производительность в обмен на настраиваемость. Даже несмотря на то, что мой пример работает, он не чувствует себя хорошо - я бы исказил бы внутренний сервер так много вызовов конструктора! Это требует другой реализации metaclass
, позволяющей улучшить отсрочку вызова.
Итак, как бы вы рекомендовали мне реализовать эту функциональность? Мне нужно подчеркнуть важность сохранения всех системных событий Vector
однородными и независимыми от линейной алгебры.
Вы должны проверить PEP-3141 и стандартный модуль lib ABCMeta.
Подробное объяснение того, как использовать ABCMeta, всегда полезно PyMOTW иметь хорошую запись.
Почему бы просто не сделать "виртуальный" класс (AbstractVector
), который похож на Vector в вашем примере, и сделать для него разные подклассы для него?
Двигатель можно выбрать, выполнив Vector = NumPyVector
или что-то в этом роде.
Просто FYI, вы можете легко настроить и построить NumPy, чтобы использовать библиотеку ядра Intel Math или библиотеку AMD Core Math вместо обычного ATLAS + LAPACK. Это так же просто, как создание файла site.cfg с набором переменных blas_libs
, lapack_libs
, library_dirs
и include_dirs
соответственно. (Подробности для установки этих параметров для MKL и ACML легко доступны для Google.) Поместите его рядом с setup.py
script и создайте, как обычно.
Чтобы переключаться между этими стандартными библиотеками линейных алгебр, вы можете создать другой экземпляр NumPy для каждого и управлять ими, например, virtualenvs.
Я знаю, что это не дает вам гибкости, необходимой для использования ваших собственных математических математических библиотек, но просто подумал, что я брошу это там. И хотя я не рассматривал это, я думаю, вы также можете получить NumPy для создания против пользовательской библиотеки с меньшими усилиями, чем потребовалось бы, чтобы создать собственный интерфейс, особенно если вы хотите сохранить расширенную функциональность здания NumPy/SciPy.