class method __instancecheck__ does not work

2020-02-05 06:54发布

I am using python 2.7.3 on Windows. I tried to override the __instancecheck__ magic method as a class method. But I can not make it work.

class Enumeration(int):
    @classmethod
    def __instancecheck__(cls, inst):
        if type(inst) == cls:
            return True
        if isinstance(inst, int) and inst in range(0,10):
            return True
        return False

print isinstance(1, Enumeration)   # prints False
print isinstance(1, Enumeration()) # prints True

I assume the first print statement would get True. But it seems the magic method __instancecheck__ is not called. And I don't know why the second print statement can work since the isinstance should take a class/type as the second parameter.

Does anyone know what the problem is? Thanks.

标签: python
2条回答
家丑人穷心不美
2楼-- · 2020-02-05 07:25

instancecheck must be defined in a metaclass:

class Enumeration(type):
    def __instancecheck__(self, other):
        print 'hi'
        return True


class EnumInt(int):
    __metaclass__ = Enumeration

print isinstance('foo', EnumInt) # prints True

Why is that? For the same reason why your second example worked. When python evaluates isinstance(A, B) it assumes B to be an object, looks for its class and calls __instancecheck__ on that class:

isinstance(A, B):
    C = class-of(B)
    return C.__instancecheck__(A)

But when B is a class itself, then its class C should be a class of a class, in other words, a meta-class!

查看更多
看我几分像从前
3楼-- · 2020-02-05 07:32

The docs say:

Note that these methods are looked up on the type (metaclass) of a class. They cannot be defined as class methods in the actual class. This is consistent with the lookup of special methods that are called on instances, only in this case the instance is itself a class.

http://docs.python.org/2/reference/datamodel.html#customizing-instance-and-subclass-checks

查看更多
登录 后发表回答