Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.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 正在为枚举使用_prepare__。。。什么';什么是陷阱?_Python_Enums_Metaclass_Python 3.6 - Fatal编程技术网

Python 正在为枚举使用_prepare__。。。什么';什么是陷阱?

Python 正在为枚举使用_prepare__。。。什么';什么是陷阱?,python,enums,metaclass,python-3.6,Python,Enums,Metaclass,Python 3.6,Python的声明性用法要求提供值,而在枚举的最基本用例中,我们实际上并不关心名称和值。我们只关心哨兵自己。在最近阅读了一篇文章之后,我意识到可以使用enum元类的方法来获得这种声明: class Color(Enum): red blue green 而让事情变得如此干涸的实现实际上相当简单: from collections import defaultdict class EnumMeta(type): @classmethod def __pr

Python的声明性用法要求提供值,而在枚举的最基本用例中,我们实际上并不关心名称和值。我们只关心哨兵自己。在最近阅读了一篇文章之后,我意识到可以使用enum元类的方法来获得这种声明:

class Color(Enum):
    red
    blue
    green
而让事情变得如此干涸的实现实际上相当简单:

from collections import defaultdict

class EnumMeta(type):
    @classmethod
    def __prepare__(meta, name, bases):
        return defaultdict(object)

    def __new__(cls, name, bases, classdict):
        classdict.default_factory = None
        return type.__new__(cls, name, bases, classdict)

class Enum(metaclass=EnumMeta):
    pass
在Python 3.6中,提供了帮助解决该问题的接口,但接口仍然很奇怪-需要为每个成员指定
auto()
值,并从不同的基继承,从而修复
\uu repr\uu

class Color(NoValue):
    red = auto()
    blue = auto()
    green = auto()
知道为标准库选择的实现花费了大量的人力和精力,一定有某种原因导致前面演示的声明性枚举的更具Python风格的版本不能正常工作


我的问题是,所提出的方法存在哪些问题和故障模式,以及为什么会反对这种方法(或类似的方法)——Python 3.6中包含了
auto
功能?

defaultdict
作为枚举的名称空间有几个陷阱:

  • 除其他枚举成员/方法外,无法访问任何内容
  • 输入错误会创建新成员
  • 丢失保护窗体
    \u EnumDict
    命名空间:
    • 覆盖成员
    • 覆盖方法
    • 较新的
      \u生成
      方法
最重要的是:

  • 这是行不通的
为什么不起作用?
\uuuuuuuuuuuuuuuuuu
不仅可以在名称空间dict上设置属性,名称空间dict本身也可以设置属性,
\uEnumdict
可以:
\uMember\uNames
,一个应该是成员的所有属性的列表

但是,声明一个没有值的名称的目标并非不可能——1包允许它有一些保护措施:

  • 魔法自动行为仅在定义成员时出现(一旦定义了普通方法,它就会关闭)
  • 默认情况下,
    property
    classmethod
    staticmethod
    被排除在外,但可以包括它们和/或排除其他全局名称
这种行为被认为对stdlib来说太神奇了,因此如果您想要它,以及其他一些增强/改进2,您必须使用
aenum

例如:

from aenum import AutoEnum

class Color(AutoEnum):
    red
    green
    blue
尽管如此,
\uuu repr\uuu
仍然显示创建的值

--

1披露:我是,和图书馆的作者

2
NamedConstant
(就像上面说的;),
NamedTuple
(基于元类、默认值等),以及一些内置枚举:

  • 多值枚举
    -->多个值可以映射到一个名称(而不是别名)
  • NoAliasEnum
    -->具有相同值的名称不是别名(想想扑克牌)
  • orderedum
    -->根据定义,成员的顺序是可比较的
  • uniquenum
    -->不允许使用别名

您可能对使用多个参数创建枚举感兴趣:

from enum import Enum

class NoValue(Enum):
    def __repr__(self):
        return '<%s.%s>' % (self.__class__.__name__, self.name)

Color = NoValue('Color', ['red', 'green', 'blue'])  # no need for "auto()" calls

但是对于
enum
它们应该被解释为赋值吗?这个用例根本没有被考虑。

很有趣,谢谢!我刚刚简单地浏览了一下
AutoEnum
的实现,但它很快就深入到了
\u generate\u next\u value\u
的内容中。公平地说,元类使用了与我的问题中描述的相同的基本技巧,还是完全不同的实现?@wim:Similar:
defaultdict
使用了
\uuuu missing\uuu
方法,而
\u EnumDict
捕获
\uu getitem\uuuuuuuu
查找并从那里处理它。@wim:aenum
中的一系列复杂性支持Python 2.x系列。几天前,我打开了
Enum
的stdlib版本,感觉就像呼吸了一口新鲜空气!Hm,在文档中没有一个引用到
aenum
。对于那些希望获得更神奇的东西的用户来说,这似乎是一个很好的参考。@JimFasarakisHilliard:Python文档没有引用外部项目的习惯(我相信只有几个例外)。也许是维基,虽然…是的,我知道功能界面(我不喜欢它)。。。这就是为什么问题的开头是:“Python枚举的声明性用法…”+1获取相关讨论的链接
class A(object):
    a