英文:
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:
官方的Enum HOWTO有[这个示例](https://docs.python.org/3.11/howto/enum.html#planet):
```python
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
@property
def surface_gravity(self):
# universal gravitational constant (m3 kg-1 s-2)
G = 6.67300E-11
return G * self.mass / (self.radius * self.radius)
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129
假设我正在做类似于这样的事情,我希望将.value
,即类似于(3.303e+23, 2.4397e6)
的元组,视为Planet
API的不稳定实现细节。我不希望我的API使用者依赖于它们。相反,我希望他们使用我明确公开的属性,如.surface_gravity
。
有没有一种传统的方法来指示这一点?
我目前只是在docstring中添加一个注释,像这样:
class Planet(Enum):
""".value is an implementation detail. Use .surface_gravity instead."""
但这似乎太容易被忽略。
如果这是一个普通的类,我只需将其命名为._value
而不是.value
。但在这里,.value
是自动添加的,因为我从Enum
中继承,我没有看到覆盖它的方法。
<details>
<summary>英文:</summary>
The official Enum HOWTO has [this example](https://docs.python.org/3.11/howto/enum.html#planet):
```python
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
@property
def surface_gravity(self):
# universal gravitational constant (m3 kg-1 s-2)
G = 6.67300E-11
return G * self.mass / (self.radius * self.radius)
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129
Suppose I'm doing something like this, and I want to treat the .value
s—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:
class Planet(Enum):
""".value is an implementation detail. Use .surface_gravity instead."""
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()
:
def __repr__(self):
return '<%s.%s>' % (self.__class__.__name__, self._name_)
- 使用自定义的
__new__
来使value
显然是 "错误" 的,以便视为表面重力(或其他)(可能与上面的__repr__
结合使用):
def __new__(cls, mass, radius):
member = object.__new__(cls)
member._value_ = len(cls._member_names_)
member.mass = mass
member.radius = radius
return member
- 您可以与
dataclass
结合使用(它会自动更新 repr):
@dataclass
class PlanetData:
mass: float
radius: float
class Planet(PlanetData, Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
# 等等
>>> Planet.VENUS
<Planet.VENUS: mass=4.869e+24, radius=6051800.0>
披露:我是 Python 标准库 Enum
、enum34
回溯 和 高级枚举 (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
def __repr__(self):
return '<%s.%s>' % (self.__class__.__name__, self._name_)
- have a custom
__new__
to make thevalue
obviously "wrong" to treat as surface gratity (or whatever) (probably combined with the__repr__
above):
def __new__(cls, mass, radius):
member = object.__new__(cls):
member._value_ = len(cls._member_names_)
member.mass = mass
member.radius = radius
return member
- you could combine with a
dataclass
(which automatically updates the repr):
@dataclass
class PlanetData:
mass: float
radius: float
class Planet(PlanetData, Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
# etc
>>> Planet.VENUS
<Planet.VENUS: mass=4.869e+24, radius=6051800.0>
Disclosure: I am the author of the Python stdlib Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) library.
答案2
得分: 0
以下是翻译好的部分:
问题之一是您有一个执行两个任务的单一类:
- 存储物理常数
- 进行计算
个人而言,我会将计算分离成一个接受来自枚举的行星参数的全局函数:
def surface_gravity(planet: Planet):
#...与原实现相同,只需使用 `planet` 替代 `self`。
如果您需要进一步的翻译或帮助,请告诉我。
英文:
One of the problems is that you have a single class that is doing two things:
- Storing physical constants
- Doing a calculation
Personally, I would separate the calculation into a global function that accepts a planet from the enum:
def surface_gravity(planet: Planet):
#...same implementation except use `planet` instead of `self`.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论