为什么定义顺序在python2中不可用?

为什么定义顺序在python2中不可用?,python,enums,Python,Enums,在python3中,这很有效 >>> from enum import Enum >>> class Animal(Enum): ... cat = [0] ... dog = {1} 但在PythonV2.7.6中,它会引发TypeError,因为当元类尝试调用按值排序的函数时,会出现未处理的异常 我们可以这样修复它: >>> class Animal(Enum): ... __order__ = 'cat dog

在python3中,这很有效

>>> from enum import Enum
>>> class Animal(Enum):
...     cat = [0]
...     dog = {1}
但在PythonV2.7.6中,它会引发
TypeError
,因为当元类尝试调用按值排序的函数时,会出现未处理的异常

我们可以这样修复它:

>>> class Animal(Enum):
...     __order__ = 'cat dog'
...     cat = [0]
...     dog = {1}
我的问题:为什么定义顺序在python2中不可用?我假设这就是python2版本不起作用的原因,如果我错了,请纠正我

如果我们进行如下枚举:

>>> class Animal(Enum):
...     cat = {0, 1}
...     dog = {1, 2}
...     fish = {2, 0}
订购是否安全且定义明确?还是不可靠,比如
dict
set
迭代


编辑:带回溯

In [1]: from enum import Enum

In [2]: class Animal(Enum):
    dog = [0]
    cat = {1}
   ...:     
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-d14b1041d5bc> in <module>()
----> 1 class Animal(Enum):
      2     dog = [0]
      3     cat = {1}
      4 

/usr/local/lib/python2.7/dist-packages/enum/__init__.pyc in __new__(metacls, cls, bases, classdict)
    164         if __order__ is None:
    165             if pyver < 3.0:
--> 166                 __order__ = [name for (name, value) in sorted(members.items(), key=lambda item: item[1])]
    167             else:
    168                 __order__ = classdict._member_names

TypeError: Error when calling the metaclass bases
    can only compare to a set
[1]中的
:从枚举导入枚举
在[2]中:类动物(枚举):
狗=[0]
cat={1}
...:     
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1类动物(枚举):
2狗=[0]
3类={1}
4.
/usr/local/lib/python2.7/dist packages/enum/_init_uuuuuuuuuuu.pyc in_uuuuuuunew_uuuuuuuu(metacls、cls、base、classdict)
164如果“订单”为“无”:
165如果pyver<3.0:
-->166 \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
167其他:
168 \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
TypeError:调用元类基时出错
只能与一套相比

Enum使用了一个新的元类功能:,允许元类使用with
\uuuuuu prepare\uuuuu
钩子指定另一个名称空间实现。这在Python2中不可用

通过让
\uuuuu prepare\uuuuu
返回自定义映射对象,您可以捕获类主体的定义顺序。请参阅和。
\u member\u names
属性是一个列表,是一个有序结构,
Enum
子类中的名称在定义时添加到其中

在Python2中,对于类主体,您必须使用正常的
dict
名称空间,它不保留定义顺序。因此,在上一个示例中,属性顺序取决于所用映射对象的实现细节。在Python2中,如果没有
\uuuuuuuuuuuuuuuu
属性,则enum34按值排序,而在Python2中,这意味着如果项目实际上没有定义顺序,则顺序是任意的。您的集合没有定义的顺序,因为它们不是彼此的严格子集:

>>> {0, 1} < {1, 2}
False
>>> {0, 1} > {1, 2}
False
>>{0,1}<{1,2}
假的
>>> {0, 1} > {1, 2}
假的
因此使用了原始的类名称空间顺序,这是任意的。如果打开,您将看到订单波动:

$ bin/python -R -c $'from enum import Enum\nclass Animal(Enum):\n    cat = {0, 1}\n    dog = {1, 2}\n    fish = {2, 0}\n\nprint list(Animal)\n'
[<Animal.dog: set([1, 2])>, <Animal.cat: set([0, 1])>, <Animal.fish: set([0, 2])>]
$ bin/python -R -c $'from enum import Enum\nclass Animal(Enum):\n    cat = {0, 1}\n    dog = {1, 2}\n    fish = {2, 0}\n\nprint list(Animal)\n'
[<Animal.fish: set([0, 2])>, <Animal.cat: set([0, 1])>, <Animal.dog: set([1, 2])>]
$ bin/python -R -c $'from enum import Enum\nclass Animal(Enum):\n    cat = {0, 1}\n    dog = {1, 2}\n    fish = {2, 0}\n\nprint list(Animal)\n'
[<Animal.fish: set([0, 2])>, <Animal.dog: set([1, 2])>, <Animal.cat: set([0, 1])>]
$bin/python-R-c$'from enum import enum\n类动物(enum):\n cat={0,1}\n dog={1,2}\n fish={2,0}\n\n打印列表(动物)\n
[使使用
set()
对象成为可能,
set
对象确实不可排序

< P>这个问题的修复是Python 2.7.8的一部分,我个人认为旧行为是一个bug;一个<代码>未被提交的应该返回SeaveNeL而不是引发一个异常。
因此,如果您必须使用混合类型的枚举作为值,那么在升级到2.7.8之前,您必须使用
\uuuu order\uuuu
属性。在对异构类型进行排序时,
不能很好地发挥作用是一个遗憾,但这几乎不是
enum34
的错误。

理论上我们不是可以访问python2中的code对象吗,要使用内省恢复定义顺序?@wim:即使是获取定义类的原始代码对象也会很棘手,因为没有函数作用域可以从中提取。您必须首先加载原始模块字节码,这意味着您必须首先依赖于能够访问该数据。这需要支持ng压缩模块存档等。这除了将
STORE\u FAST
字节码顺序映射到它们存储的名称等需要经历的痛苦之外。@wim:还有对Jython、IronPython和PyPy的支持,所以使用字节码之类的实现细节是正确的。是的,好的,有意义。你能评论一下行为吗我们对病理枚举的定义,其中sorted认为它使用的是排序运算符,但实际上使用的是子集运算符?我不确定您的意思;也许这与您所说的引发异常有关?您在Python2中使用的是什么
enum
实现?第一次使用时不会引发
TypeError
示例。这里缺少什么吗?根据pip freeze,它正是enum34 backport,版本
enum34==1.0
。是的,它在Python2.7.6上引发异常,你是说你的不是?!也许你在使用不同的实现Martijn..我在Python2.7.8上使用
enum34==1.0
,没有引发异常;sorting混合类型不会在Python2上引发异常。找到和;这在Python2.7.8中确实发生了更改。