TypeError: type () takes 1 or 3 arguments

I have a TypeClass to create a class:

class MyMetaClass(type):

    def __new__(cls, *args, **kwargs):
        print('call __new__ from MyMetaClass.')
        return type(cls.__name__, *args, **kwargs)

but when using:

Foo= MyMetaClass('Foo', (), {'name':'pd'})

raise Error:

TypeError: type() takes 1 or 3 arguments

if you change it as:

class MyMetaClass(type):
    def __new__(cls, *args, **kwargs):
        print('call __new__ from MyMetaClass.')
        return type(cls.__name__, (), {})

he will work okey! where is the problem?

+4
source share
1 answer

The method __new__is passed to 3 positional arguments in args; class name, base classes, and class body. The argument is clsbound to a metaclass, so MyMetaClasshere.

You add another name to this sequence; drop the name or remove the first argument from args:

class MyMetaClass(type):
    def __new__(cls, *args, **kwargs):
        print('call __new__ from MyMetaClass.')
        return type(*args, **kwargs)

or

class MyMetaClass(type):
    def __new__(cls, *args, **kwargs):
        print('call __new__ from MyMetaClass.')
        return type(cls.__name__, *args[1:], **kwargs)

An argument clsis a metaclass object, however, if you do not want all your classes to be named MyMetaClass, I would stick with the first option.

. Python:

metaclasss __new__() - type.__new__() . :

class metacls(type):
    def __new__(mcs, name, bases, dict):
        dict['foo'] = 'metacls was here'
        return type.__new__(mcs, name, bases, dict)

object.__new__ :

__new__() - ( , ), , . - , ( ).

, , ( ).

:

>>> class MyMetaClass(type):
...     def __new__(cls, *args, **kwargs):
...         print('call __new__ from MyMetaClass.')
...         return type(*args, **kwargs)
... 
>>> class Foo(object):
...     __metaclass__ = MyMetaClass
... 
call __new__ from MyMetaClass.
>>> Foo
<class '__main__.Foo'>
>>> class MyMetaClass(type):
...     def __new__(cls, *args, **kwargs):
...         print('call __new__ from MyMetaClass.')
...         return type(cls.__name__, *args[1:], **kwargs)
... 
>>> class Foo(object):
...     __metaclass__ = MyMetaClass
... 
call __new__ from MyMetaClass.
>>> Foo
<class '__main__.MyMetaClass'>
>>> # Note the  ^^^^^^^^^^^^ class.__name__ attribute here
...
+6
source

Source: https://habr.com/ru/post/1606262/


All Articles