python - 为什么不调用 __instancecheck__?

标签 python python-3.x class python-3.6 metaclass

我有以下 python3 代码:

class BaseTypeClass(type):
    def __new__(cls, name, bases, namespace, **kwd):
        result = type.__new__(cls, name, bases, namespace)
        print("creating class '{}'".format(name))
        return result

    def __instancecheck__(self, other):
        print("doing instance check")
        print(self)
        print(other)
        return False


class A(metaclass=BaseTypeClass):
    pass

print(type(A))
print(isinstance(A(), A))

当我在 Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32 上运行时我得到以下输出

creating class 'A'
<class '__main__.BaseTypeClass'>
True

为什么不输出 doing instance checkdocumentation__instancecheck__ 方法需要在元类上定义,而不是类本身,我已经在这里完成了。自 creating class 'A' 被打印以来,我什至验证元类正在被使用。但是,当我调用 isinstance 时,它似乎使用的是默认实现,而不是我在元类中定义的实现。

我可能没有正确使用元类,但我想不出我在哪里犯了错误。

最佳答案

isinstance 函数快速检查作为参数提供的实例类型是否与类的类型相同。如果是这样,它会提前返回并且不会调用您的自定义 __instancecheck__

这是一种优化,用于避免在不需要时对 __instancecheck__(它是 Pythonland 代码)的昂贵调用。

你可以看到 specific test in PyObject_IsInstance ,在 CPython 实现中处理 isinstance 调用的函数:

/* Quick test for an exact match */
if (Py_TYPE(inst) == (PyTypeObject *)cls)
    return 1;

当然,当该测试不是True 时,您的__instancecheck__ 会正确触发:

>>> isinstance(2, A)
doing instance check
<class '__main__.A'>
2
False

我不确定这是否是特定于实现的,不过我会这么认为,因为在 the corresponding PEP section 中没有提到它也不在关于 isinstance 的文档中。


有趣的是:issubclass 实际上并不是这样的。由于它的实现,它总是调用 __subclasscheck__。我打开了an issue不久前,这仍然悬而未决。

关于python - 为什么不调用 __instancecheck__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47740953/

相关文章:

python - 如何为 pandas groupby 设计 agg 函数

python - 从 Instagram 中提取关注者数量

Python Tkinter Tk root.after 延迟

java - 为什么一个final类不能被继承,一个final方法却可以被继承?

jQuery 按类获取元素

java - 动态创建和读取java类

python - 如何使用 OpenAI 最大上下文长度为 2049 个 token ?

python - 如何提高 scapy 读取大文件的性能

python - 如何将正则表达式与 pandas series.find 函数一起使用

python - 将整数列表、数字字符串转换为整数列表