Ошибки при использовании абстрактных методов в Python при расчете

Пишу код для расчетов, начал тестирование и столкнулся с проблемой, при попытке получить ответ выскакивает ошибка:

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

Как я могу это исправить?

Основной файл:

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()

Все базовые вычисления выполняются в основном Injector классе, а два оставшихся отвечают за выбор конфигурации этого расчета, чтобы не было ошибки из-за прямого вызова основного класса, он абстрактен, как и функция, получающая конфигурацию. данные

Приведите, пожалуйста, минимальный воспроизводимый пример - акцент на минимальном.

Thierry Lathuille 09.07.2024 19:04

Кроме того, ваша обратная трассировка ошибок ссылается на два разных файла, а вы предоставили только часть одного (какого?)

Thierry Lathuille 09.07.2024 19:06

@ThierryLathuille Да, я ошибся, добавил второй файл при запуске первого

DYNAMIC AEROSPACE 09.07.2024 19:08

В ваших файлах слишком много кода, оставьте только минимум, чтобы воспроизвести проблему.

Thierry Lathuille 09.07.2024 19:09

@ThierryLathuille ОК, вот сокращенный пример кода

DYNAMIC AEROSPACE 09.07.2024 19:17

Если self.geometric_characteristics_injector является свойством, то вам следует использовать его с self.geometric_characteristics_injector (который является числом с плавающей запятой), а не self.geometric_characteristics_injector(), которое пытается вызвать это число с плавающей запятой.

Thierry Lathuille 09.07.2024 19:22

@ThierryLathuille Ладно, допустим, это не будет свойство, но тогда будет еще одна ошибка в работе, но как заставить код работать в этом случае?

DYNAMIC AEROSPACE 09.07.2024 19:27

Я не понимаю ваш последний вопрос. Если это не свойство, а обычный метод, просто вызовите его, как вы это сделали. Если это свойство, просто используйте его, как если бы это был обычный атрибут.

Thierry Lathuille 09.07.2024 19:29
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
8
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Расширяя ответ @Thierry Lathuille в их комментарии:

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

Вы объявляете метод geometric_characteristics_injector, который сам по себе должен вызываться с помощью self.geometric_characteristics_injector().

Но декоратор @cached_property перезаписывает этот метод специальным аксессором, который ведет себя как свойство. Итак, после оформления правильно использовать self.geometric_characteristics_injector без скобок.

Поэтому уберите скобки в

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

Если используемый вами API требует, чтобы этот метод вел себя как метод, вам следует использовать декоратор @cached вместо @cached_property. Тогда вы можете оставить скобки.

Это не совсем то, что нужно. Посмотрите, код построен таким образом, что Geometric_characteristics_injector — это абстрактный метод, принимающий значение одного из двух оставшихся классов, в зависимости от того, какой из них мы используем. Вы не можете просто оставить значение в этой функции

DYNAMIC AEROSPACE 09.07.2024 20:44
Ответ принят как подходящий

Похоже, есть две проблемы.

Метод Geometric_characteristics_injector определен как свойство, но метод *equiqual_geometric_characteristic_injector* обрабатывает его как метод:

@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))

Чтобы это исправить, вам нужно удалить «()» в первой строке оператора return.

@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))

Вышеупомянутое решит конкретную ошибку, с которой вы столкнулись. Однако похоже, что в ваших конкретных тестах соотношение_live_section_injector_nozzle будет иметь отрицательное число внутри выражения квадратного корня.

Мне удалось решить эту проблему, используя комплексные числа:

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

Другие вопросы по теме