2017-05-03 34 views
1

当我尝试unickickle复杂的枚举实例时,我总是得到“ValueError:BLUE不是有效的颜色”。如何在Python中腌制复杂的枚举值

有没有办法如何泡菜和unpickle?

from pickle import loads, dumps 
from enum import Enum 


class ColorType(object): 

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

    def __str__(self): 
     return self.name 


class Colors(Enum): 
    GREEN = ColorType(1, 'GREEN') 
    BLUE = ColorType(2, 'BLUE') 


color = Colors.BLUE 
print(color is loads(dumps(color))) 

我正在使用Python 2.7。

+0

假设你使用'enum34' backport包然后呢? –

+0

为什么你使用'ColorType'类? IIRC'Enum'直接支持更复杂的值类型,包括其他方法,而不使用单独的类对象。有关示例,请参阅文档。 –

+0

是的,我安装了'enum34',这个例子只是为了说明更复杂的实际问题。 –

回答

2

不要使用自定义类作为枚举值;这里没有必要。你的具体例子并不需要一个单独的类在所有的,你可以只使用:

class Colors(Enum): 
    GREEN = 1 
    BLUE = 2 

    def __str__(self): 
     return self.name 

    @property 
    def counter(self): 
     return self.value 

这有更好str().counter行为;您的代码要求str()应用于Color.<name>.value而不是直接应用到Color.<name>

对于其他自定义方法和属性,将它们直接放在Enum子类上,它们也将成为枚举成员的一部分。如果您需要每个条目更多的值,请设置一个元组,然后将该元组分开,方法为__init__。该文件有一个很好的Planet example,进一步说明了这一点。

演示:

>>> Colors.BLUE 
<Colors.BLUE: 2> 
>>> Colors.BLUE.value 
2 
>>> Colors.BLUE.counter 
2 
>>> str(Colors.BLUE) 
'BLUE' 
>>> Colors.BLUE is loads(dumps(Colors.BLUE)) 
True 
+0

好的,非常感谢,我直接将我的方法放到'Colors'枚举中。 –

0

这里的问题是基本的平等:

>>> ColorType(2, 'BLUE') == ColorType(2, 'BLUE') 
False 

所以当Colors试图找到的ColorType(2, 'BLUE')的拆封值是失败的比赛。

解决办法很简单:__eq____ne__方法添加到`的ColorType':

class ColorType(object): 

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

    def __str__(self): 
     return self.name 

    def __eq__(self, other): 
     return self.name == other.name and self.counter == other.counter 

    def __ne__(self, other): 
     # not needed in Python 3 
     return self.name != other .name or self.counter != other.counter 

NB我@MartijnPieters同意,在大多数情况下,你应该只添加所需的功能到Enum本身。

+0

但是为什么第二类*在第一个地方*? –

+0

如果不使用'aenum',获取属性访问的一个简单方法就是混入'namedtuple',例如,关键是它可以在你需要的时候完成。 (不,我自己没有用例。) –

+0

在Python 3中,'__ne__'是可选的,因为['__ne__'委托给'__eq__'并反转结果](https://docs.python.org/3/reference/datamodel.html#object.__ne__ )。不幸的是,在Python 2中,你并不那么幸运。 –