pythonpython-3.xoopdebuggingcalculation

Errors when using abstract methods in Python when calculating


I am writing code for calculations, I started testing and ran into a problem, an error pops up when trying to get an answer:

Traceback (most recent call last):
  File "G:\LARIS\tests\test_centrifugal_injector.py", line 51, in <module>
    test()
  File "G:\LARIS\tests\test_centrifugal_injector.py", line 34, in test
    print(injector.equivalent_geometric_characteristic_injector)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\iru\AppData\Local\Programs\Python\Python312\Lib\functools.py", line 995, in __get__
    val = self.func(instance)
          ^^^^^^^^^^^^^^^^^^^
  File "G:\LARIS\src\centrifugal_injector_calc.py", line 89, in equivalent_geometric_characteristic_injector
    return self.geometric_characteristics_injector() / (1 + self.coefficient_friction /
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'float' object is not callable

How can I fix it?

The main file:

from dataclasses import dataclass
from functools import cached_property
from abc import ABC, abstractmethod


@dataclass(frozen=True)
class Injector(ABC):
    @abstractmethod
    def geometric_characteristics_injector(self) -> float:
        """"""
        raise NotImplementedError

    @cached_property
    def equivalent_geometric_characteristic_injector(self) -> float:
        """Возвращает эквивалентную геометрическую характеристику"""
        return self.geometric_characteristics_injector() / 2.0


@dataclass(frozen=True)
class CentrifugalInjector(Injector):
    @cached_property
    def geometric_characteristics_injector(self) -> float:
        """Возвращает геометрическую характеристику центробежной форсунки"""
        return 2.0


@dataclass(frozen=True)
class ScrewInjector(Injector):
    @cached_property
    def geometric_characteristics_injector(self) -> float:
        """Возвращает геометрическую характеристику шнековой форсунки"""
        return 1.0
from src.centrifugal_injector_calc import CentrifugalInjector, ScrewInjector


def test() -> None:
    common = {
        "outer_diameter_injector": 5,
        "side_wall_thickness_injector": 0.1,
        "number_input_tangential_holes": 2,
        "diameter_input_tangential_holes": 0.1,
        "length_input_tangential_holes": 0.1,
        "relative_length_twisting_chamber": 0.1,
        "diameter_injector_nozzle": 0.1,
        "relative_length_injector_nozzle": 0.1,
        "angle_nozzle_axis": 0.1,
        "mass_flow_rate": 0.1,
        "viscosity": 0.1,
        "cross_sectional_area_one_passage_channel": 0.1,
        "density_fuel_component_front_injector": 0.1,
        "density_combustion_products": 0.1,
        "surface_tension_coefficient": 0.1,
    }

    injector = CentrifugalInjector(**common)


if __name__ == "__main__":
    test()

All basic calculations are performed in the main Injector class, and the two remaining ones are responsible for choosing the configuration of this calculation, so that there is no error due to calling the main class directly, it is abstract, like the function that receives configuration data


Solution

  • It looks like there are two problems.

    The geometric_characteristics_injector method is defined as a property, but the * equivalent_geometric_characteristic_injector* method treats it as a method:

    @cached_property
        def equivalent_geometric_characteristic_injector(self) -> float:
            """Возвращает эквивалентную геометрическую характеристику"""
            return self.geometric_characteristics_injector() / (1 + self.coefficient_friction /
                                                                2 * self.radius_tangential_inlet *
                                                                (self.radius_tangential_inlet +
                                                                 self.diameter_input_tangential_holes -
                                                                 self.radius_injector_nozzle))
    

    To fix this, you need to remove the "()" on the first line of the return statement.

    @cached_property
        def equivalent_geometric_characteristic_injector(self) -> float:
            """Возвращает эквивалентную геометрическую характеристику"""
            return self.geometric_characteristics_injector / (1 + self.coefficient_friction /
                                                                2 * self.radius_tangential_inlet *
                                                                (self.radius_tangential_inlet +
                                                                 self.diameter_input_tangential_holes -
                                                                 self.radius_injector_nozzle))
    

    The above will solve the specific error you are encountering. However, it appears that with your specific tests, the ratio_live_section_injector_nozzle will have a negative number inside a square root expression.

    I was able to fix this issue using complex numbers:

    from cmath import sqrt as csqrt
    #other imports
    #...
    
    @cached_property
    def ratio_live_section_injector_nozzle(self) -> float:
        linear_fraction_geometric_characteristic = self.equivalent_geometric_characteristic_injector / (2 * sqrt(2))
        quadratic_fraction_geometric_characteristic = csqrt(self.equivalent_geometric_characteristic_injector ** 2 / 8 - 1 / 27)
    
        result = 1 / ((linear_fraction_geometric_characteristic + quadratic_fraction_geometric_characteristic) ** (1 / 3)
                    + (linear_fraction_geometric_characteristic - quadratic_fraction_geometric_characteristic) **
                    (1 / 3)) ** 2
        return result.real  # Return only the real part