How do I indicate that the .value of an enum is an unstable implementation detail?

huangapple go评论94阅读模式
英文:

How do I indicate that the .value of an enum is an unstable implementation detail?

问题

Here's the translation of the code portion you provided:

  1. 官方的Enum HOWTO有[这个示例](https://docs.python.org/3.11/howto/enum.html#planet):
  2. ```python
  3. class Planet(Enum):
  4. MERCURY = (3.303e+23, 2.4397e6)
  5. VENUS = (4.869e+24, 6.0518e6)
  6. EARTH = (5.976e+24, 6.37814e6)
  7. MARS = (6.421e+23, 3.3972e6)
  8. JUPITER = (1.9e+27, 7.1492e7)
  9. SATURN = (5.688e+26, 6.0268e7)
  10. URANUS = (8.686e+25, 2.5559e7)
  11. NEPTUNE = (1.024e+26, 2.4746e7)
  12. def __init__(self, mass, radius):
  13. self.mass = mass # in kilograms
  14. self.radius = radius # in meters
  15. @property
  16. def surface_gravity(self):
  17. # universal gravitational constant (m3 kg-1 s-2)
  18. G = 6.67300E-11
  19. return G * self.mass / (self.radius * self.radius)
  1. >>> Planet.EARTH.value
  2. (5.976e+24, 6378140.0)
  3. >>> Planet.EARTH.surface_gravity
  4. 9.802652743337129

假设我正在做类似于这样的事情,我希望将.value,即类似于(3.303e+23, 2.4397e6)的元组,视为Planet API的不稳定实现细节。我不希望我的API使用者依赖于它们。相反,我希望他们使用我明确公开的属性,如.surface_gravity

有没有一种传统的方法来指示这一点?

我目前只是在docstring中添加一个注释,像这样:

  1. class Planet(Enum):
  2. """.value is an implementation detail. Use .surface_gravity instead."""

但这似乎太容易被忽略。

如果这是一个普通的类,我只需将其命名为._value而不是.value。但在这里,.value是自动添加的,因为我从Enum中继承,我没有看到覆盖它的方法。

  1. <details>
  2. <summary>英文:</summary>
  3. The official Enum HOWTO has [this example](https://docs.python.org/3.11/howto/enum.html#planet):
  4. ```python
  5. class Planet(Enum):
  6. MERCURY = (3.303e+23, 2.4397e6)
  7. VENUS = (4.869e+24, 6.0518e6)
  8. EARTH = (5.976e+24, 6.37814e6)
  9. MARS = (6.421e+23, 3.3972e6)
  10. JUPITER = (1.9e+27, 7.1492e7)
  11. SATURN = (5.688e+26, 6.0268e7)
  12. URANUS = (8.686e+25, 2.5559e7)
  13. NEPTUNE = (1.024e+26, 2.4746e7)
  14. def __init__(self, mass, radius):
  15. self.mass = mass # in kilograms
  16. self.radius = radius # in meters
  17. @property
  18. def surface_gravity(self):
  19. # universal gravitational constant (m3 kg-1 s-2)
  20. G = 6.67300E-11
  21. return G * self.mass / (self.radius * self.radius)
  1. &gt;&gt;&gt; Planet.EARTH.value
  2. (5.976e+24, 6378140.0)
  3. &gt;&gt;&gt; Planet.EARTH.surface_gravity
  4. 9.802652743337129

Suppose I'm doing something like this, and I want to treat the .values—the tuples like (3.303e+23, 2.4397e6)—as unstable implementation details of the Planet API. I don't want my API consumers to ever rely on them. Instead, I want them to use the properties that I explicitly expose myself, like .surface_gravity.

Is there a conventional way to indicate this?

I'm currently just adding a note in the docstring like this:

  1. class Planet(Enum):
  2. &quot;&quot;&quot;.value is an implementation detail. Use .surface_gravity instead.&quot;&quot;&quot;

But that seems too easy to miss.

If it were a normal class, I would just make it ._value instead of .value. But here, .value is added automatically because I subclassed from Enum, and I don't see a way to override that.

答案1

得分: 2

以下是翻译好的内容:

枚举的确切值几乎总是一个实现细节;之所以将其公开,是因为有时候可以访问它是有用的。

有几种方式来减少它的存在:

  • 更改该枚举类的 repr()
  1. def __repr__(self):
  2. return '<%s.%s>' % (self.__class__.__name__, self._name_)
  • 使用自定义的 __new__ 来使 value 显然是 "错误" 的,以便视为表面重力(或其他)(可能与上面的 __repr__ 结合使用):
  1. def __new__(cls, mass, radius):
  2. member = object.__new__(cls)
  3. member._value_ = len(cls._member_names_)
  4. member.mass = mass
  5. member.radius = radius
  6. return member
  • 您可以与 dataclass 结合使用(它会自动更新 repr):
  1. @dataclass
  2. class PlanetData:
  3. mass: float
  4. radius: float
  5. class Planet(PlanetData, Enum):
  6. MERCURY = (3.303e+23, 2.4397e6)
  7. VENUS = (4.869e+24, 6.0518e6)
  8. # 等等
  9. >>> Planet.VENUS
  10. <Planet.VENUS: mass=4.869e+24, radius=6051800.0>

披露:我是 Python 标准库 Enumenum34 回溯高级枚举 (aenum) 库的作者。

英文:

The exact value of any enum is nearly always an implementation detail; the reason it's exposed at all is that sometimes it's useful to be able to access it.

There are several ways to de-emphasize it's presence:

  • change the repr() of that enum class
  1. def __repr__(self):
  2. return &#39;&lt;%s.%s&gt;&#39; % (self.__class__.__name__, self._name_)
  • have a custom __new__ to make the value obviously "wrong" to treat as surface gratity (or whatever) (probably combined with the __repr__ above):
  1. def __new__(cls, mass, radius):
  2. member = object.__new__(cls):
  3. member._value_ = len(cls._member_names_)
  4. member.mass = mass
  5. member.radius = radius
  6. return member
  • you could combine with a dataclass (which automatically updates the repr):
  1. @dataclass
  2. class PlanetData:
  3. mass: float
  4. radius: float
  5. class Planet(PlanetData, Enum):
  6. MERCURY = (3.303e+23, 2.4397e6)
  7. VENUS = (4.869e+24, 6.0518e6)
  8. # etc
  9. &gt;&gt;&gt; Planet.VENUS
  10. &lt;Planet.VENUS: mass=4.869e+24, radius=6051800.0&gt;

Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

答案2

得分: 0

以下是翻译好的部分:

问题之一是您有一个执行两个任务的单一类:

  1. 存储物理常数
  2. 进行计算

个人而言,我会将计算分离成一个接受来自枚举的行星参数的全局函数:

  1. def surface_gravity(planet: Planet):
  2. #...与原实现相同,只需使用 `planet` 替代 `self`。

如果您需要进一步的翻译或帮助,请告诉我。

英文:

One of the problems is that you have a single class that is doing two things:

  1. Storing physical constants
  2. Doing a calculation

Personally, I would separate the calculation into a global function that accepts a planet from the enum:

  1. def surface_gravity(planet: Planet):
  2. #...same implementation except use `planet` instead of `self`.

huangapple
  • 本文由 发表于 2023年4月20日 06:14:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76059187.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定