0

通过定义__instancecheck__()类元类的特殊方法,可以控制对象何时作为该类的成员进行测试。如果您有一个预定义的类 P(例如,一个内置类),并且您想有条件地控制您的 C 类的给定实例是否作为 P 类型的对象进行测试,该怎么办?这可以做到吗?

这是一个愚蠢的例子:

class C:
    def __init__ (self, x, y):
        self.x = x
        self.y = y

假设我希望 C 作为 class 的对象进行测试numbers.Number,但前提是x > yy % 3 == 0。(我说这将是一个愚蠢的例子。)

from numbers import Number
assert isinstance(C(4, 3), Number)
assert not isinstance(C(1, 3), Number)
assert not isinstance(C(4, 2), Number)

这可以做到吗?如何?

4

1 回答 1

1

该方法__instancecheck__()是在您要测试实例的类上定义的——在本例中是 class numbers.Number。这个类abc.ABCMeta用作它的元类(参见源代码)。该机制ABCMeta提供了添加更多应该被视为类实例的类的方法是register()方法。要准确实现您的要求,您必须将元类替换为该覆盖numbers.Number的一些自定义子类,以提供您想要的功能。这在 CPython 中可以通过将新类分配给 来实现,但不能保证在其他 python 实现中也能正常工作。ABCMeta__instancecheck__()numbers.Number.__class__

import abc
import numbers

class C(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def is_number(self):
        return self.x > self.y and not self.y % 3

class NumberMeta(abc.ABCMeta):
    def __instancecheck__(self, obj):
        if type(obj) is C:
            return obj.is_number()
        return abc.ABCMeta.__instancecheck__(obj)

numbers.Number.__class__ = NumberMeta

assert isinstance(C(4, 3), Number)
assert not isinstance(C(1, 3), Number)
assert not isinstance(C(4, 2), Number)

也就是说,实际上做这样的事情似乎是一个糟糕的主意。为什么你认为你需要这个?

于 2013-08-18T21:29:50.257 回答