Во-первых, есть ли причина, по которой __prepare__
является методом класса?В определении не используются метаклы - это просто соглашение?
Как указано в комментариях, когда вызывается __prepare__
, сам класс еще не создан.Это означает, что если это обычный метод (с self
в качестве первого параметра) - не будет никакого значения, чтобы стать self
в этом вызове.
И это имеет смысл, потому что __prepare__
делает - возвращает объект, похожий на dict, который будет использоваться вместо обычного dict при разборе тела класса - так что он вообще не зависит от создаваемого класса.
Если, как упомянуто вкомментарии, это был staticmethod
(что означает, что он не получит первый параметр metacls
), тогда __prepare__
не сможет получить доступ к любым другим методам метакласса - это излишне ограничивает.
Ида, точно так же, как self
, metacls
в данном случае это просто соглашение - обычный идентификатор Python.(Обратите внимание, что когда методы классов используются в обычных классах, первый параметр обычно обозначается cls
вместо metacls
.)
Во-вторых, когда я пытаюсь этот код, __module__
заканчиваетсяMyClass.member_names перед method1
и method2
, очевидно противоречащим комментариям, которые утверждают, что method1
является первым элементом.Почему этот специальный атрибут попадает в список, а другие нет?Есть ли другие, которые могут меня удивить (кроме __doc__
, если у класса есть строка документации, и любая, которую я определяю явно)?
Возможно, потому что специальный __module__
член для классов был продуманпосле того, как они подумали о методе __prepare__
для метаклассов.(Я не смог проверить путем поиска в Google для определения PEP __module__
, но я бы поспорил, что это так.)
И нет, нет никаких гарантий, что будущие версии Python не добавят ещемагические атрибуты для классов, которые могут находиться перед вашими явными членами класса в словаре.
Но с метаклассами вы полностью контролируете - вы можете просто настроить свой объект типа dict (member_table
в вашем коде), чтобы несчитать любые атрибуты, начинающиеся с "__" - например.Или даже вообще не добавлять его в конечный экземпляр класса (риск того, что ваши классы, определенные таким образом, не будут работать с некоторыми функциями Python).
Наконец, эта реализация не извлекает имена членов из базыклассы.Если я хочу добиться этого, есть ли что-то не так со следующим изменением на __prepare__
?
Читая его, я не вижу ничего плохого в предложенной вами реализации, но вам придется проверить, конечно.
Обновление (2013-06-30): эта тема активно обсуждается в списке разработчиков Python, и похоже, что из Python 3.4 все классы будут упорядочены по умолчанию, без необходимости использовать метакласс или __prepare__
только для заказа