效果图代做网站,wordpress终极简码,苏州区网站建设,百度入驻哈尔滨一、说明 Numpy的数组是强大的对象#xff0c;通常用作更复杂的对象#xff08;如pandas或xarray#xff09;的基本数据结构。话虽如此#xff0c;您当然也可以在自己的类中使用numpy的强大数组 - 为此#xff0c;您基本上有2种方法#xff1a;
子类方法#xff1a;创建… 一、说明 Numpy的数组是强大的对象通常用作更复杂的对象如pandas或xarray的基本数据结构。话虽如此您当然也可以在自己的类中使用numpy的强大数组 - 为此您基本上有2种方法
子类方法创建从 Numpy.ndarray 继承的类容器方法创建将数组作为属性的类
在本文中我们将看到如何使用容器方法来包装 numpy 的数组来正确创建自己的自定义类。 二、 物理格式的项目 让我们举一个示例项目我们想创建一个简单的项目来处理物理单位和尺寸创建长度或重量的数组然后使用这些数组来计算平均身高或[身体质量指数]https://en.wikipedia.org/wiki/Body_mass_index。我们希望依靠 numpy 来完成繁重的数值计算如加法、减法、幂但我们也希望能够处理像 numpy 数组这样的实例比如 or .[1, 2, 3] meter [55 65 8] kilogramnp.sort(weights)np.min(heights) 为此我们将创建一个使用容器方法来包装 numpy 数组的新类。数值将存储为普通 numpy 数组物理维度存储为字符串
import numpy as npclass Physical():def __init__(self, value, unit):self.value value # store the numerical value as a plain numpy arrayself.unit unitdef __repr__(self):return fPhysical:({self.value}, {self.unit})def __str__(self):return f{self.value} {self.unit}weights Physical(np.array([55.6, 45.7, 80.3]), kilogram)
print(weights) # [55.6 45.7 80.3] kilogram 物理阵列的第一个实现
这将简单地打印。同样此字符串后面的数字列表是存储在 中的实际 numpy 数组。[55.6 45.7 80.3] kilogramself.value
现在这是毫无用处的我们不能让这个对象与其他任何东西交互所以我们添加了基本操作如加法或乘法与其他实例Physical import numpy as npclass Physical():def __init__(self, value, unit):self.value valueself.unit unitdef __repr__(self):return fPhysical:({self.value}, {self.unit})def __str__(self):return f{self.value} {self.unit}def __add__(self, other):if self.unit other.unit:return Physical(self.value other.value, self.unit)else:raise ValueError(Physical objects must have same unit to be added.)def __sub__(self, other):if self.unit other.unit:return Physical(self.value - other.value, self.unit)else:raise ValueError(Physical objects must have same unit to be subtracted.)def __mul__(self, other):return Physical(self.value * other.value, f{self.unit}*{other.unit})def __truediv__(self, other):return Physical(self.value / other.value, f{self.unit}/{other.unit})def __pow__(self, powfac):return Physical(self.value**powfac, f{self.unit}^{powfac})weights Physical(np.array([55.6, 45.7, 80.3]), kilogram)
heights Physical(np.array([1.64, 1.85, 1.77]), meter)
print(weights) # [55.6 45.7 80.3] kilogram
print(heights) # [1.64 1.85 1.77] meter
print(heights heights) # [3.28 3.7 3.54] meter
# print(height weights) # raises ValueError
print(heights**2) # [2.6896 3.4225 3.1329] meter^2 现在可以将物理阵列与其他物理阵列相加或相乘。
请注意在添加或减去物理之前我们首先检查它们是否具有相同的单位您不能用重量添加长度或土豆加胡萝卜或马用驴。
这很好我们现在可以计算一个身体质量指数 BMI 数组给定一个以米为单位的高度数组和一个以公斤为单位的重量数组。BMI 只是通过将重量除以平方高度来给出的即
BMI 体重公斤/身高米^2
weights Physical(np.array([55.6, 45.7, 80.3]), kilogram)
heights Physical(np.array([1.64, 1.85, 1.77]), meter)
bmi weights/heights**2
print(bmi) # [20.67221892 13.35281227 25.63120432] kilogram/meter^2 万岁我们使用身高数组和身高数组计算了一个身体质量指数数组使用后面的numpy数组来执行实际的数值计算。但是numpy的数组还有很多东西可以提供这就是它变得非常有趣的地方。
三、实现 numpy 函数支持
Numpy 提供了许多用于数组的有用函数。仅举几例
np.sin等np.cosnp.tannp.exp等np.lognp.log10np.add等np.multiplynp.dividenp.min等np.maxnp.argminnp.argmaxnp.floor等np.ceilnp.truncnp.concatenate等np.vstack
等等。您可以在他们的网站上找到numpy提供的所有内容Routines — NumPy v1.25 Manual。
让我们尝试在我们的类中使用其中之一
np.mean(bmi)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
...
ipython-input-10-538e4626f6f7 in __truediv__(self, other)31 32 def __truediv__(self, other):
--- 33 return Physical(self._value / other._value, f{self._unit}/{other._unit})34 35 def __pow__(self, powfac):AttributeError: numpy.int64 object has no attribute _value 尝试调用我们的物理实例会引发一个 因为 numpy 依赖于整数的加法和除法而我们的类没有正确实现这种操作。所以我们必须在某个地方告诉 numpy 我们想要如何表现。np.meanbmiAttributeErrornp.mean(bmi)
这就是界面发挥作用的地方。__array_function__
该接口只是一个规范化过程用于重载某些numpy 函数如何处理类中的参数。__array_function__
让我们看一个轻量级的例子来处理我们的调用np.mean(bmi) import numpy as np# FIRST
HANDLED_FUNCTIONS {}class Physical():def __init__(self, value, unit):self._value valueself._unit unit# ... other methods here, see above# SECONDdef __array_function__(self, func, types, args, kwargs):if func not in HANDLED_FUNCTIONS:return NotImplemented# Note: this allows subclasses that dont override# __array_function__ to handle MyArray objectsif not all(issubclass(t, Physical) for t in types):return NotImplementedreturn HANDLED_FUNCTIONS[func](*args, **kwargs)# THIRD
def implements(numpy_function):Register an __array_function__ implementation for Physical objects.def decorator(func):HANDLED_FUNCTIONS[numpy_function] funcreturn funcreturn decorator# FOURTH
implements(np.mean)
def np_mean_for_physical(x, *args, **kwargs):# first compute the numerical value, with no notion of unitmean_value np.mean(x._value, *args, **kwargs)# construct a Physical instance with the result, using the same unitreturn Physical(mean_value, x._unit)weights Physical(np.array([55.6, 45.7, 80.3]), kilogram)
heights Physical(np.array([1.64, 1.85, 1.77]), meter)
bmi weights/heights**2print(np.mean(bmi)) # 19.885411834844252 kilogram/meter^2 使用 __array_function__ 接口实现 np.mean 支持
再次欢呼返回我们物理数组的“平均值”这确实是一个物理量单位为“千克/米^2”。np.mean(bmi)
让我们回顾一下我们添加到代码中以实现此目的的内容。有 4 点需要注意
首先我们在类定义之上创建一个空字典称为 。HANDLED_FUNCTION {}其次我们在类中添加一个调用的方法该方法采用一个名为 .我们将在一分钟内回到此方法的内容。__array_function__func第三我们创建一个装饰器构造函数这是一个返回装饰器的函数即另一个将函数作为参数的函数。我们的装饰器只是在我们的字典中创建 numpy 函数和 之间的对应关系后者是我们版本的 numpy 函数。implementsHANDLED_FUNCTIONfunc第四我们实现了 numpy 处理物理实例的平均值当调用时是物理实例。它具有与 大致相同的签名并执行以下操作np.mean(x)xnp.mean
使用 x 的值计算数值平均值这是一个普通数组。x._value然后使用平均值作为值和输入的单位作为单位创建新的物理实例。最后我们在该函数上使用装饰器。implements
那么当我们打电话时会发生什么np.mean(bmi)
好吧由于 numpy 无法计算平均值正如我们上面看到的它检查是否有方法并使用在 上使用的函数调用它即 。bmi__array_function__bminp.meanbmi.__array_function__(np.mean, *args, **kwargs)
由于已经在 中注册我们用它来调用我们的版本这里相当于 。np.meanHANDELED_FUNCTIONSnp.meanHANDLED_FUNCTIONS[np.mean](*args, **kwargs)np_mean_for_physical(*args, **kwargs)
这就是如何使 numpy 的函数与您的自定义类一起工作。
不幸的是这并不完全正确。此接口仅适用于某些 numpy 函数但不适用于全部。
还记得上面的功能列表吗好吧我们可以将它们分为 2 个子列表常规 numpy 函数和 numpy 通用函数 — 或简称“ufuncs”
Numpy 函数 np.minnp.maxnp.argminnp.argmaxnp.concatenatenp.vstack.Numpy ufuncs ,, , ,, , , , ,np.sinnp.cosnp.tannp.expnp.lognp.log10np.addnp.multiplynp.dividenp.floornp.ceilnp.trunc
我们看到了如何使用 实现 numpy 函数支持。在下一篇文章中我们现在将看到如何使用该接口添加对“ufuncs”的支持。__array_function____array_ufunc__
四、总结一下
使用 numpy 数组的容器方法包括在自定义类实例中将数组设置为属性与子类化数组相反。要使类使用 numpy 函数调用如 必须在类中实现接口。np.mean(my_array_like_instance)__array_function__这基本上是通过向类添加一个方法编写自己的包装器就像我们对 所做的那样并将它们链接在一起就像我们对查找字典所做的那样。__array_function__np_mean_for_physicalHANDLED_FUNCTIONS请注意这仅适用于“常规”numpy 函数。对于numpy的“通用”函数您还需要实现该接口。__array_ufunc__
这个主题相当广泛所以这里有几个链接你应该阅读以更好地掌握利害关系
容器方法Writing custom array containers — NumPy v1.25 Manual__array_function__参考资料 Standard array subclasses — NumPy v1.25 Manual参考资料 Universal functions (ufunc) — NumPy v1.25 Manual
以下是我们在本文中编写的完整代码
import numpy as npHANDLED_FUNCTIONS {}class Physical():def __init__(self, value, unit):self._value valueself._unit unitdef __repr__(self):return fPhysical:({self._value}, {self._unit})def __str__(self):return f{self._value} {self._unit}def __add__(self, other):if self._unit other._unit:return Physical(self._value other._value, self._unit)else:raise ValueError(Physical objects must have same unit to be added.)def __sub__(self, other):if self._unit other._unit:return Physical(self._value - other._value, self._unit)else:raise ValueError(Physical objects must have same unit to be subtracted.)def __mul__(self, other):return Physical(self._value * other._value, f{self._unit}*{other._unit})def __truediv__(self, other):return Physical(self._value / other._value, f{self._unit}/{other._unit})def __pow__(self, powfac):return Physical(self._value**powfac, f{self._unit}^{powfac})def __array_function__(self, func, types, args, kwargs):if func not in HANDLED_FUNCTIONS:return NotImplemented# Note: this allows subclasses that dont override# __array_function__ to handle Physical objectsif not all(issubclass(t, Physical) for t in types):return NotImplementedreturn HANDLED_FUNCTIONS[func](*args, **kwargs)def implements(numpy_function):Register an __array_function__ implementation for Physical objects.def decorator(func):HANDLED_FUNCTIONS[numpy_function] funcreturn funcreturn decoratorimplements(np.mean)
def np_mean_for_physical(x, *args, **kwargs):# first compute the numerical value, with no notion of unitmean_value np.mean(x._value, *args, **kwargs)# construct a Physical instance with the result, using the same unitreturn Physical(mean_value, x._unit)weights Physical(np.array([55.6, 45.7, 80.3]), kilogram)
heights Physical(np.array([1.64, 1.85, 1.77]), meter)
print(weights)
print(heights)
print(heights heights)
print(heights**2)
ratio weights/heights
print(ratio)
bmi weights/heights**2
print(bmi)
print(np.mean(bmi)) 干杯