Есть ли веская причина вызывать type.mro() вместо того, чтобы напрямую перебирать type.__mro__?

Есть ли веская причина вызывать type.mro() вместо того, чтобы напрямую перебирать type.__mro__? Доступ буквально в ~13 раз быстрее (36 нс против 488 нс).

Я наткнулся на него, когда искал кэш type.mro(). Это кажется законным, но это заставляет меня задуматься: могу ли я положиться на type.__mro__ или мне нужно позвонить type.mro()? и при каких условиях я могу обойтись без первого?

Что еще более важно, какой набор условий должен произойти, чтобы type.__mro__ стало недействительным?

Например, когда определяется/создается новый подкласс, который изменяет mro существующего класса, немедленно ли обновляется существующий класс .__mro__? Это происходит при каждом создании нового класса? что делает его частью типа класса? Какая часть? ..или об этом type.mro()?

Конечно, все это предполагает, что type.__mro__ на самом деле является кортежем кэшированных имен, указывающих на объекты в mro данного типа. Если это предположение неверно; тогда что это? (вероятно, дескриптор или что-то в этом роде..) и почему я могу/не могу его использовать?

РЕДАКТИРОВАТЬ: Если это дескриптор, то я хотел бы изучить его магию, так как оба: type(type.__mro__) is tuple и type(type(type).__mro__) is tuple (то есть: вероятно, не дескриптор)

EDIT: не уверен, насколько это актуально, но type('whatever').mro() возвращает список, тогда как type('whatever').__mro__ возвращает кортеж. (Не?) К счастью, добавление к этому списку не меняет __mro__ или последующие вызовы .mro() из/для рассматриваемого типа (в данном случае str).

Спасибо за помощь!


person Inversus    schedule 03.09.2015    source источник


Ответы (1)


Согласно документам:

class.__mro__

Этот атрибут представляет собой кортеж классов, которые учитываются при поиске базовых классов во время разрешения метода.

class.mro()

Этот метод может быть переопределен метаклассом для настройки порядка разрешения методов для его экземпляров. Он вызывается при создании экземпляра класса, и его результат сохраняется в __mro__.

Так что да, ваше предположение о том, что __mro__ является кешем, верно. Если ваш метакласс mro() всегда возвращает одно и то же или если у вас нет метаклассов, вы можете безопасно использовать __mro__.

person fjarri    schedule 03.09.2015