TypeError:type()需要1或3个参数

Zer*_*ays 5 python

我有一个TypeClass来制作类:

class MyMetaClass(type):

    def __new__(cls, *args, **kwargs):
        print('call __new__ from MyMetaClass.')
        return type(cls.__name__, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

但是在使用时:

Foo= MyMetaClass('Foo', (), {'name':'pd'})
Run Code Online (Sandbox Code Playgroud)

提出错误:

TypeError: type() takes 1 or 3 arguments
Run Code Online (Sandbox Code Playgroud)

如果改变它:

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

它会起作用!哪里有问题?

Mar*_*ers 6

__new__方法通过3个位置参数args; 类名,基类和类体.该cls参数绑定到元类,所以MyMetaClass在这里.

您正在为该序列添加另一个名称; 删除名称,或从中删除第一个参数args:

class MyMetaClass(type):
    def __new__(cls, *args, **kwargs):
        print('call __new__ from MyMetaClass.')
        return type(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

要么

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

cls参数是元类对象然而,所以除非你想所有的类被称为MyMetaClass我与第一个选项棒.

请参阅Python数据模型的Customizing类创建部分:

这些步骤必须在元类的__new__()方法中执行 - type.__new__()然后可以从此方法调用以创建具有不同属性的类.此示例在创建类之前向类字典添加新元素:

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

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
...
Run Code Online (Sandbox Code Playgroud)