Я прочитал этот отличный пост , пытаясь лучше понять метаклассы, и столкнулся с некоторым поведением, которое меня смущает.
Настройка
class AMeta(type):
# Disclaimer: this is not what a real-world metaclass __call__ should look like!
def __call__(self, *args):
print("AMeta.__call__, self = {}, args = {}".format(self, args))
class A(metaclass=AMeta):
def __call__(self, *args):
print("A.__call__, self = {}, args = {}".format(self, args))
Вопрос 1
A.__call__(1, 2)
печать A.__call__, self = 1, args = (2,)
.
Аргументы перенаправляются напрямую (1 появляется на месте себя), поэтому он появляетсяМеханизм дескриптора не запускается. На основании этих правил поиска это может быть связано с тем, что AMeta.__call__
является дескриптором без данных (и поэтому не имеет приоритета над A.__call__
), или это может быть потому, что __call__
является магическим методом, которыйпоэтому, учитывая какой-то особый прямой поиск со стороны переводчика.
Я не уверен, какая из этих двух гипотез верна, если тоже. Если кто-нибудь знает ответ, я был бы признателен за это!
Вопрос 2 A(1, 2)
печать AMeta.__call__, self = <class '__main__.A'>, args = (1, 2)
.
Вызывается __call__
метакласса, который соглашаетсяс изображением здесь из AMeta
__call__
, являющимся хозяином марионеток при создании A
экземпляров.
Почему метакласс __call__
вызывается здесь? Какое правило поиска действует при вызове A(1, 2)
в стиле конструктора? Ясно, что A(1, 2)
- это не просто синтаксический сахар для A.__call__(1, 2)
.
Я видел ряд других вопросов, которые танцуют вокруг этих вопросов, но ни один из них не отвечает на них напрямую.
Iиспользую / занимаюсь Python 3.7 +.