python - 如何防止内置类型被覆盖(分配给)它们的方法?

标签 python built-in-types

我注意到了

int.__str__ = lambda x: pass

产生错误。

我明白了,为什么这是被禁止的。但是怎么办?我可以在“正常”代码中使用它吗?

最佳答案

为了直接在 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__ >,其中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;
    }
    ...

关于python - 如何防止内置类型被覆盖(分配给)它们的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50118488/

相关文章:

python - 使用 type() 信息来转换存储为字符串的值

python - 获取数据中的 Pandas 系列索引

python - 计算字符串出现次数的最快方法

python - 如何使用 Insert/Modify/Remove 将 dynamodb 设计为 Elastic search

python - 通过聚合函数过滤 Pandas 数据框?

python - 在 3 channel 阵列上创建 numpy 掩码阵列永远行不通

c++ - 原始内置类型初始化

c++ - new[] 是否初始化一个内置数组?

c++ - 0 C++ 内置类型的初始化