【发布时间】:2018-06-21 01:42:07
【问题描述】:
这是关于 Python2.7 中的元类的。
要清楚,代码是这样的:
class MetaC(type):
def __new__(cls, name, bases, attrs):
print "MetaC"
return super(MetaC, cls).__new__(cls, name, bases, attrs)
class MetaB(MetaC):
def __new__(cls, name, bases, attrs):
print "MetaB"
return super(MetaB, cls).__new__(cls, name, bases, attrs)
class MetaA(MetaB):
def __new__(cls, name, bases, attrs):
print "MetaA"
return super(MetaA, cls).__new__(cls, name, bases, attrs)
class A(object):
__metaclass__ = MetaA
print type(A)
class B(A):
__metaclass__ = MetaB
print type(B)
class C(B):
__metaclass__ = MetaC
print type(C)
结果如下:
MetaA
MetaB
MetaC
<class '__main__.MetaA'>
MetaB
MetaC
MetaA
MetaB
MetaC
<class '__main__.MetaA'>
MetaC
MetaA
MetaB
MetaC
<class '__main__.MetaA'>
似乎在创建类C时,MetaA.__new__是在MetaC.__new__之后调用的。
为了弄清楚,我查看了源代码并在typeobject.c中找到:
static PyObject *
type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
{
/* some code is omitted here */
for (i = 0; i < nbases; i++) {
tmp = PyTuple_GET_ITEM(bases, i);
tmptype = tmp->ob_type;
if (tmptype == &PyClass_Type)
continue; /* Special case classic classes */
if (PyType_IsSubtype(winner, tmptype))
continue;
if (PyType_IsSubtype(tmptype, winner)) {
winner = tmptype;
continue;
}
PyErr_SetString(PyExc_TypeError,
"metaclass conflict: "
"the metaclass of a derived class "
"must be a (non-strict) subclass "
"of the metaclasses of all its bases");
return NULL;
}
if (winner != metatype) {
if (winner->tp_new != type_new) /* Pass it to the winner */
return winner->tp_new(winner, args, kwds);
metatype = winner;
}
/* some code is omitted here */
}
for 循环找到最深的子类winner(抱歉我的英语不好,代码可能比我说的要清楚得多)。如果不是metatype,将调用winner->tp_new。这就是我从代码中得到结果的原因。
那么,我想知道的是,为什么要这样设计?是否有任何务实的案例表明这样做的必要性?
另外,我也注意到了错误信息
元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类
显然,在我的例子中,C 的元类 MetaC 不是其基类的任何元类的子类。那么,它是一个非严格的子类吗?这里的“非严格”是什么意思?
【问题讨论】:
-
你为什么仍然使用 Python 2 来研究 Python 的这些高级方面?最新的 Python 2 到现在已经 8 年了,2 年后 EOL。最新版本 (3.6) 可能会更好地提供您想通过元类在“现实世界”中活动的任何内容
标签: python inheritance metaclass cpython