我注意到了
int.__str__ = lambda x: pass
产生错误。
我可以看到,为什么这是被禁止的。但是怎么样?我可以在“普通”代码中使用它吗?
答案 0 :(得分:4)
为了直接在int
本身和其他内置类型(而不是它们的实例)上设置属性,这种保护发生在type.__setattr__
中,它明确禁止在内置类型上设置属性:
static int
type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
{
int res;
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(
PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'",
type->tp_name);
return -1;
}
...
Py_TPFLAGS_HEAPTYPE
是一个标志,指示是否在Python中定义了类型而不是C。
你不能用自己的类做同样的事情,除非你用C实现它们。你可以通过编写一个带有自定义__setattr__
的元类来假装这样做,但这会使得使用其他有用的元类更多很复杂,它仍然不会阻止有人直接在你的课堂上调用type.__setattr__
。 (使用object.__setattr__(int, ...)
尝试类似的技巧并不起作用,因为有specific check可以捕获它。)
您没有询问内置类型的实例,但它们也很有趣。大多数内置类型的实例都不能设置属性,因为没有地方可以放置这些属性 - 没有__dict__
。而不是有一个特殊的"没有设置允许" __setattr__
,或缺少__setattr__
,他们通常会从__setattr__
继承object
,其中knows how to handle个对象没有__dict__
:
descr = _PyType_Lookup(tp, name);
if (descr != NULL) {
Py_INCREF(descr);
f = descr->ob_type->tp_descr_set;
if (f != NULL) {
res = f(descr, obj, value);
goto done;
}
}
if (dict == NULL) {
dictptr = _PyObject_GetDictPtr(obj);
if (dictptr == NULL) {
if (descr == NULL) {
PyErr_Format(PyExc_AttributeError,
"'%.100s' object has no attribute '%U'",
tp->tp_name, name);
}
else {
PyErr_Format(PyExc_AttributeError,
"'%.50s' object attribute '%U' is read-only",
tp->tp_name, name);
}
goto done;
}
...