如果不更改类代码,您将无法以 NumPy 数组作为输入来实例化类。 @PabloAlvarez 和 @NagaKiran 已经提供了替代方案:使用 zip 遍历数组并为每对元素实例化类。虽然这是一个非常简单的解决方案,但它破坏了使用 NumPy 及其高效矢量化操作的目的。
以下是我建议您重写代码的方法:
from typing import Union
import numpy as np
def total(a: Union[float, np.ndarray],
b: Union[float, np.ndarray],
n: int = 5) -> np.array:
"""Calculates what your self.tot was"""
bc = 8 * a
c = bc / b
vectorized_geometric_progression = np.vectorize(geometric_progression,
otypes=[np.ndarray])
l = np.stack(vectorized_geometric_progression(bc, c, n))
l = np.atleast_2d(l)
p = np.insert(l[:, :-1], 0, b, axis=1)
l = np.squeeze(l)
p = np.squeeze(p)
pl_avg = (p + l) / 2
komp = np.array([0.75 * pl_avg ** 2]).T
return komp + l
def geometric_progression(bc, c, n):
"""Calculates array l"""
return bc * np.logspace(start=0,
stop=n - 1,
num=n,
base=c + 2)
您可以将它称为唯一数字和 NumPy 数组,如下所示:
>>> print(total(1, 2))
[[2.6750000e+01 6.6750000e+01 3.0675000e+02 1.7467500e+03 1.0386750e+04]
[5.9600000e+02 6.3600000e+02 8.7600000e+02 2.3160000e+03 1.0956000e+04]
[2.1176000e+04 2.1216000e+04 2.1456000e+04 2.2896000e+04 3.1536000e+04]
[7.6205600e+05 7.6209600e+05 7.6233600e+05 7.6377600e+05 7.7241600e+05]
[2.7433736e+07 2.7433776e+07 2.7434016e+07 2.7435456e+07 2.7444096e+07]]
>>> print(total(3, 4))
[[1.71000000e+02 3.39000000e+02 1.68300000e+03 1.24350000e+04 9.84510000e+04]
[8.77200000e+03 8.94000000e+03 1.02840000e+04 2.10360000e+04 1.07052000e+05]
[5.59896000e+05 5.60064000e+05 5.61408000e+05 5.72160000e+05 6.58176000e+05]
[3.58318320e+07 3.58320000e+07 3.58333440e+07 3.58440960e+07 3.59301120e+07]
[2.29323574e+09 2.29323590e+09 2.29323725e+09 2.29324800e+09 2.29333402e+09]]
>>> print(total(np.array([1, 3]), np.array([2, 4])))
[[[2.67500000e+01 6.67500000e+01 3.06750000e+02 1.74675000e+03 1.03867500e+04]
[1.71000000e+02 3.39000000e+02 1.68300000e+03 1.24350000e+04 9.84510000e+04]]
[[5.96000000e+02 6.36000000e+02 8.76000000e+02 2.31600000e+03 1.09560000e+04]
[8.77200000e+03 8.94000000e+03 1.02840000e+04 2.10360000e+04 1.07052000e+05]]
[[2.11760000e+04 2.12160000e+04 2.14560000e+04 2.28960000e+04 3.15360000e+04]
[5.59896000e+05 5.60064000e+05 5.61408000e+05 5.72160000e+05 6.58176000e+05]]
[[7.62056000e+05 7.62096000e+05 7.62336000e+05 7.63776000e+05 7.72416000e+05]
[3.58318320e+07 3.58320000e+07 3.58333440e+07 3.58440960e+07 3.59301120e+07]]
[[2.74337360e+07 2.74337760e+07 2.74340160e+07 2.74354560e+07 2.74440960e+07]
[2.29323574e+09 2.29323590e+09 2.29323725e+09 2.29324800e+09 2.29333402e+09]]]
可以看到结果合规。
说明:
首先,我想指出您对p、k 和l 的计算不必在循环中。此外,不需要计算k。如果你仔细看,p 和l 的元素是如何计算的,它们只是几何级数(p 的第一个元素除外):
p = [b, b*c, b*c*(c+2), b*c*(c+2)**2, b*c*(c+2)**3, b*c*(c+2)**4, ...]
l = [b*c, b*c*(c+2), b*c*(c+2)**2, b*c*(c+2)**3, b*c*(c+2)**4, b*c*(c+2)**5, ...]
因此,您可以使用np.logspace 而不是那个循环。不幸的是,np.logspace 不支持将base 参数作为数组,所以我们别无选择,只能使用np.vectorize,这只是一个循环......
komp 的计算很容易矢量化。您可以在我的示例中看到它。那里不需要循环。
另外,正如我已经在评论中指出的那样,您的类不必是类,所以我冒昧地将其更改为函数。
接下来,注意输入参数c被覆盖了,所以我把它去掉了。变量y 从未使用过。 (另外,你可以像y = c + a * b * np.sign(a - b)一样计算它)
最后,我想指出的是,使用 np.append 创建 NumPy 数组的效率非常低(正如 @kabanus 所指出的那样),因此您应该始终尝试一次创建它们 - 没有循环,没有附加.
P.S.:我在代码中使用了 np.atleast_2d 和 np.squeeze,可能不清楚我为什么这样做。它们对于避免使用 if-else 子句来检查数组 l 的维度是必要的。你可以print中间结果来看看那里到底发生了什么。没什么难的。