在python中实例化元类

在python中实例化元类,python,metaclass,Python,Metaclass,我用python编写了一个类,它继承了type。我认为这是类作为元类调用的唯一要求,但没有为它定义一个\uuuu新的方法。但是在将这个新类作为元类实例化时,我得到了一个错误,说明如下: TypeError: type.__new__() takes exactly 3 arguments (0 given) 以下是我的代码: class a(type) : pass c= a() 现在,在处理class语句时,调用type的\uuuu new\uuuu方法是我的假设。这是因为pyt

我用python编写了一个类,它继承了
type
。我认为这是类作为元类调用的唯一要求,但没有为它定义一个
\uuuu新的方法。但是在将这个新类作为元类实例化时,我得到了一个错误,说明如下:

TypeError: type.__new__() takes exactly 3 arguments (0 given)
以下是我的代码:

class a(type) :
    pass 
c= a()
现在,在处理class语句时,调用
type
\uuuu new\uuuu
方法是我的假设。这是因为python中所有类的默认元类都是
type

现在,当我实例化类
a
,我假设从(
type
)继承的任何类都是元类,那么我假设它是元类,这与创建类不一样吗?为什么这不应该导致使用正确的参数调用
type.\uuuuu new\uuuu

这不起作用:

class a(type) :
    pass 
c = a()
c = type()
…与此不起作用的原因相同:

class a(type) :
    pass 
c = a()
c = type()
最后,两者都做了同样的事情

要将其用作元类,请执行以下操作:

>>> class Class(metaclass=a):
...     pass
...
>>> Class
<class '__main__.Class'>
>>> type(Class)
<class '__main__.a'>

此错误是由于您不尊重
类型
的签名造成的

类型继承
对于一个类作为元类使用来说确实足够了,但问题是您实际上必须将它作为元类使用

type
本身有“两种工作模式:如果用3个位置参数调用,它将创建一个新类。然后type是该类的元类。如果用1个位置参数调用,它将不创建任何新类或对象-相反,它只返回该对象的类

但是调用
type
而不带任何参数是没有意义的。而且上述模式中的参数不是可选的。因此,如果您尝试调用type而不带任何参数,您将得到
TypeError
,而这不是“TypeError,因为type类出了问题”-这是一个TypeError,因为您的呼叫与可呼叫的签名不匹配”

当您从
类型继承而不做任何更改时,您的类的行为将与原始
类型的行为完全相同:您可以使用一个或三个位置参数调用它,并且负责在任一模式下工作的代码位于
类型中。\uuuu new\uuuu

现在,如果你想将你的类用作元类,你确实可以调用它,但是以三个参数的形式:你给它命名新的类名,它的基和它的属性-实际上可以都是空的,但是你必须传递一个字符串,一个元组和一个字典作为这三个参数:

AnotherClass = type('AnotherClass', (), {})

YetAnotherClass = a('YetAnotherClass', (), {})
class A(type): pass

myclass = A("", (), {})
现在,
A
作为
myclass
的元类工作:

In [16]: type(myclass)                                                                                   
Out[16]: __main__.A
但是,每当定义元类时,在声明类主体时,更常见的做法是将其与
metaclass=
命名参数一起使用:

In [17]: class  MyOtherClass(metaclass=A): 
    ...:     pass 
    ...:                                                                                                 

In [18]: type(MyOtherClass)                                                                              
Out[18]: __main__.A
Python的运行时将编译这个类主体,当执行它的字节码时,它将调用您的元类“
\uuuu new\uuuu
(然后是
\uuuu init\uuuu
,在此之前它的
\uuu prepare\uuuu
)方法,以便它作为元类工作


因此,以防万一不清楚:当您从
type
派生一个类,打算将其用作元类时,就不需要进一步实例化它来表示“它现在是一个元类”“”类型的子类已经可以是元类,其实例将是类,这些类将把它作为元类

@zvzone:在这里的第二个示例中,您正在调用类型类的init,它隐式地调用新方法,对吗?@itpdusra
\uuuuuuu init\uuuuuuuuuu
不调用
\uuuuuuu new\uuuuuuuuuu
。在构造实例时,首先调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,然后调用
\uuuuuuuuuuuuuuu
<代码>\uuuuuuuuuuuuuuuuu
创建一个新实例,并对其进行初始化。换句话说,
\uuu new\uuu
的结果作为
self
传递给
\uuuu init\uuu
。请参阅了解更多详细信息。我想确定的是,在第二行实例化中,您是否调用metaclass@itpdusra我懂了。在类定义的最后一行之后调用元类构造函数,即在
类类(元类=a)之后:
传递
。尝试在
\uuuuu new\uuuuu
\uuuuu init\uuuuu
中使用
print
s创建元类,然后查看它们的打印时间。这里可能存在x-y问题。通常,如果我们遇到实际需要的问题,元类的需求就会自然产生。在这种情况下,我们将很好地了解它们是什么——事实似乎并非如此。你想用元类实现什么?