0

CPython doesn't recognize the following argument:

type.__subclasscheck__(object)
# gives us: TypeError: __subclasscheck__() takes exactly one argument (0 given)

type.__subclasscheck__(object, object) # works fine
# give us: True

Why does it behave so?

PS: Using Python3 on Debian 10

Daniel Bandeira
  • 360
  • 1
  • 2
  • 12
  • 1
    The suggest duplicate is not directly related to my question! – Daniel Bandeira Aug 26 '21 at 17:10
  • 1
    I don't really get the question. __subclasscheck is usually implemented to check one object against another. Calling it with ine argument really makes no sense. This is what ´TypeError: __subclasscheck__() takes exactly one argument (0 given)´ tells you as well. –  Aug 27 '21 at 09:04
  • "__subclasscheck__() takes exactly one argument (0 given)". This doesn't make sense because I passed a argument. I am thinking now... Being type a metaclass. (a parent object, would like to mean), the method could work differently from the others. Anyway, the interpreter responses in a not correct way. – Daniel Bandeira Aug 27 '21 at 12:59
  • It works just like other methods. `type.__subclasscheck__` is an unbound method, so you either need to call it on an instance, like: `object.__classcheck__(...)` or pass `self` explicitly: `type.__subclasscheck__(object, ...)`. – Jasmijn Aug 27 '21 at 13:43
  • object.__subclasscheck__(type). Try it. Perhaps will you get the point I'm trying to show you. – Daniel Bandeira Aug 27 '21 at 14:09
  • 1
    If I do `object.__subclasscheck__(type)` cython compiles fine –  Aug 29 '21 at 20:39
  • But type.__subclasscheck__(object) didn't. (python3). This is the point. – Daniel Bandeira Aug 29 '21 at 22:56

1 Answers1

1

type is not a regular class. It is the metaclass of all classes in python. That means that class methods like mro() or __subclasscheck__() are defined as regular methods on the type metaclass, and can be used as bound methods only on instances of that metaclass, i.e. all python classes except for type itself.

For example, let's experiment with the classes int and object. First, let's make it clear that type is the metaclass of both classes:

isinstance(object, type)  # True
isinstance(int, type)     # True
issubclass(object, type)  # False
issubclass(int, type)     # False

But, as int inherits from object, it is a subclass of object:

issubclass(int, object)  # True

Now, what is __subclasscheck__()?

type(type.__subclasscheck__)    # method_descriptor
type(object.__subclasscheck__)  # builtin_function_or_method
str(inspect.signature(type.__subclasscheck__))    # (self, subclass, /)
str(inspect.signature(object.__subclasscheck__))  # (subclass, /)

So, __subclasscheck__() is a method of type, which means when used as type.__subclasscheck__ it will be unbound, and when used as X.__subclasscheck__ it will be bound to the class X.

Knowing that, you could probably figure out the right way of using __subclasscheck__():

# As an unbound method:
type.__subclasscheck__(object, int)  # True
# As a bound method:
object.__subclasscheck__(int)        # True

Note that both ways are logically equal.

It is also worth noting that if you actually want to check if a class is a subclass of another, you should just be using the builtin function issubclass.

kmaork
  • 5,722
  • 2
  • 23
  • 40