Python 如何编写一个行为类似于numpy.ndarray的类,而不将numpy.ndarray子类化?

Python 如何编写一个行为类似于numpy.ndarray的类,而不将numpy.ndarray子类化?,python,numpy,Python,Numpy,让我们假设以下给定的类定义: class Numeric(object): def __init__(self, signal): self.signal = signal 现在,由于要求Numeric不继承自numpy.ndarray,我如何扩展Numeric行为类似于numpy.ndarray的定义 编辑:信号应为np.ndarray(或类似的,如数量.数量)。我想到了以下情景: import numpy as np import quantities as pq a = N

让我们假设以下给定的类定义:

class Numeric(object):
  def __init__(self, signal):
    self.signal = signal
现在,由于要求
Numeric
不继承自
numpy.ndarray
,我如何扩展
Numeric
行为类似于
numpy.ndarray
的定义

编辑:
信号
应为
np.ndarray
(或类似的,如
数量.数量
)。我想到了以下情景:

import numpy as np
import quantities as pq

a = Numeric(pq.Quantity([1,2,3], 'mV'))
b = Numeric(pq.Quantity([1,3,5], 's'))
c = Numeric(np.array([10,20,30]))

a = Numeric(np.array([1,2,3]))
b = Numeric(np.array([1,3,5]))
a * c
a * b
a * np.array([3,4,5])
以及:


使用用于调整
numpy
-函数的装饰器和
数值
中的
\uuu数组\uuuu
实现,我可以解决大多数问题:

def adapt_signal_functions(cls):
  def generateAdjustedFunction(functionName):
    print functionName
    def foo(self, *args, **kwargs):
      function = getattr(self.signal.__class__, functionName)
      return function(self.signal, *args, **kwargs)
    return foo
  functionNames = [
      '_get_units',
      '_set_units',
      'rescale',
      'ptp',
      'clip',
      'copy',
      'compress',
      'conj',
      'cumprod',
      'cumsum',
      'diagonal',
      'dot',
      'flatten',
      'getfield',
      'round',
      'trace',
      'max',
      'mean',
      'min',
      'newbyteorder',
      'prod',
      'ravel',
      'reshape',
      'resize',
      'round',
      'std',
      'sum',
      'trace',
      'transpose',
      'var',
      '__getitem__',
      '__getslice__',
      '__abs__',
      #
      '__add__',
      '__div__',
      '__divmod__',
      '__floordiv__'
      '__mod__',
      '__mul__',
      '__pow__',
      '__sub__',
      #
      '__radd__',
      '__div__',
      '__divmod__',
      '__rfloordiv__',
      '__rmod__',
      '__imul__',
      #'__rmul__',
      '__rpow__',
      '__rsub__',
      ]
  for functionName in functionNames:
    foo = generateAdjustedFunction(functionName)
    setattr(cls, functionName, foo)
  return cls


@adapt_signal_functions
class Numeric(object):
  def __init__(self, signal):
    self.signal = signal
    self.adapt_quantity()

  def adapt_quantity(self):
    if hasattr(self.signal, '_dimensionality'):
      self._dimensionality = self.signal._dimensionality
      self.dimensionality = self.signal.dimensionality

  def __array__(self):
    return self.signal
有了这些,我可以:

import numpy as np
import quantities as pq

a = Numeric(pq.Quantity([1,2,3], 'mV'))
b = Numeric(pq.Quantity([1,3,5], 's'))
c = Numeric(np.array([10,20,30]))
n =  np.array([1,2,3])

a * a
a * c
a * n
a.max()

print type(a * n) == type(a.signal *  n)
# >>> True
print type(a * c) == type(a.signal *  c.signal)
# >>> True
返回类型对应于
Numeric.signal
的等效返回类型

还有一个问题:

print type(n * a) == type(n * a.signal)
# >>> False

有什么想法,如何解决吗?

有一个用于调整
numpy
-函数的装饰器,并在
数值
中实现
\uuuuuuuu
,我可以解决大多数问题:

def adapt_signal_functions(cls):
  def generateAdjustedFunction(functionName):
    print functionName
    def foo(self, *args, **kwargs):
      function = getattr(self.signal.__class__, functionName)
      return function(self.signal, *args, **kwargs)
    return foo
  functionNames = [
      '_get_units',
      '_set_units',
      'rescale',
      'ptp',
      'clip',
      'copy',
      'compress',
      'conj',
      'cumprod',
      'cumsum',
      'diagonal',
      'dot',
      'flatten',
      'getfield',
      'round',
      'trace',
      'max',
      'mean',
      'min',
      'newbyteorder',
      'prod',
      'ravel',
      'reshape',
      'resize',
      'round',
      'std',
      'sum',
      'trace',
      'transpose',
      'var',
      '__getitem__',
      '__getslice__',
      '__abs__',
      #
      '__add__',
      '__div__',
      '__divmod__',
      '__floordiv__'
      '__mod__',
      '__mul__',
      '__pow__',
      '__sub__',
      #
      '__radd__',
      '__div__',
      '__divmod__',
      '__rfloordiv__',
      '__rmod__',
      '__imul__',
      #'__rmul__',
      '__rpow__',
      '__rsub__',
      ]
  for functionName in functionNames:
    foo = generateAdjustedFunction(functionName)
    setattr(cls, functionName, foo)
  return cls


@adapt_signal_functions
class Numeric(object):
  def __init__(self, signal):
    self.signal = signal
    self.adapt_quantity()

  def adapt_quantity(self):
    if hasattr(self.signal, '_dimensionality'):
      self._dimensionality = self.signal._dimensionality
      self.dimensionality = self.signal.dimensionality

  def __array__(self):
    return self.signal
有了这些,我可以:

import numpy as np
import quantities as pq

a = Numeric(pq.Quantity([1,2,3], 'mV'))
b = Numeric(pq.Quantity([1,3,5], 's'))
c = Numeric(np.array([10,20,30]))
n =  np.array([1,2,3])

a * a
a * c
a * n
a.max()

print type(a * n) == type(a.signal *  n)
# >>> True
print type(a * c) == type(a.signal *  c.signal)
# >>> True
返回类型对应于
Numeric.signal
的等效返回类型

还有一个问题:

print type(n * a) == type(n * a.signal)
# >>> False

有什么想法,如何解决吗?

这个要求是从哪里来的?ndarray的行为有什么你想要的吗?这是一件大事。如果没有子类化,您将永远无法获得完整的
ndarray
行为,因为一些Numpy操作,如
asarray
根据它们是否获得
ndarray
实例或其他东西而不同。当我想将对象映射到表时,要求来自SQLAlchemy。我想使用算术函数和类似plot(Numeric(np.array([1,2,3])的东西。这个要求从何而来?你想要ndarray的行为有什么特别的地方吗?这是一件大事。如果不进行子类化,你永远不会得到完整的
ndarray
行为,因为一些Numpy操作,如
asarray
根据它们是否得到
ndarray
实例或其他什么,它们的行为会有所不同否则。当我想将对象映射到一个表时,要求来自SQLAlchemy。我想使用算术函数和绘图(数字(np.array([1,2,3])。什么是“数量”?是SQLAlchemy中定义的东西?还是您自己定义的东西?(或其他东西?)@EdwardLoper-我假设它是这个单位转换库:准确地说,并且
pq.Quantity
继承自
numpy.ndarray
。什么是“数量”?是SQLAlchemy中定义的东西?还是您自己定义的东西?(或其他东西?)@EdwardLoper-我假设它是这个单位转换库:准确地说,
pq.Quantity
继承自
numpy.ndarray