Вы не сможете создать экземпляр класса с массивами 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
, это просто геометрические прогрессии (кроме 1-го элемента 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)
)
И, наконец, я хотел бы отметить, что создание массивов NumPy с np.append
очень неэффективно (как было отмечено @kabanus),поэтому вы всегда должны пытаться создать их сразу - без циклов, без добавления.
PS: я использовал np.atleast_2d
и np.squeeze
в своем коде, и может быть неясно, почему я это сделал.Они необходимы, чтобы избежать предложений if-else, где мы проверяли бы размеры массива l
.Вы можете print
промежуточные результаты, чтобы увидеть, что на самом деле там происходит.Ничего сложного.