Message266667
All types are instances of `type`, so the single argument case makes sense to me as a 'constructor'. It always returns an instance of `type`, just not a new instance.
>>> X = type('X', (type,), {})
>>> type(X)
<class 'type'>
>>> isinstance(type(X), type)
True
OTOH, implementing this for subclasses of `type` doesn't generally make sense to me. That this is allowed (sometimes) is I think a mistake:
>>> X(X)
<class 'type'>
>>> isinstance(X(X), X)
False
PyType_CheckExact(metatype) isn't checking that metatype is `type`. It's checking that the type of metatype is exactly `type`, which is true for `type` and immediate instances of type, i.e. normal metaclasses. But it's not the case for a metaclass that's an instance of another metaclass:
>>> Y = X('Y', (X,), {})
>>> Y(Y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type() takes 1 or 3 arguments
Maybe I'm missing something, but it makes more sense to me if metatype is required to be *exactly* `type`, i.e. metatype == &PyType_Type, and that this check is used to gate the entire special case:
/* Special case: type(x) should return x->ob_type */
if (metatype == &PyType_Type) {
const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);
if (nargs == 1 && nkwds == 0) {
PyObject *x = PyTuple_GET_ITEM(args, 0);
Py_INCREF(Py_TYPE(x));
return (PyObject *) Py_TYPE(x);
}
/* SF bug 475327 -- if that didn't trigger, we need 3
arguments. but PyArg_ParseTupleAndKeywords below may give
a msg saying type() needs exactly 3. */
if (nargs + nkwds != 3) {
PyErr_SetString(PyExc_TypeError,
"type() takes 1 or 3 arguments");
return NULL;
}
}
This change yields the following behavior:
>>> X = type('X', (type,), {})
>>> type(X)
<class 'type'>
>>> type(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type() takes 1 or 3 arguments
>>> X()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Required argument 'name' (pos 1) not found
>>> X(X)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type() argument 1 must be str, not type |
|
Date |
User |
Action |
Args |
2016-05-30 03:17:17 | eryksun | set | recipients:
+ eryksun, steven.daprano, r.david.murray, ppperry, abarry |
2016-05-30 03:17:17 | eryksun | set | messageid: <1464578237.33.0.0785742202227.issue27157@psf.upfronthosting.co.za> |
2016-05-30 03:17:17 | eryksun | link | issue27157 messages |
2016-05-30 03:17:16 | eryksun | create | |
|