如何优化含有大量常量的代码?

1 投票
2 回答
64 浏览
提问于 2025-04-14 15:44

这里有一段代码,用来做一些数学计算。这段代码不仅计算数值,还检查这些数值是否在一个可以接受的范围内。为了存储这个范围,代码中使用了类里的常量,但这样会导致常量的数量变得很多。有没有办法来优化一下这个情况呢?

from dataclasses import dataclass
from enum import Enum


class RecommendedNumberInputHoles(Enum):
    MAX_NUMBER_INPUT_HOLES = 6
    MIN_NUMBER_INPUT_HOLES = 2


class RecommendedDiameterRange(Enum):
    MAX_RECOMMENDED_DIAMETER = 2.5
    MIN_RECOMMENDED_DIAMETER = 0.5


class RelativeLength(Enum):
    MAX_RELATIVE_LENGTH = 6.0
    MIN_RELATIVE_LENGTH = 1.5


@dataclass(frozen=True, slots=True)
class CentrifugalLiquidInjector:
    outer_diameter_injector: float
    side_wall_thickness_injector: float
    number_input_tangential_holes: float

    diameter_input_tangential_holes: float
    length_input_tangential_holes: float

    relative_length_twisting_chamber: float

    def __post_init__(self):
        if not (RecommendedNumberInputHoles.MIN_NUMBER_INPUT_HOLES.value >= self.number_input_tangential_holes <=
                RecommendedDiameterRange.MAX_RECOMMENDED_DIAMETER.value):
            raise ValueError(f"Значение {self.number_input_tangential_holes} количества входных тангенциальных"
                             f"отверстий не входит в рекомендуемый диапазон"
                             f"[{RecommendedNumberInputHoles.MIN_NUMBER_INPUT_HOLES.value}..."
                             f"{RecommendedDiameterRange.MAX_RECOMMENDED_DIAMETER.value}]")

        if not (RecommendedDiameterRange.MIN_RECOMMENDED_DIAMETER.value >= self.diameter_input_tangential_holes <=
                RecommendedDiameterRange.MAX_RECOMMENDED_DIAMETER.value):
            raise ValueError(f"Значение {self.diameter_input_tangential_holes} диаметров входных тангенциальных"
                             f"отверстий не входит в рекомендуемый диапазон"
                             f"[{RecommendedDiameterRange.MIN_RECOMMENDED_DIAMETER.value}..."
                             f"{RecommendedDiameterRange.MAX_RECOMMENDED_DIAMETER.value}]")

    @property
    def diameter_twisting_chamber_injector(self) -> float:
        return self.outer_diameter_injector - 2 * self.side_wall_thickness_injector

    @property
    def relative_length_tangential_hole(self) -> float:
        value_relative_length = self.length_input_tangential_holes / self.diameter_input_tangential_holes

        if not(RelativeLength.MIN_RELATIVE_LENGTH.value >= value_relative_length <=
               RelativeLength.MAX_RELATIVE_LENGTH.value):
            raise ValueError(f"Значение {value_relative_length} относительной длины входного тангенциального отверстия"
                             f"не входит в допустимый диапазон [{RelativeLength.MIN_RELATIVE_LENGTH.value}..."
                             f"{RelativeLength.MAX_RELATIVE_LENGTH.value}]")
        else:
            return value_relative_length

2 个回答

0

如果不需要使用枚举(Enums),你可以把所有常量放在一个MappingProxyType里。

from types import MappingProxyType
const: MappingProxyType = MappingProxyType({"MAX_NUM_IN_HOLES" = 6, "MIN_NUM_IN_HOLES" = 2, "MAX_REC_DIAMETER" = 2.5, "MIN_REC_DIAMETER" = 0.5, "MAX_REL_LENGTH" = 6.0, "MIN_REL_LENGTH" = 1.5})

根据Python文档的说明:[MappingProxyType是一个] "只读的映射代理。它提供了一个动态视图,能反映映射中条目的变化,也就是说,当映射发生变化时,这个视图会显示这些变化。”

它的工作方式就像一个简单的Python字典(dict),你可以通过索引来访问它的元素。如果你不保留对原始字典的引用,它就是不可变的。

1
  1. 如果你一定要用Enum这种方式,建议你使用IntEnum,因为IntEnum的值是整数,这样你就不用在每次使用的时候加上.value了。

  2. 如果你想检查某个值是否在一个范围内,Python里比较常用的方法就是用in这个操作符。所以你可以考虑添加一个自定义的范围类,这样就能像这样操作(内置的range只能处理整数):

class AcceptableRange:
    def __init__(self, min, max):
        self.min = min
        self.max = max

    def __contains__(self, val):
        """Return true if the value is within the acceptable range of values"""
        return self.min <= val <= self.max

    def __repr__(self):
        """Format the range for e.g. pasting into error messages"""
        return f"[{self.min}...{self.max}]"

# then use like so:
RelativeLengthRange = AcceptableRange(1.5, 6.0)

...
         # in property relative_length_tangential_hole()
         if value_relative_length not in RelativeLengthRange:
            raise ValueError(f"Значение {value_relative_length} относительной длины входного тангенциального отверстия " # (nitpick: add space)
                             f"не входит в допустимый диапазон {RelativeLengthRange!r}")
         # rest of function

撰写回答