4 ms·
Looking in the implementation of the Python version of ABC[0], you'll see that `__subclasshook__` doesn't do any language magic, it just registers the method to
by w-m 4y ago
Looking in the implementation of the Python version of ABC[0], you'll see that `__subclasshook__` doesn't do any language magic, it just registers the method to be called in `__instancecheck__`. So if you just implement `__instancecheck__` directly, you get the same behavior, but without the caching around it.
class OneWayMeta(type):
seen_classes = set()
@classmethod
def __instancecheck__(cls, instance):
C = instance.__class__
print(f"trying {C}")
if C in cls.seen_classes:
return False
cls.seen_classes |= {C}
return True
class OneWay(metaclass=OneWayMeta):
pass
def f(x):
match x:
case OneWay():
print(f"{x} is a new class")
case _:
print(f"we've seen {x}'s class before")
if __name__ == "__main__":
f("abc")
f([1, 2, 3])
f("efg")
When running:
trying <class 'str'>
abc is a new class
trying <class 'list'>
[1, 2, 3] is a new class
trying <class 'str'>
we've seen efg's class before
Am I missing a particular point the article is making, or did the author overlook this?
[0]: https://github.com/python/cpython/blob/main/Lib/_py_abc.py https://github.com/python/cpython/blob/main/Lib/_py_abc.py
- Joker_vD 4y ago> if you just implement `__instancecheck__` directly The point of the article is that to override what "isinstance(obj, ClassA)" means one doesn't need to touch ClassA, or any descendants of it, at all.
- nadavr 4y agoCan you help me understand what you mean here? The author manages to make something match `case NotIterable()` by...modifying the `NotIterable(ABC)` class. That's exactly what I would have expected. What you mean by "one doesn't need to touch ClassA, or any descendants of it, at all."?
- w-m 4y agoNot quite! The point of the article is that you don’t need to change the class of obj to override this instance check. If you have a look, ClassA always uses the hook implementation in the examples. And this can be shortened to just using instancecheck.
- cryptonector 4y agoRight, but, what's the problem with that?
- redeyedtreefrog 4y agoI think the point in the first section is that the way ABC instancecheck/subclasshook interacts with pattern matching is surprising for anyone not familiar with ABC. It allows you to check for a match with arbitrary functions, beyond simply checking if an object is an instance of a given type. In the final section where he has issues with caching, I presume he hasn't read about instancecheck, your code would fix his issue.