Date

修改对象从属关系

其实这里想介绍的一个神奇的函数__instancecheck__,它的描述文档在这里

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. Similarly, the call issubclass(D, C) first checks whether C.__subclasscheck__ exists, and if so, calls C.__subclasscheck__(D) instead of its normal implementation.

class MyMeta(type):
    def __instancecheck__(self, other):
        return True

class MyClass(object):
    __metaclass__ = MyMeta


assert isinstance(123, MyClass)

但是因为cpython具体实现的关系,__instancecheck__并不一定会被调用,如下:

class MyMeta(type):
    def __instancecheck__(self, other):
        return False

class MyClass(object):
    __metaclass__ = MyMeta


assert not isinstance(123, MyClass)
assert isinstance(MyClass(), MyClass)

这个问题的答案解释了原因。

可见文档也不一定完全对,代码才是不会骗人的。

修改类继承关系

这里我们用到了__subclasshook__方法,其文档在这里

from abc import ABCMeta
class MyClass(object):
    __metaclass__ = ABCMeta
    @classmethod
    def __subclasshook__(cls, C):
        return False

class MyClass2(MyClass):
    pass

assert not issubclass(MyClass2, MyClass)

另外,和PEP3119文档描述的不一样的是,__isinstancecheck____subclasshook__定义的位置是不同的:

  • 前者是定义在MyClass的meta class里面
  • 后者是定义在MyClass里面,不过MyClass还需要同时设置meta class为abc.ABCMeta或者其子类