3

以下不适用于我,使用 Python 3.4.7,ruamel.yaml 版本 0.15.35:

import sys
import enum

import ruamel.yaml
from ruamel.yaml import yaml_object
yaml = ruamel.yaml.YAML()

@yaml_object(yaml)
class Speed(enum.IntEnum):
    Reverse = 0
    Neutral = 1
    Low = 2
    Drive = 3
    Park = 999

print("Neutral:", repr(Speed.Neutral))

yaml.dump(Speed.Neutral, sys.stdout)

我得到一个完全合理的repr

Neutral: <Speed.Neutral: 1>

.dump()加薪:

ruamel.yaml.representer.RepresenterError: cannot represent an object: <enum 'Speed'>

如果enum不支持,我可以做些什么来扩展enum我正在使用的类(或enum.IntEnum我创建的子类),例如 dunder 方法?

4

2 回答 2

6

enum不支持开箱即用,主要是因为默认dump方法是安全的,因此不支持任意 Python 对象。这种安全性也排除enum了标准库中的类型。

您应该按照ruamel.yaml 文档to_yaml classmethod中的说明向您的Speed类添加一个:

import sys
import enum

import ruamel.yaml
from ruamel.yaml import yaml_object
yaml = ruamel.yaml.YAML()

@yaml_object(yaml)
class Speed(enum.IntEnum):
    Reverse = 0
    Neutral = 1
    Low = 2
    Drive = 3
    Park = 999

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(
            u'!Speed',
            '{}-{}'.format(node._name_, node._value_)
        )

yaml.dump(Speed.Neutral, sys.stdout)

这使:

!Speed Neutral-1
...

您当然可以根据自己的喜好调整字符串表示形式(并添加 afrom_yaml以便能够重新加载输出)。

请注意,您不能yaml_tag像文档示例中那样添加,因为这会干扰enum值。

于 2017-12-29T07:25:14.143 回答
1

我认为您需要按值传递枚举。

https://docs.python.org/3/library/enum.html#programmatic-access-to-enumeration-members-and-their-attributes

yaml.dump(Speed.Neutral.value, sys.stdout)

添加 @classmethod 的扩展答案,它在传递时调用 .value

http://yaml.readthedocs.io/en/latest/dumpcls.html

import sys
import enum
import ruamel.yaml
from ruamel.yaml import yaml_object
yaml = ruamel.yaml.YAML()

@yaml_object(yaml)
class Speed(enum.IntEnum):
    Reverse = 0
    Neutral = 1
    Low = 2
    Drive = 3
    Park = 999

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(u'!enum:', u'{.value}'.format(node))
于 2017-12-29T04:40:45.993 回答