__новые__ ошибки выброса метакласса

#python

#python

Вопрос:

Я тестирую использование метакласса и застрял при создании объекта. Новый метод выдает ошибку «отсутствуют 3 требуемых позиционных аргумента»:

 bash-4.4$ python3 sftester.py
Traceback (most recent call last):
  File "sftester.py", line 2, in <module>
    from sorrogatefactory import make_SA_Sorrogate
  File "/home/alelai/anvil9/kafka-client-new/sorrogatefactory.py", line 42, in <module>
    class make_SA_Sorrogate(SA_AddOn, metaclass=SorrogateFactory()):
TypeError: __new__() missing 3 required positional arguments: 'classname', 'supers', and 'classdict'



bash-4.4$ cat sftester.py
from sorrogatefactory2 import SorrogateFactory, make_SA_Sorrogate

if __name__ == '__main__':
    sa_sorrogate = make_SA_Sorrogate()



bash-4.4$ cat sorrogatefactory2.py
class SorrogateFactory(object):

    def __call__(self, classname, supers, classdict):
            print("In __call__")
            print("Making "   classname   " of"   " classname")
            Class = self.__new__(classname, supers, classdict)
            self.__init__(Class, classname, supers, classdict)
            return Class

    def __new__(self, classname, supers, classdict):
            print("In __new__")
            return type(classname, supers, classdict)

    def __init__(self):
            print("In __init__")
            pass


class SA_AddOn(object):
    pass

class make_SA_Sorrogate(SA_AddOn, metaclass=SorrogateFactory()):

    def dumb(slef):
            pass
  

Похоже, что метод _new_(), упомянутый в сообщении об ошибке, не является методом _new_() SorrogateFactory. В чем здесь подвох?

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

1. Что такое make_SA_Sorrogate ? Похоже, вы путаете __new__ метод метакласса (который используется для создания класса) и __new__ метод класса, созданного метаклассом (который создает экземпляр класса).

2. Проверьте эту технологию с помощью видео Тима на YouTube. В котором он объяснил использование new в метаклассе.

3. @GirishDattatrayHegde: хорошее видео. Спасибо

4. @chepner: make_SA_Sorrogate должно быть make_SA_AddOn.

Ответ №1:

Вы должны сделать так, чтобы ваш метакласс наследовался от type вместо object .

 class SorrogateFactory(type):

    def __call__(self, classname, supers, classdict):
        print("In __call__")
        print("Making "   classname   " of"   " classname")
        Class = self.__new__(classname, supers, classdict)
        self.__init__(Class, classname, supers, classdict)
        return Class

    def __new__(self, classname, supers, classdict):
        print("In __new__")
        return type(classname, supers, classdict)

    def __init__(self):
        print("In __init__")
        pass


class SA_AddOn(object):
    pass
  

Кроме того, просто используйте метакласс без скобок, иначе вы будете создавать его экземпляр. Вот почему вы получаете сообщение об ошибке о 3 параметрах.

 class make_SA_Sorrogate(SA_AddOn, metaclass=SorrogateFactory):
    def dumb(slef):
        pass
  

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

1. Первый аргумент __new__ на самом деле является классом, а не экземпляром класса. Хотя то, что у вас есть, верно, я бы написал def __new__(cls, classname, supers, classdict): для ясности.