Когда я прочитал обсуждение рецепта 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()
Вы должны сделать это по некоторым причинам, которые Дэвид Бизли не уточнил дальше, чем сказал, что
"it may cause problems if you don't"
в его Учебник 2013 г. Python 3 Metaprogramming, около 1 часа 30 минут.
Поскольку в этом руководстве в Python 3.6 появились словари, которые сохраняют свой порядок, вы, вероятно, можете смело игнорировать использование ordereddict
для этого рецепта.
Добро пожаловать, я рад, что смог помочь; действительно, Дэвид Бизли не уточняет причины. Если вы считаете, что мой ответ помог вам, вы можете рассмотреть что делать, когда кто-то отвечает на мой вопрос и как принять мой ответ
Нет, это не нужно.
type.__new__
может принимать любое сопоставление - возможно, даже с меньшим количеством методов, чем протокол полного сопоставления - __iter__
, __len__
и __getitem__
должно быть достаточно.
Это, вероятно, верно, начиная с Python 3.0 - автор рецепта просто выбрал «безопасную дорогу», поскольку он не был уверен, что может произойти, если неродной dict будет передан в type.__new__
, а вызов dict
в OrderedDict — это простая строка кода. в любом случае.
Но не имело бы особого смысла разрешать использование любого пользовательского сопоставления в __prepare__
, а затем не принимать это же сопоставление в type.__new__
. То есть вам даже не нужен метод __new__
в вашем метаклассе, если все, что вам нужно, это пользовательское сопоставление - просто метод __prepare__
.
Тем не менее, этот конкретный рецепт сейчас в любом случае устарел, поскольку словари Python 3.6, используемые при построении классов, упорядочены по умолчанию (а начиная с Python 3.7 все словари Python упорядочены по умолчанию).
спасибо, вы очень ясно выразились, не могли бы вы взглянуть на еще один мой вопрос?связь
спасибо, что касается того, как я смотрю видео, он не доказал, что неправильное использование словаря приведет к сбою программы или любому сообщению об ошибке, точное время 1:35:25, еще раз, спасибо за ответ на мой вопрос