Python Cookbook recipe9.14 Обсуждение - PullRequest
1 голос
/ 31 мая 2019

Когда я читаю обсуждение рецепта 9.14 Python Cookbook, в нем говорится, что мне нужно преобразовать 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()

введите описание изображения здесь

Ответы [ 2 ]

0 голосов
/ 31 мая 2019

Нет, это не нужно.

type.__new__ может принимать любое отображение - возможно, даже с меньшим количеством методов, чем протокол полного отображения - __iter__, __len__ и __getitem__ должно быть достаточно.

Это, вероятно, верно начиная с Python 3.0 - автор рецепта просто выбрал «безопасный путь», так как он не был уверен, что может произойти, если несобственный диктат передается на type.__new__ и вызывает dict на В любом случае OrderedDict - это простая строка кода.

Но не было бы особого смысла разрешать использовать любое пользовательское отображение в __prepare__, а затем не принимать это же отображение на type.__new__ - то есть вам даже не нужен метод __new__ в вашем метаклассе, если все, что вам нужно, это пользовательское отображение - просто метод __prepare__.

Тем не менее, этот конкретный рецепт теперь в любом случае устарел, так как с тех пор словари Python 3.6, используемые при построении классов, упорядочены по умолчанию (а с Python 3.7 все словари Python упорядочены по умолчанию).

0 голосов
/ 31 мая 2019

Вы должны сделать это, по некоторым причинам, которые Дэвид Бизли не уточнил дальше, чем сказать, что

"это может вызвать проблемы, если вы этого не сделаете"

в своем 2013 учебном пособии по метапрограммированию Python 3 , примерно за 1 час и 30 минут.

Поскольку в этом руководстве Python 3.6 представил словари, сохраняющие их порядок, вы можете, вероятно, безопасно игнорировать использование ordereddict для этого рецепта.

...