类变量作为封闭类的实例

Blu*_*ial 3 python enums class

我知道Python可以做枚举(很好),但它所做的枚举类型非常原始.例如,我可以这样做:

from enum import Enum

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

print(Color.BLACK.value)
Run Code Online (Sandbox Code Playgroud)

这很好但是如果我希望每种颜色都有名称和十六进制值呢?我有几个选项(比如使枚举值成为字典)但我更喜欢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)
Run Code Online (Sandbox Code Playgroud)

现在我可以有多个值,自定义方法,并且可以按名称引用不同的字段,因为每种颜色都是一个对象.我已经用几种语言做了这个没有问题,但Python似乎抱怨"名称'颜色'没有定义".我可以不在该类中创建类的实例吗?我的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)
Run Code Online (Sandbox Code Playgroud)

哪个工作得很好.不过,我的问题是为什么课堂内不允许这些字段?我可以添加一些东西或重组它以使其允许吗?提前感谢您的任何答案!

Mar*_*ers 9

枚举直接支持此用例.该库的文档在示例部分Planet示例中介绍了这一点:

如果__new__()__init__()定义了枚举成员的值将传递给这些方法:

>>> 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)
Run Code Online (Sandbox Code Playgroud)

[...]

>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129
Run Code Online (Sandbox Code Playgroud)

因此,对于您的具体示例,只需定义一个__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)
Run Code Online (Sandbox Code Playgroud)

我没有name用作属性,因为这是一个保留属性(用于反映枚举值名称,此处BLACKWHITE):

>>> Color.BLACK
<Color.BLACK: ('black', '#000')>
>>> Color.BLACK.name
'BLACK'
>>> Color.BLACK.color_name
'black'
>>> Color.BLACK.hex
'#000'
Run Code Online (Sandbox Code Playgroud)

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

我使用这种技术在我的Advent of Code第22天解决方案中定义病毒状态,定义下一个状态名称和每个条目的方向更改.


use*_*ica 5

使用元组值和@property访问器为元组元素指定名称:

from enum import Enum

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

    @property
    def name(self):
        return self.value[0]

    @property
    def hex(self):
        return self.value[1]

print(Color.BLACK.name)
print(Color.BLACK.hex)
Run Code Online (Sandbox Code Playgroud)

输出:

black
#000
Run Code Online (Sandbox Code Playgroud)

至于为什么你的代码不起作用,Python类定义是必不可少的.在您尝试构建Color实例时,Color该类尚不存在.