I have a TypeClass to make Class:
class MyMetaClass(type):
def __new__(cls, *args, **kwargs):
print('call __new__ from MyMetaClass.')
return type(cls.__name__, *args, **kwargs)
but when use it :
Foo= MyMetaClass('Foo', (), {'name':'pd'})
raise Error :
TypeError: type() takes 1 or 3 arguments
if Change it like :
class MyMetaClass(type):
def __new__(cls, *args, **kwargs):
print('call __new__ from MyMetaClass.')
return type(cls.__name__, (), {})
it will works okey ! where is problem ?
The __new__
method is passed 3 positional arguments in args
; the class name, the baseclasses and the class body. The cls
argument is bound to the metaclass, so MyMetaClass
here.
You are adding another name to that 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)
The cls
argument is the metaclass object however, so unless you want all your classes to be called MyMetaClass
I'd stick with the first option.
See the Customizing class creation section of the Python data model:
These steps will have to be performed in the metaclass’s
__new__()
method –type.__new__()
can then be called from this method to create a class with different properties. This example adds a new element to the class dictionary before creating the class:class metacls(type): def __new__(mcs, name, bases, dict): dict['foo'] = 'metacls was here' return type.__new__(mcs, name, bases, dict)
and the object.__new__
documentation:
__new__()
is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class).
where class of which an instance was requested is your metaclass (producing a class object).
Demo:
>>> 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
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With