Python 食谱 recipe9.14 讨论

Python Cookbook recipe9.14 Discussion

当我阅读 Python Cookbook recipe 9.14 讨论时,它说我必须在制作最终的 class 对象时将 OrderedDict 转换为字典实例。我必须这样做还是使用 OrderedDict 可以?

我试过了,将 OrderedDict 传递给类型构造函数,它没有引发任何异常

class OrderedMeta(type):
    def __new__(cls, clsname, bases, attr_dict):
        order = []
        for name, value in attr_dict.items():
            if isinstance(value, Typed):
                value._name = name
                order.append(name)
        attr_dict['_order'] = order
        return type.__new__(cls, clsname, bases, attr_dict)

    @classmethod
    def __prepare__(cls, clsname, bases):
        return OrderedDict()

书中的代码

class OrderedMeta(type):
    def __new__(cls, clsname, bases, attr_dict):
        d = dict(attr_dict)
        order = []
        for name, value in attr_dict.items():
            if isinstance(value, Typed):
                value._name = name
                order.append(name)
        d['_order'] = order
        return type.__new__(cls, clsname, bases, d)

    @classmethod
    def __prepare__(cls, clsname, bases):
        return OrderedDict()

enter image description here

你必须这样做,出于某些原因,David Beasley 没有进一步详细说明

"it may cause problems if you don't"

在他的 2013 tutorial Python 3 Metaprogramming 中,大约 1 小时 30 分钟。

自该教程以来,python 3.6 引入了保留其顺序的词典,因此您可以安全地忽略此食谱中 ordereddict 的使用。

不,不需要。

type.__new__ 可以采用任何映射 - 甚至可能使用比完整映射协议更少的方法 - __iter____len____getitem__ 就足够了。

这可能是有效的,因为 Python 3.0 - 食谱的作者简单地使用了 "safe road",因为他不确定将 non-native dict 传递给 type.__new__ 并在 OrderedDict 上调用 dict 无论如何都是一行简单的代码。

但是允许在 __prepare__ 中使用任何自定义映射然后不在 type.__new__ 上接受相同的映射没有多大意义 - 也就是说,你甚至不如果您只需要自定义映射,则需要在您的 metaclass 上使用 __new__ 方法 - 只需 __prepare__ 方法。

就是说,这个特殊的配方现在已经过时了,因为 Python 3.6 中使用的词典在 class 中默认排序(并且从 Python 3.7 开始,所有 Python字典默认排序)。