Python 3 __instancecheck__() 检查某个变量或字面量是否是某个对象的实例

yufei       5 年, 9 月 前       1648

Python 3 isinstance() 函数源码解读 中我们讲解了 isinstance() 的源码,同时也看到在 isinstance() 的末尾使用 __instancecheck__() 属性来检查某个字面量或变量是否是某个对象的实例

也就是说

isinstance(3.14,float)

相当于调用了

float.__instancecheck__(3.14)

所以,是否表示很好奇,__instancecheck__() 是什么鬼? 又是怎么实现的

__instancecheck__()

PEP 3119 有几句话

The primary mechanism proposed here is to allow overloading the built-in functions isinstance() and issubclass(). The overloading works as follows: The call isinstance(x, C) first checks whether C.__instancecheck__ exists, and if so, calls C.__instancecheck__(x) instead of its normal implementation.

翻译如下

这里提出的主要机制是允许重载内置函数 isinstance()issubclass() 函数。 重载的工作原理如下:

调用 isinstance(x,c) 首先检查 C.__instancecheck__() 是否存在,如果存在,则调用 C.__ instancecheck__(x) 而不是其默认实现

但,这句话其实是错的

比如下面的代码

class C:
    def do_stuff(self):
        print('hello')

C.do_stuff(C())

运行结果为 hello

如果按照 PEP 中所说,那么下面的代码则可以用来重写 isinstance() 的实现

class C:
    @classmethod
    def __instancecheck__(cls, x):
        print('hello')


C.__instancecheck__(C())

不用怀疑,这段代码能正常工作,且输出结果是 hello

但如果你使用了 instance() 来判断,那么结果就是大大的惊叹号了,没被调用

class C:
    @classmethod
    def __instancecheck__(cls, y):
        print('hello')


x = C()
isinstance(x, C)

输出结果 True ,对,没有任何输出 hello 的倾向

对了,继续看 PEP ,就会看到如下文件

These methods are intended to be be called on classes whose metaclass is (derived from) ABCMeta

翻译如下

这些方法适用于其元类是 ( 派生自 ) ABCMeta 的类。

悲剧啊,那,我们继续改代码呗

import abc

class MyMeta(abc.ABCMeta):  #A metaclass derived from ABCMeta
    def __instancecheck__(cls, inst):
        print('hello')
        return True

class C(metaclass=MyMeta):  #A class whose metaclass is derived from ABCMeta
    pass


x = C()
C.__instancecheck__(x)

输出结果为 hello,好吧,看起来正常了

如果我们继续使用 isinstance() ,结果又不是了

isinstance(x, C)

输出结果 True ,对,没有任何输出 hello 的倾向

大家知道为什么吗?

如果你不知道的话,那么可以看看开始提到的那篇文章 Python 3 isinstance() 函数源码解读

原因很简单,就是因为 x.__class__ 属性指向的就是 C

>>> x.__class__
<class '__main__.C'>

所以,根本就不会留到调用 __instancecheck__() 方法的时候

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.