当前位置: 首页 > 面试题库 >

是否可以在枚举中定义类常量?

蒋阳华
2023-03-14
问题内容

Python
3.4引入了一个新模块enum,该模块向该语言添加了枚举类型。的文档enum.Enum提供了一个示例来演示如何扩展它:

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

此示例还演示了一个问题Enum:在surface_gravity()property方法中,G定义了一个常量,该常量通常在类级别定义-
但是尝试在a级别内执行此操作Enum只会将其添加为枚举的成员之一,因此,在方法内部定义。

如果该类想在其他方法中使用此常量,则也必须在其中定义它,这显然不是理想的选择。

有什么方法可以在中定义类常量Enum,也可以通过一些解决方法来达到相同的效果?


问题答案:

这是高级行为,在创建的90%以上的枚举中将不需要此行为。

根据文档:

允许的规则如下:_sunder_名称(以单个下划线开头和结尾)由枚举保留,不能使用;枚举中定义的所有其他属性都将成为该枚举的成员,但__dunder__名称和descriptors(方法也是描述符)除外。

因此,如果您想要一个类常量,则有多种选择:

  • 在其中创建 __init__
  • 创建类后添加
  • 使用mixin
  • 创建自己的 descriptor

在创建__init__类后在其中创建常量并将其添加都会使所有类信息都没有聚集在一个地方。

当然可以在适当的时候使用[Mixins]有关示例,请参见dnozay的答案,但是通过Enum内置具有实际常量的基类也可以简化这种情况。

首先,将在以下示例中使用的常量:

class Constant:  # use Constant(object) if in Python 2
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)

和一次性Enum示例:

from enum import Enum

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)

    # universal gravitational constant
    G = Constant(6.67300E-11)

    def __init__(self, mass, radius):
        self.mass = mass       # in kilograms
        self.radius = radius   # in meters
    @property
    def surface_gravity(self):
        return self.G * self.mass / (self.radius * self.radius)

print(Planet.__dict__['G'])             # Constant(6.673e-11)
print(Planet.G)                         # 6.673e-11
print(Planet.NEPTUNE.G)                 # 6.673e-11
print(Planet.SATURN.surface_gravity)    # 10.44978014597121

最后,多用途枚举示例:

from enum import Enum

class AstronomicalObject(Enum):

    # universal gravitational constant
    G = Constant(6.67300E-11)

    def __init__(self, mass, radius):
        self.mass = mass
        self.radius = radius
    @property
    def surface_gravity(self):
        return self.G * self.mass / (self.radius * self.radius)

class Planet(AstronomicalObject):
    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)

class Asteroid(AstronomicalObject):
    CERES = (9.4e+20 , 4.75e+5)
    PALLAS = (2.068e+20, 2.72e+5)
    JUNOS = (2.82e+19, 2.29e+5)
    VESTA = (2.632e+20 ,2.62e+5

Planet.MERCURY.surface_gravity    # 3.7030267229659395
Asteroid.CERES.surface_gravity    # 0.27801085872576176

注意事项

Constant G还真不是。一个人可以重新绑定G到其他东西:

Planet.G = 1

如果确实需要将其保持不变(也就是不可重新绑定),请使用新的aenum库[1],该库将阻止尝试重新分配constants及其Enum成员。

1披露:我是Python
stdlibEnum
enum34backport和Advanced
Enumeration(aenum) 库的作者。



 类似资料:
  • 问题内容: 在Java中有可能发生这种情况吗?可以为Java中的枚举元素分配自定义数值吗? 问题答案:

  • 问题内容: 我正在尝试将我的某些Obj-C类转换为Swift。还有其他一些Obj- C类仍在该转换后的类中使用枚举。我在“预发布文档”中进行了搜索,但找不到它,或者我错过了它。有没有办法在Obj- C类中使用Swift枚举?或指向此问题的文档的链接? 这就是我在旧的Obj-C代码和新的Swift代码中声明枚举的方式。 我以前的Obj-C代码: 我的新Swift代码: 更新: 从答案。在Swift低

  • enum 关键字允许创建一个代表数个可能变量的数据的类型(原文:The enum keyword allows the creation of a type which may be one of a few different variants.若您对此句有 更好的翻译或理解,希望指出来,谢谢。)。在 struct 中任何合法的变量在 enum 同样是合法的。 // 隐藏未使用代码警告的属性。

  • 问题内容: 我想采用一个现有的枚举,并向其添加更多元素,如下所示: 这在Java中可行吗? 问题答案: 不,你无法使用Java执行此操作。除了别的什么,d大概就是A(扩展的“正常”想法)的一个实例,但是只知道这一点的用户却一无所知-这违背了枚举作为一组众所周知的集合的观点。价值观。 如果你可以告诉我们更多有关如何使用它的信息,我们可能会建议其他解决方案。

  • 问题内容: 有什么方法可以在Java枚举声明中定义静态最终变量(有效常量)? 我想要在一个地方定义BAR(1 … n)值的字符串文字值: 对于以上代码,我收到以下错误消息: 在定义字段之前无法引用它 。 问题答案: 正如IntelliJ IDEA建议的那样,在提取常量时-制作静态嵌套类。此方法有效:

  • 为什么要在C++11中编译: 但这不是: