首页 > 解决方案 > 如何 Cythonize Python Enum mixin 类?

问题描述

我有一个 Enum mixin (serde_enum.py) 类型,它将转储/加载方法添加到 Enum 以进行序列化/反序列化,看起来像这样:

from enum import Enum

class Primitive:

    def load(self):
        pass

    def dump(self):
        pass

我可以创建一个Apple像这样的枚举,它具有额外的load()dump()方法:

In [1]: import serde_enum                                                                                                        

In [2]: from enum import Enum                                                                                                    

In [3]: Apple = Enum('Apple', ['RED', 'GREEN', 'BLUE'], type=serde_enum.Primitive)                                               

In [4]: Apple.__members__                                                                                                        
Out[4]: 
mappingproxy({'RED': <Apple.RED: 1>,
              'GREEN': <Apple.GREEN: 2>,
              'BLUE': <Apple.BLUE: 3>})

In [5]: Apple.RED.dump                                                                                                           
Out[5]: <bound method Primitive.dump of <Apple.RED: 1>>

In [6]: r = Apple(1)

现在,如果我尝试对 mixin 类进行 cythonize(以加快慢速加载/转储代码的速度),它会破坏枚举。这是我的 cython 代码(serde_enum.pyx):

# cython: language_level=3
from enum import Enum

cdef class Primitive:

    cpdef load(self):
        pass

    cpdef dump(self):
        pass


class SerDeEnum(Primitive, Enum):
    pass

但现在:

In [1]: from enum import Enum                                                                                                    

In [2]: import serde_enum                                                                                                        

In [3]: Apple = Enum('Apple', ['RED', 'GREEN', 'BLUE'], type=serde_enum.Primitive)                                               

In [4]: Apple.__members__                                                                                                        
Out[4]: 
mappingproxy({'RED': <Apple.RED: <serde_enum.Primitive object at 0x7ff91adc2ea0>>,
              'GREEN': <Apple.GREEN: <serde_enum.Primitive object at 0x7ff91adc2eb0>>,
              'BLUE': <Apple.BLUE: <serde_enum.Primitive object at 0x7ff91adc2ec0>>})

In [5]: Apple.RED.dump                                                                                                           
Out[5]: <function Apple.dump>

In [6]: r = Apple(1)                                                                                                             
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-670cfcdec304> in <module>
----> 1 r = Apple(1)

/usr/lib/python3.6/enum.py in __call__(cls, value, names, module, qualname, type, start)
    291         """
    292         if names is None:  # simple value lookup
--> 293             return cls.__new__(cls, value)
    294         # otherwise, functional API: we're creating a new Enum type
    295         return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)

/usr/lib/python3.6/enum.py in __new__(cls, value)
    533                     return member
    534         # still not found -- try _missing_ hook
--> 535         return cls._missing_(value)
    536 
    537     def _generate_next_value_(name, start, count, last_values):

/usr/lib/python3.6/enum.py in _missing_(cls, value)
    546     @classmethod
    547     def _missing_(cls, value):
--> 548         raise ValueError("%r is not a valid %s" % (value, cls.__name__))
    549 
    550     def __repr__(self):

ValueError: 1 is not a valid Apple

SerDeEnum如果我使用上面定义的类通过继承创建带有 mixin 类的枚举,也会发生同样的事情,比如Apple = serde_enum.SerDeEnum('Apple', ['RED', 'GREEN', 'BLUE'])

标签: pythoncython

解决方案


推荐阅读