Ошибка: 'float' object is not callable при вызове функции
Есть код, который выполняет некоторые расчеты, он разделен на два класса и функции внутри них.
import math
class SimilarCalculations:
def __init__(self, diameter, length, mass_flow_rate, viscosity, density):
self.diameter = diameter
self.length = length
self.mass_flow_rate = mass_flow_rate
self.viscosity = viscosity
self.density = density
def injector_nozzle_area(self):
return (math.pi * self.diameter ** 2) / 4
def reynolds_number(self):
return (4 * self.mass_flow_rate) / (math.pi * self.diameter * self.viscosity)
def average_speed(self):
return self.mass_flow_rate / (self.density * self.injector_nozzle_area())
class LiquidJetInjector(SimilarCalculations):
def __init__(self, density_comb, sigma_fuel):
SimilarCalculations.__init__(self, diameter, length, mass_flow_rate, viscosity, density)
self.reynolds_laminar = 2000
self.reynolds_turbulent = 10000
self.density_comb = density_comb
self.sigma_fuel = sigma_fuel
self.reynolds_number = super().reynolds_number()
self.injector_nozzle_area = super().injector_nozzle_area()
self.average_speed = super().average_speed()
def linear_hydraulic_resistance(self):
if self.reynolds_number < self.reynolds_laminar:
return 64 / self.reynolds_number
elif self.reynolds_laminar <= self.reynolds_number <= self.reynolds_turbulent:
return 0.3164 * self.reynolds_number ** (-0.25)
else:
return 0.031
def injector_losses_inlet(self):
if self.reynolds_number < self.reynolds_laminar:
return 2.2 - 0.726 * math.exp(-74.5 * ((self.viscosity * self.length) / self.mass_flow_rate))
else:
return 1 + 2.65 * self.linear_hydraulic_resistance()
def injector_flow_coefficient(self):
return 1 / (math.sqrt(self.injector_losses_inlet() + self.linear_hydraulic_resistance() *
(self.length / self.diameter)))
def pressure_drop_injector(self):
return self.mass_flow_rate ** 2 / (2 * self.density * self.injector_flow_coefficient() ** 2 *
self.injector_nozzle_area ** 2)
def weber_criterion(self):
return (self.density_comb * self.average_speed ** 2 * self.diameter) / self.sigma_fuel
def media_diameter_spray_droplets(self):
return self.diameter * round(math.pow((27 * math.pi) / 4, 1 / 3.)) * self.weber_criterion() ** (-0.333)
diameter = 0.001
length = 0.01
mass_flow_rate = 0.01899
viscosity = 0.00116
density = 1315
density_comb = 0.1
sigma_fuel = 0.5
calc = SimilarCalculations(diameter, length, mass_flow_rate, viscosity, density)
calc_2 = LiquidJetInjector(density_comb, sigma_fuel)
print(calc.injector_nozzle_area())
print(calc_2.pressure_drop_injector())
Если запустить данный код в данной конфигурации, то он выдаст ошибку:
Traceback (most recent call last):
File "G:\LARIS\src\jet_injector_calc.py", line 79, in <module>
calc_2 = LiquidJetInjector(density_comb, sigma_fuel)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "G:\LARIS\src\jet_injector_calc.py", line 33, in __init__
self.average_speed = super().average_speed()
^^^^^^^^^^^^^^^^^^^^^^^
File "G:\LARIS\src\jet_injector_calc.py", line 19, in average_speed
return self.mass_flow_rate / (self.density * self.injector_nozzle_area())
^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'float' object is not callable
Но, если в строчке 19 заменить self.injector_nozzle_area() на self.injector_nozzle_area, то код будет корректно работать без ошибок.
Почему так происходит?
Ответы (1 шт):
Почему выходит ошибка вам написали в комментарии - вы перекрываете унаследованную функцию результатом её вызова.
При этом, судя по всему, вам вообще не нужно наследование, лучше просто инициализируйте класс для вычислений и пользуйтесь им где вам нужно, например как у вас сейчас в конструкторе:
class LiquidJetInjector():
def __init__(self, density_comb, sigma_fuel):
self.calc = SimilarCalculations(diameter, length, mass_flow_rate, viscosity, density)
...
self.reynolds_number = self.calc.reynolds_number()
self.injector_nozzle_area = self.calc.injector_nozzle_area()
self.average_speed = self.calc.average_speed()
В данном случае я на всякий случай записал калькулятор в поле self.calc, чтобы им можно было и потом пользоваться. Но если он дальше не нужен, можно было бы ограничиться локальной переменной calc.
Наследование нужно для других вещей - для расширения функционала базового класса. В вашем же случае достаточно того, что называется композицией. Пример я привёл выше - просто инициализируете нужный вам класс в конструкторе, и пользуетесь им.
Кстати, очень странно, что часть переменных вы прямо передали в класс LiquidJetInjector, а часть передали неявно, как глобальные. Не делайте так. Передавайте все переменные, нужные классу, в явном виде в его конструктор.