type其实是一个类,而且是极为特殊的类,叫做元类(metaclass)。元类是Python黑魔法——元编程的关键组成部分。我们知道,Python中任何东西都是对象,那么自然也包括类本身,称为“类对象”。一个普通的类是产生对象的“模板”,调用这个类的构造方法生成的是这个类的对象。同理,一个元类是产生类的“模板”,调用元类的构造方法生成的是类对象。Python中的任何类都是type类的对象。

type其实有两种调用方式:type(object),这种用法是我们常见的,接受一个object对象,返回该对象的类型
type(name, bases, dict),这种用法就是元编程的黑魔法了,它接受三个参数:
name:类名
bases:这个类的mro继承链,也就是它的父类元组
dict:这个类的属性字典
返回一个类对象,也就是创建了一个名为name的类。
例如,定义一个简单的类Person,使用name和age两个属性来初始化:
class Person:
def __init__(self, name, age):
 = name
self.age = age
def __str__(self):
return '%s of age %d' % (, self.age)
tom = Person('Tom', 20)
print(tom)
其实和以下代码完全等价:
def Person_init(self, name, age):
 = name
self.age = age
def Person_str(self):
return '%s of age %d' % (, self.age)
Person = type('Person', (object,), {'__init__': Person_init, '__str__': Person_str})
tom = Person('Tom', 20)
print(tom)

至于为什么type可以像函数一样调用,是因为它实现了__call__方法。任何实现了__call__方法的类,都可以用对象()的形式来调用它的对象,就像一个函数一样。这样的类叫做仿函数(functor)。仿函数是函数式编程中经常用到的一种技巧。在Python中,函数,仿函数和lambda表达式等合称可调用对象(callable)。可以用内建函数callable(obj)来判断一个对象obj是否是可调用对象。

在cpython中,type类的__call__方法是一个slot-wrapper,所谓slot-wrapper也就是底层C实现的Python包装器,它负责调用C实现的函数。__call__方法的C实现源码位于typeobject.c的type_call函数中。

static PyObject *
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *obj;
PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG /* type_call() must not be called with an exception set,because it can clear it (directly or indirectly) and so thecaller loses its exception */
assert(!_PyErr_Occurred(tstate));
#endif
/* Special case: type(x) should return Py_TYPE(x) */
/* We only want type itself to accept the one-argument form (#27157) */
if (type == &PyType_Type) {
assert(args != NULL && PyTuple_Check(args));
assert(kwds == NULL || PyDict_Check(kwds));
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
if (nargs == 1 && (kwds == NULL || !PyDict_GET_SIZE(kwds))) {
obj = (PyObject *) Py_TYPE(PyTuple_GET_ITEM(args, 0));
Py_INCREF(obj);
return obj;
}
/* SF bug 475327 -- if that didn't trigger, we need 3arguments. But PyArg_ParseTuple in type_new may givea msg saying type() needs exactly 3. */
if (nargs != 3) {
PyErr_SetString(PyExc_TypeError,
"type() takes 1 or 3 arguments");
return NULL;
}
}
if (type->tp_new == NULL) {
_PyErr_Format(tstate, PyExc_TypeError,
"cannot create '%.100s' instances",
type->tp_name);
return NULL;
}
obj = type->tp_new(type, args, kwds);
obj = _Py_CheckFunctionResult(tstate, (PyObject*)type, obj, NULL);
if (obj == NULL)
return NULL;
/* If the returned object is not an instance of type,it won't be initialized. */
if (!PyType_IsSubtype(Py_TYPE(obj), type))
return obj;
type = Py_TYPE(obj);
if (type->tp_init != NULL) {
int res = type->tp_init(obj, args, kwds);
if (res < 0) {
assert(_PyErr_Occurred(tstate));
Py_DECREF(obj);
obj = NULL;
}
else {
assert(!_PyErr_Occurred(tstate));
}
}
return obj;
}

我们可以看到这个函数做了这样几件事:

1.检查参数type是否就是type类本身,如果是才允许以type(x)的形式调用。

这主要是为了解决type类的子类metaclass也可以以metaclass(x)的形式调用的问题,因为凡是继承了type类的类都可以作为元类使用,自然也就继承了__call__方法。

2.如果1成立且可变参数数量nargs为1(即以type(obj)的形式调用),则返回该obj的类对象Py_TYPE(即obj->ob_type成员,每个PyObject都会有一个ob_type成员表示这个对象所属的类),并将类对象的引用计数+1。

3.否则,调用type对象的tp_new方法(即__new__方法,这个方法才是真正创建实例对象的方法,而我们平常认为的构造方法__init__其实是在实例对象创建完成后做一些初始化工作,也就是5),生成一个实例对象obj。对于type类及其子类来说,即以type(name, bases, dict)的形式调用);而对于其他的类(即type类的其他对象),相当于调用该类的构造器生成该类的实例对象。

4.检查生成的实例对象obj的类对象Py_TYPE是否是type类的对象,因为继承type类的子类可以重写__new__方法,返回的可能不是一个type类对象,此时直接返回该obj对象,而不会进行5中的初始化工作。

5.调用obj的类对象的__init__方法,对obj对象进行初始化。

基于以上事实,我们可以得出以下有趣的结论:所有的类都是可调用对象,因为所有的类都是type类的对象(当然,除非你重写了metaclass的__new__方法返回了奇怪的东西),而type类实现了__call__方法。这就意味着type类本身也是一个可调用对象,因为type类也是type类的一个对象。(套娃?笑)

调用一个类的构造器Person('Tom', 20),其实等价于在这个类对象上调用__call__方法Person.__call__('Tom', 20)。

更进一步,调用任何callable对象,其实都等价于调用这个对象所属类的__call__方法。