Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 类变量作为封闭类的实例_Python_Class_Enums - Fatal编程技术网

Python 类变量作为封闭类的实例

Python 类变量作为封闭类的实例,python,class,enums,Python,Class,Enums,我知道Python可以执行枚举(有点不错),但它所执行的枚举类型非常原始。例如,我可以这样做: from enum import Enum class Color(Enum): BLACK = 'black' WHITE = 'white' print(Color.BLACK.value) 这很好,但是如果我希望每种颜色都有一个名称和十六进制值呢?我有几种选择(比如让枚举值成为字典),但我更喜欢Java执行枚举的方式。在Java中,允许枚举像类一样具有字段和方法。因此,通常情况下,

我知道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’”。我不能在该类中创建类的实例吗?我的黑客解决方案是这样做:

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)

这很好用。但是,我的问题是,为什么类中不允许字段?我可以添加一些内容或对其进行重组以使其成为允许的吗?提前感谢您的回答

使用元组值和
@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)
:

至于为什么代码不能工作,Python类定义是必不可少的。当您试图构造
Color
实例时,
Color
类还不存在。

鸡和蛋问题 你会遇到“鸡和蛋”的问题。因为如果构造一个类,Python必须将属性和函数的名称与属性和函数的值相关联。如果访问
Color.abc
,它将查看是否找到了相应的名称,并返回值/函数定义

但现在有一个问题。如果你写:

class Foo(object):
    bar = Foo()
这里我们首先定义
Color
类,然后向
Color
类添加属性。我们可以在以后再做,因为现在已经定义了对象

将值附加到
Enum
对象 我们还可以将值附加到
Enum
对象:

from enum import Enum

class Color(Enum):

  white = {'name': 'white', 'hex': '#fff'}
  black = {'name': 'black', 'hex': '#000'}

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

  @property
  def hex(self):
    return self.value['hex']
从枚举导入枚举
类别颜色(枚举):
白色={'name':'white','hex':'#fff'}
黑色={'name':'black','hex':'#000'}
@财产
def名称(自我):
返回self.value['name']
@财产
def十六进制(自身):
返回自身值['hex']

我们可以为每个
Enum
成员附加一个值。例如,我们将
{'name':'white','hex':'#fff'}
附加到
white
。我们以后可以通过
self.value
访问该值。现在我们可以通过定义一个属性函数
def name(self):
来定义
Color.white
上的属性,该函数访问字典的
'name'
键。

我想
user2357112
已经找到了您想要的答案,但是,研究
namedtuples
以及访问属性可能是值得的

命名元组:

from collections import namedtuple
Color = namedtuple('Color', 'name hex')
Black = Color(name='Black', hex='#000')

print(Black.hex)
print(Black.name)
>#000
>Black

命名元组解决方案如何

from collections import namedtuple

color = namedtuple('Color', ['name', 'value'])  # Add attributes as you please

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

print(Color.BLACK.name, Color.BLACK.value)
输出

黑色#000

添加新的就这么简单

Color.RED = color('red', '#ff0')
print(Color.RED.name, Color.RED.value)
红色#ff0


您可以通过使用一个元类来帮助构建
Color
类来做您想做的事情:

class ColorMeta(type):
    def __new__(cls, class_name, parents, attrs):
        NUL = object()  # Sentinel.
        meta_args = attrs.get('meta_args', NUL)
        if meta_args is NUL:
            meta_args = []
        else:
            del attrs['meta_args']  # Clean up so isn't part of class created.

        clsobj = super().__new__(cls, class_name, parents, attrs)

        for meta_arg in meta_args:
            name, hex = meta_arg
            color = clsobj(name, hex)
            setattr(clsobj, name, color)

        return clsobj


class Color(metaclass=ColorMeta):
    meta_args = [('WHITE', '#fff'),
                 ('BLACK', '#000'),]

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


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

枚举直接支持这个用例。该库的文档包括以下内容:

如果定义了
\uuuu new\uuuu()
\uuuu init\uuuu()
,则枚举成员的值将传递给这些方法:

>>> 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
因此,对于您的特定示例,只需定义一个
\uuuu init\uuu
方法:

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
作为属性,因为这是一个保留属性(用于反映枚举值名称,此处为
BLACK
WHITE
):

>Color.BLACK
>>>Color.BLACK.name
“黑色”
>>>Color.BLACK.Color\u名称
“黑色”
>>>颜色。黑色。十六进制
'#000'
您仍然可以使用
@属性
覆盖
名称
属性,但我不会偏离这里的标准


我使用这种技术在我的中定义病毒状态,定义下一个状态名称和每个条目的方向更改

Python必须构造一个
Color
类,其参数为
BLACK=Color('BLACK','#000')
。但那时,
颜色
还没有定义。所以这就像“鸡和蛋”的问题。类不是字典。只有字典才是字典。更准确的说法是类有一个dict,或者(如果你想更强调dict的话)类是围绕dict的包装。我认为有两个这样的颜色类可能会有点混淆(
color
tuple
的子类,这是
namedtuple()
工厂函数返回的)。
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129
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)
>>> Color.BLACK
<Color.BLACK: ('black', '#000')>
>>> Color.BLACK.name
'BLACK'
>>> Color.BLACK.color_name
'black'
>>> Color.BLACK.hex
'#000'