python - 类变量作为封闭类的实例

标签 python class enums

我知道 Python 可以执行枚举(某种程度上),但它执行的枚举类型非常原始。例如我可以这样做:

from enum import Enum

class Color(Enum):
  BLACK = 'black'
  WHITE = 'white'

print(Color.BLACK.value)

这很好,但是如果我希望每种颜色都有一个名称和一个十六进制值怎么办?我有几种选择(比如将枚举值设为字典),但我更喜欢 Java 枚举的方式。在 Java 中,枚举可以像类一样拥有字段和方法。所以通常当一种语言只支持像上面例子这样的简单枚举时,我会重构类似于以下的代码:

class Color(object):
  BLACK = Color('black', '#000')
  WHITE = Color('white', '#fff')

  def __init__(self, name, hex):
    self.name = name
    self.hex = hex

print(Color.BLACK.name + ' ' + Color.BLACK.hex)

现在我可以拥有多个值、自定义方法,并且可以按名称引用不同的字段,因为每种颜色都是一个对象。我已经用多种语言完成了此操作,但没有问题,但 Python 似乎提示“名称‘Color’未定义”。我不能在那个类中创建一个类的实例吗?我的 hacky 解决方案是这样做:

class Color(object):
  def __init__(self, name, hex):
    self.name = name
    self.hex = hex

Color.BLACK = Color('black', '#000')
Color.WHITE = Color('white', '#fff')

print(Color.BLACK.name + ' ' + Color.BLACK.hex)

效果很好。不过,我的问题是为什么类内不允许使用这些字段?我可以添加一些东西或重组它以允许它吗?提前感谢任何答案!

最佳答案

枚举直接支持这个用例。该库的文档在 Planet example in the examples section 中对此进行了介绍:

If __new__() or __init__() is defined the value of the enum member will be passed to those methods:

>>> class Planet(Enum):
...     MERCURY = (3.303e+23, 2.4397e6)
...     # ...
...
...     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

因此对于您的特定示例,只需定义一个 __init__ 方法:

from enum import Enum

class Color(Enum):
    BLACK = ('black', '#000')
    WHITE = ('white', '#fff')

    def __init__(self, color_name, hex):
        self.color_name = color_name
        self.hex = hex 

print(Color.BLACK.color_name + ' ' + Color.BLACK.hex)

我没有使用 name 作为属性,因为那是一个保留属性(用于反射(reflect)枚举值名称,这里是 BLACKWHITE):

>>> Color.BLACK
<Color.BLACK: ('black', '#000')>
>>> Color.BLACK.name
'BLACK'
>>> Color.BLACK.color_name
'black'
>>> Color.BLACK.hex
'#000'

您仍然可以使用 @property 覆盖 name 属性,但我不会偏离此处的标准。

我使用这种技术来定义我的 Advent of Code day 22 solution 中的病毒状态,为每个条目定义下一个状态名称和方向变化。

关于python - 类变量作为封闭类的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48045518/

相关文章:

android - 如何将字符串转换为类名

sql - PostgreSQL 8.2.9 枚举类型

arrays - Delphi XE6 中使用枚举声明数组错误

c++ - '=' 应初始化所有枚举成员或仅初始化第一个;

python - 强制所有列都是 pandas 中的字符串

python - pcolorfast 上的 matplotlib MemoryError

Python 类继承 - 如何使用它连接到 mysql 数据库

python - 将视频与具有额外属性的 ffmpeg(或替代品)合并(叠加)

事件 OOPS 实现后的 Python Tkinter

c++ - 什么是 C++ 内联类?