【问题标题】:Python Cookbook recipe9.14 DiscussionPython Cookbook recipe9.14 讨论
【发布时间】:2019-10-16 16:52:54
【问题描述】:

当我阅读 Python Cookbook recipe 9.14 的讨论时,它说我必须在制作最终类对象时将 OrderedDict 转换为 dict 实例。我必须这样做还是使用 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

【问题讨论】:

    标签: python-3.x class oop metaclass


    【解决方案1】:

    不,不需要。

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

    这可能从 Python 3.0 开始有效 - 配方的作者只是选择了一条“安全之路”,因为他不确定将非本地 dict 传递给 type.__new__ 并在无论如何,OrderedDict 是一行普通的代码。

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

    也就是说,无论如何,这个特定的配方现在已经过时了,因为在类构造中使用的 Python 3.6 字典是默认排序的(从 Python 3.7 开始,所有 Python 字典都是默认排序的)。

    【讨论】:

    • 谢谢,你说的很清楚,介意看看我的另一个问题吗?link
    【解决方案2】:

    你必须这样做,出于某些原因,大卫比斯利没有进一步详细说明,而是说

    “如果不这样做可能会导致问题”

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

    从那个教程开始,python 3.6 引入了保留其顺序的字典,因此,您可能可以放心地忽略在此配方中使用 ordereddict

    【讨论】:

    • 谢谢,就我看视频而言,他并没有证明不使用正确的字典会导致程序崩溃或任何错误信息,确切的时间是1:35:25,再次,谢谢你回答我的问题
    • 不客气,很高兴能帮上忙;事实上,大卫比斯利并没有详细说明原因。如果你觉得我的回答对你有帮助,可以考虑what to do when someone answers my questionhow to accept my answer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2018-12-23
    • 2021-08-24
    • 2016-08-28
    相关资源
    最近更新 更多