Как я могу вызвать __call__ метакласса?

#python #class #call #metaclass

#python #класс #вызов #метакласс

Вопрос:

Приведен следующий пример для экземпляра X класса:

 class X():

    def __call__(self, incoming_list):
        print incoming_list

X()([x for x in range(10)])
 

Как я могу получить тот же результат, используя __call__ магический метод из самого класса вместо экземпляра? Пример:

 X([x for x in range(10)]) 
 

Вызывая напрямую, как будто переходя к __init__ . Но, прежде чем он вызовет __call__ эти вызовы __new__ , которые передают аргументы __init__ . Как я могу получить доступ к этому «метаклассу __call__ «? Возможно ли это?

Просто чтобы было легче понять, это дает мне тот же результат оттуда:

 class X:

    def __call__(self, incoming_list):
        print incoming_list

X().__call__([x for x in range(10)])
 

Я хочу что-то вроде этого:

 class X:

    def X.__call__(incoming_list): # Syntax Error
        print incoming_list

X.__call__([x for x in range(10)])
 

Комментарии:

1. где ваш метакласс?

2. Я не понимаю, чего вы пытаетесь достичь здесь. def foo(xs): print(xs); foo([x for x in range(10]); Действительно, что вы делаете со всеми этими волшебными вещами?

3. … вы пытались на самом деле использовать метакласс, а не просто случайно упомянуть его в вопросе?

4. «Если вы не знаете, что такое метаклассы, вероятность того, что они вам не понадобятся, составляет 99%».

5. Класс не имеет a __call__ , который вы можете переопределить. Вызывается конструктор классов __new__ .

Ответ №1:

Я думаю, вы считаете слишком сложным.

Возможно, вы хотите что-то вроде

 class X:
    def __init__(self, incoming_list):
        self.data = incoming_list # to keep them for later, if needed
        print incoming_list

X([x for x in range(10)])
 

Все без метакласса, только по определению класса.

Если вам нужен мета-класс, вы можете сделать это следующим образом

 class MC(type):
    def __call__(self, *a, **k):
    super(MC, self).__call
        print a, k
        r = super(MC, self).__call__(*a, **k)
        print "R", r
        return r

class X(object):
    __metaclass__ = MC
    def __init__(self, x): print "Init", x
 

Используя его с

 >>> X(1)
(1,) {}
Init 1
R <__main__.X object at 0x00000000022907B8>
<__main__.X object at 0x00000000022907B8>
 

показывает, что вызывается мета- __call__ класс, который, в свою очередь, вызывает __init__ .

Но я уверен, что вам это не нужно и что вы просто хотите __init__ .

Комментарии:

1. Спасибо! Я знаю, что мне это не нужно, мне просто было любопытно, и это было именно то, что я хотел знать.

2. Возможно __new__ , а не __init__ в случае OP.